phpredis实现点赞,基于redis实现的点赞功能设计思路详解前⾔
点赞其实是⼀个很有意思的功能。基本的设计思路有⼤致两种, ⼀种⾃然是⽤mysql等
数据库直接落地存储, 另外⼀种就是利⽤点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回mysql等。
直接写⼊Mysql
直接写⼊Mysql是最简单的做法。
做两个表即可,
1、post_like
记录⽂章被赞的次数,已有多少⼈赞过这种数据就可以直接从表中查到;
2、user_like_post
记录⽤户赞过了哪些⽂章, 当打开⽂章列表时,显⽰的有没有赞过的数据就在这⾥⾯;
缺点
1、数据库读写压⼒⼤
热门⽂章会有很多⽤户点赞,甚⾄是短时间内被⼤量点赞, 直接操作数据库从长久来看不是很理想的做法。
redis存储随后批量刷回数据库
redis主要的特点就是快, 毕竟主要数据都在内存嘛;
另外为啥我选择redis⽽不是memcache的主要原因在于redis⽀持更多的数据类型, 例如hash, set, zset等。
下⾯具体的会⽤到这⼏个类型。
优点
1、性能⾼
2、缓解数据库读写压⼒
其实我更多的在于缓解写压⼒, 真的读压⼒, 通过mysql主从甚⾄通过加⼊redis对热点数据做缓存都
可以解决,
写压⼒对于前⾯的⽅案确实是不⼤好使。
缺点
1、开发复杂
这个⽐直接写mysql的⽅案要复杂很多, 需要考虑的地⽅也很多;
2、不能保证数据安全性
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
2、写⼊post_user_like_set_{$post_id}
将user_id写⼊post_user_like_set_{$post_id}
3、写⼊post_user_like_{$post_id}_{$user_id}
将⽤户点赞数据, 例如赞状态, post_id, user_id, ctime(操作时间), mtime(修改时间)写⼊post_user_like_{$post_id}_{$user_id}中4、更新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表中页⾯展⽰
1、查询⽤户点赞情况
前⾯已经说过, 需要同时查询redis和mysql
2、查询post点赞统计php修改数据库内容
同样需要查询redis中的post_{$post_id}_counter和mysql的post_like表, 并将两者相加
得到的结果才是正确的结果
总结
解决了mysql读写的问题
但没有针对⽤户量较⼤的场景考虑分表的设计, 可以考虑针对user_id或者post_id进⾏分表

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。