源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

基于redis实现的点赞功能设计思路详解

  • 时间:2021-01-12 03:43 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:基于redis实现的点赞功能设计思路详解
[b]前言[/b] 点赞其实是一个很有意思的功能。基本的设计思路有大致两种, 一种自然是用mysql等 数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回mysql等。 [b]直接写入Mysql[/b] 直接写入Mysql是最简单的做法。 做两个表即可, 1、[code]post_like[/code] 记录文章被赞的次数,已有多少人赞过这种数据就可以直接从表中查到; 2、[code]user_like_post[/code] 记录用户赞过了哪些文章, 当打开文章列表时,显示的有没有赞过的数据就在这里面; [b]缺点[/b] 1、数据库读写压力大 热门文章会有很多用户点赞,甚至是短时间内被大量点赞, 直接操作数据库从长久来看不是很理想的做法。 [b]redis存储随后批量刷回数据库[/b] redis主要的特点就是快, 毕竟主要数据都在内存嘛; 另外为啥我选择redis而不是memcache的主要原因在于redis支持更多的数据类型, 例如hash, set, zset等。 下面具体的会用到这几个类型。 [b]优点[/b] 1、性能高 2、缓解数据库读写压力 其实我更多的在于缓解写压力, 真的读压力, 通过mysql主从甚至通过加入redis对热点数据做缓存都可以解决, 写压力对于前面的方案确实是不大好使。 [b]缺点[/b] 1、开发复杂 这个比直接写mysql的方案要复杂很多, 需要考虑的地方也很多; 2、不能保证数据安全性 redis挂掉的时候会丢失数据, 同时不及时同步redis中的数据, 可能会在redis内存置换的时候被淘汰掉; 不过对于我们点赞而已, 稍微丢失一点数据问题不大; [b]具体设计[/b] [b]Mysql设计[/b] 这一块和写入写mysql是一样的,毕竟是要落地存储的。 所以还是同样的需要[code]post_like[/code], [code]user_like_post[/code]这两表存储文章被点赞的个数(等统计), 用户对那些文章点了赞(取消赞)。 这两表分别通过[code]post_id[/code], [code]user_id[/code]进行关联。 [b]redis设计部分:[/b] [code]post_set[/code] 在redis中弄一个set存放所有被点赞的文章 [code]post_user_like_set_{$post_id}[/code] 对每个post以post_id作为key, 搞一个set存放所有对该post点赞的用户; [code]post_user_like_{$post_id}_{$user_id}[/code] 将每个用户对每个post的点赞情况放到一个hash里面去, hash的字段就 随意跟进需求来处理就行了。 [b]为啥用hash[/b] 只所以用hash是因为完全可以用hash来存储一个点赞的对象, 对应数据库的一行记录。 当然有同学会说用key, value也可以, 将所有的数据序列化([code]json_encode[/code]等) 后全部放到value里面去。 反复序列化也是一个很大的开销不是, hash可以很 方便的修改某个字段, 而序列化和反序列化的操作。 [code]post_{$post_id}_counter[/code] 对每个post维护一个计数器, 用来记录当前在redis中的点赞数, 这里我们只用counter记录尚未同步到mysql中的点赞数(可以为负), 每次 刷回mysql中时将counter中的数据和数据库已有的赞数相加即可。 [b]用户点赞/取消赞[/b] 获取[code]user_id[/code], [code]post_id[/code], 查询该用户是否已经点过赞, 已点过则不允许再次点赞, 或者设计为前端允许用户点, 只是后台不重复计算; 这里需要注意的是用户点赞的记录可能在数据库中, 也可能在缓存中, 所以查询的时候 缓存和数据库都要查询, 缓存没有再查询数据库。 将用户的点赞/取消赞的情况记录在redis中, 具体为: 1、写入[code]post_set[/code] 将[code]post_id[/code]写入[code]post_set[/code] 2、写入[code]post_user_like_set_{$post_id}[/code] 将[code]user_id[/code]写入[code]post_user_like_set_{$post_id}[/code] 3、写入[code]post_user_like_{$post_id}_{$user_id}[/code] 将用户点赞数据, 例如赞状态, post_id, user_id, ctime(操作时间), mtime(修改时间)写入[code]post_user_like_{$post_id}_{$user_id}[/code]中 4、更新[code]post_{$post_id}_counter[/code] 更新[code]post_{$post_id}_counter[/code], 这里的更新稍晚复杂一点, 需要和前面一样先获取当前用户是否对这个post点过赞 如果点过, 并且本次是取消赞, counter减一, 如果没点过, 本次是点赞, counter加一。 如果原来是取消赞的情况, 本次是点赞, counter加一。 [b]同步刷回数据库[/b] 循环从[code]post_set[/code]中pop出来一个[code]post_id[/code]至到空     根据[code]{$post_id}[/code] , 每次从[code]post_user_like_set_{$post_id}[/code]中pop出来一个[code]user_id[/code]直到空         根据[code]post_id[/code], [code]user_id[/code], 直接获取对应的hash表的内容([code]post_user_like_{$post_id}_{$user_id}[/code]         将hash表中的数据写入[code]user_like_post[/code]表中         将[code]post_{$post_id}_counter[/code]中的数据和[code]post_like[/code]中的数据相加, 将结果写入到[code]post_like[/code]表中 [b]页面展示[/b] 1、查询用户点赞情况 前面已经说过, 需要同时查询redis和mysql 2、查询post点赞统计 同样需要查询redis中的[code]post_{$post_id}_counter[/code]和mysql的[code]post_like[/code]表, 并将两者相加 得到的结果才是正确的结果 [b]总结[/b] 解决了mysql读写的问题 但没有针对用户量较大的场景考虑分表的设计, 可以考虑针对user_id或者post_id进行分表 好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程素材网的支持。
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部