点赞功能与redis
转:https://edu.aliyun.com/a/20538
摘要: 前言点赞其实是一个很有意思的功能。基本的设计思路有大致两种, 一种自然是用mysql等数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回mysql等。直接写入Mysql直接写入Mysql是最简单的做法。做两个表即可,1、post_like记录文章被赞的次数,已有多少人赞过这种数据就可以直接从表中查到;2、user_like_...
前言
点赞其实是一个很有意思的功能。基本的设计思路有大致两种, 一种自然是用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点赞统计
同样需要查询redis中的post_{$post_id}_counter和mysql的post_like表, 并将两者相加
得到的结果才是正确的结果
总结
解决了mysql读写的问题
但没有针对用户量较大的场景考虑分表的设计, 可以考虑针对user_id或者post_id进行分表
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。
以上是互联网用户为您的的内容,在阿里云内部有更多的关于基于redis实现的点赞功能设计思路详解_Redis的内容,欢迎继续使用右上角搜索按钮进行搜索redis、点赞数据存储、点赞、redis实现点赞、以便于您获取更多的相关信息。
点赞功能与redis的更多相关文章
- 点赞功能与redis的相遇
https://www.jianshu.com/p/2ab76d5bde71 或者 https://kikoroc.com/2016/06/07/dev-like-function-with-redi ...
- thinkphp redis实现文章点赞功能并同步入mysql
<?php namespace app\common\controller; use think\App; use think\facade\Cache; use think\facade\Db ...
- 基于SpringBoot如何实现一个点赞功能?
基于SpringBoot如何实现一个点赞功能? 解析: 基于 SpringCloud, 用户发起点赞.取消点赞后先存入 Redis 中,再每隔两小时从 Redis 读取点赞数据写入数据库中做持久化存储 ...
- ajax点赞功能
- Redis附加功能之Redis流水线pipeline
流水线功能的目的:通过减少客户端与服务器之间的通信次数来提高程序的执行效率. 一.通信 在一般情况下, 用户每执行一个 Redis 命令,客户端与服务器都需要进行一次通信:客户端会将命令请求发送给服务 ...
- JavaScript实现评论点赞功能
通过分析评论功能的逻辑关系,学会如何使用JavaScript实现评论.回复.点赞等各种功能 1.学会JavaScript处理日期和时间. 2.掌握Dom操作中的添加/删除子节点方法. 3.使用setT ...
- JavaScript cookie操作实现点赞功能
JavaScript cookie操作实现点赞功能 参考实现原理,但是代码不够简洁,简洁代码参考:js操作cookie 实现一个点赞功能十分简单,主要问题在于不能重复点赞. 若是一个有用户的网站,可 ...
- 基于微信小程序的用户列表点赞功能
代码地址如下:http://www.demodashi.com/demo/13997.html 一.前言 (1).适合人群 1.微信小程序开发者 2.前端工程师 3.想入门学习小程序开发的人员 4.想 ...
- 全栈项目|小书架|微信小程序-点赞功能实现
微信小程序端的点赞功能其实没什么好介绍的,无非就是调用接口改变点赞状态和点赞数量.需要注意的是取消点赞时的处理,我这里为了减少服务器接口的调用,直接本地存一个变量,修改这里的变量值即可. 由于源码都相 ...
随机推荐
- endnote中文格式“,等”的修改
https://www.howsci.com/endnote-eng-cn-refer-etal.html
- Java 设计模式 ------ 模板设计模式
模板设计模式主要来源于生活中有一些事情是有模板可以遵循的.举两个生活中的例子,如泡茶和泡咖啡,看一看. 泡茶有以下四个步骤: 1, 烧开水; 2 把茶放到水杯中; 3,倒入开水; 4, 加糖. 泡 ...
- codeforces24D
CF24D Broken robot 题目背景 小小迪带你吃瓜 题目描述 给出一个 n×m 的矩阵区域,一个机器人初始在第 x 行第 y 列,每一步机器人会等概率 的选择停在原地,左移一步,右移一步, ...
- codeforces493B
Vasya and Wrestling CodeForces - 493B Vasya has become interested in wrestling. In wrestling wrestle ...
- FFmpeg 将YUV数据转RGB
只要开始初始化一次,结束后释放就好,中间可以循环转码 AVFrame *m_pFrameRGB,*m_pFrameYUV; uint8_t *m_rgbBuffer,*m_yuvBuffer; str ...
- Let's Encrypt免费泛域名证书申请
一. 下载acme.sh,以下四条命令任选一条即可 curl https://get.acme.sh | shwget -O - https://get.acme.sh | sh curl https ...
- 微信小程序原生开发简介
简介: 总结: 1. 逻辑层使用js引擎,视图层使用webview渲染 2. 微信小程序已经支持了绝大部分的 ES6 API 3. 可以自动补全css的兼容语法 文档:https://develope ...
- Android 一些关于 Activity 的技巧
锁定 Activity 运行时的屏幕方向 Android 内置了方向感应器的支持.在 G1 中,Android 会根据 G1 所处的方向自动在竖屏和横屏间切换.但是有时我们的应用程序仅能在横屏 / 竖 ...
- 队列模式&主题模式
# RabbitMQ 消息中间件 **Advanced Message Queuing Protocol (高级消息队列协议** The Advanced Message Queuing Protoc ...
- cf1076E Vasya and a Tree (线段树)
我的做法: 给询问按$deep[v]+d$排序,每次做到某一深度的时候,先给这个深度所有点的值清0,然后直接改v的子树 官方做法比较妙妙: dfs,进入v的时候给$[deep[v],deep[v]+d ...