0


Redis实现点赞与关注

目录

一、点赞

直接写入Mysql

直接写入Mysql是最简单的做法。

做两个表即可,

  1. post_like

记录文章被赞的次数,已有多少人赞过这种数据就可以直接从表中查到;

  1. user_like_post

记录用户赞过了哪些文章, 当打开文章列表时,显示的有没有赞过的数据就在这里面;

缺点

  1. 数据库读写压力大 热门文章会有很多用户点赞,甚至是短时间内被大量点赞, 直接操作数据库从长久来看不是很理想的做法。

redis存储随后批量刷回数据库

redis主要的特点就是快, 毕竟主要数据都在内存嘛;

优点

  1. 性能高
  2. 缓解数据库读写压力

其实我更多的在于缓解写压力, 真的读压力, 通过mysql主从甚至通过加入redis对热点数据做缓存都可以解决,写压力对于前面的方案确实是不大好使。

缺点

  1. 开发复杂

这个比直接写mysql的方案要复杂很多, 需要考虑的地方也很多;

  1. 不能保证数据安全性

redis挂掉的时候会丢失数据, 同时不及时同步redis中的数据, 可能会在redis内存置换的时候被淘汰掉;
不过对于我们点赞而已, 稍微丢失一点数据问题不大;

具体设计

Mysql设计

这一块和写入写mysql是一样的,毕竟是要落地存储的。
所以还是同样的需要post_like, user_like_post这两表存储文章被点赞的个数(等统计), 用户对那些文章点了赞(取消赞)。
这两表分别通过

post_id, user_id

进行关联。

redis设计部分:

post_set

在redis中弄一个set存放所有被点赞的文章

post_user_like_set_{$post_id}

对每个post以post_id作为key, 搞一个set存放所有对该post点赞的用户;

post_user_like_{$post_id}_{$user_id}

将每个用户对每个post的点赞情况放到一个hash里面去, hash的字段就

为啥用hash

只所以用hash是因为完全可以用hash来存储一个点赞的对象, 对应数据库的一行记录。

当然有同学会说用key, value也可以, 将所有的数据序列化(json_encode等)

后全部放到value里面去。 反复序列化也是一个很大的开销不是, hash可以很

方便的修改某个字段, 而序列化和反序列化的操作。

post_{$post_id}_counter

对每个post维护一个计数器, 用来记录当前在redis中的点赞数,

这里我们只用counter记录尚未同步到mysql中的点赞数(可以为负), 每次

刷回mysql中时将counter中的数据和数据库已有的赞数相加即可。

用户点赞/取消赞

获取

user_id, post_id

, 查询该用户是否已经点过赞, 已点过则不允许再次点赞,

或者设计为前端允许用户点, 只是后台不重复计算;

这里需要注意的是用户点赞的记录可能在数据库中, 也可能在缓存中, 所以查询的时候

缓存和数据库都要查询, 缓存没有再查询数据库。

将用户的点赞/取消赞的情况记录在redis中, 具体为:

  1. 写入post_set

post_id

写入

post_set
  1. 写入post_user_like_set_{$post_id}

user_id

写入

post_user_like_set_{$post_id}
  1. 写入post_user_like_{$post_id}_{$user_id}

将用户点赞数据, 例如赞状态, post_id, user_id, ctime(操作时间), mtime(修改时间)写入post_user_like_{KaTeX parse error: Expected 'EOF', got '}' at position 8: post_id}̲_{user_id}中

  1. 更新post_{$post_id}_counter

更新

post_{$post_id}_counter,

这里的更新稍晚复杂一点, 需要和前面一样先获取当前用户是否对这个post点过赞

如果点过, 并且本次是取消赞, counter减一, 如果没点过, 本次是点赞, counter加一。

如果原来是取消赞的情况, 本次是点赞, counter加一。

同步刷回数据库

循环从

post_set

pop

出来一个

post_id

至到空

根据

{$post_id}

, 每次从

post_user_like_set_{$post_id}

中pop出来一个user_id直到空

根据

post_id, user_id

, 直接获取对应的hash表的内容

post_user_like_{$post_id}_{$user_id}

将hash表中的数据写入

user_like_post

表中

post_{$post_id}_counter

中的数据和post_like中的数据相加, 将结果写入到post_like表中

二、关注

使用Redis有序集合可以做到根据关注的时间有序的取出列表,假设我的ID是

me

,别人的ID是

other

1、添加关注

  1. 将对方id添加到自己的关注列表中; Redis::ZADD(“me:follow”, time(), other)
  2. 将自己的id添加到对方的粉丝列表中: Redis::ZADD(“other:fans”, time(), me)

2、取消关注

  1. 将对方id从自己的关注列表中移除; Redis::ZREM(“me:follow”, other)
  2. 将自己的id从对方的粉丝列表中移除: Redis::ZREM(“other:fans”, me)

3、 关注列表

  1. 查看我的关注列表: Redis::ZRANGE(“me:follow”, 0 , -1)
  2. 查看别人的把id换掉就可以 Redis::ZRANGE(“other:follow”, 0 , -1)

4、 粉丝列表

  1. 查看我的粉丝列表: Redis::ZRANGE(“me:fans”, 0 , -1)
  2. 查看别人的把id换掉就可以 Redis::ZRANGE(“other:fans”, 0 , -1)

5、人物关系

  1. 我单向关注他
  • 我的关注列表中有他(或他的粉丝列表中有我);
  • 我的粉丝列表中没有他(或他的关注列表中没有我)。

Redis::ZSCORE(“me:fans”, other) #未返回分数
Redis::ZSCORE(“me:follow”, other) #返回分数

  1. 他单向关注我
  • 我的关注列表中没有他(或他的粉丝列表中没有我);
  • 我的粉丝列表中有他(或他的关注列表中有我)。

Redis::ZSCORE(“other:fans”, me) #未返回分数
Redis::ZSCORE(“other:follow”, me) #返回分数

  1. 是否互粉
  • 我的关注列表中有他(或他的粉丝列表中有我);
  • 我的粉丝列表中有他(或他的关注列表中有我)。同时成立才为互粉。

Redis::ZSCORE(“me:fans”, other) #返回分数
Redis::ZSCORE(“me:follow”, other) #返回分数

6、 数量相关

  1. 我的关注数 Redis::ZCARD(“me:follow”); #返回数量
  2. 我的粉丝数 Redis::ZCARD(“me:fans”); #返回数量

7、 排序取出所有的人

  1. 根据关注的时间倒叙取出用户的id Redis::ZREVRANGE(“me:fans”, 0, -1, TRUE); #倒序取值
  2. 根据关注时间顺序取出用户的id Redis::ZRANGE(“me:fans”, 0, -1, TRUE); #顺序取值

!!!欢迎点赞收藏关注!!!

标签: redis 数据库 mysql

本文转载自: https://blog.csdn.net/qq_45911678/article/details/122966183
版权归原作者 一只小逸白 所有, 如有侵权,请联系我们删除。

“Redis实现点赞与关注”的评论:

还没有评论