一开始我们都是直接存入mysql
设计数据库表的时候 由于我们的点赞是打算独立系统
所以不跟别的业务表相耦合
所以设计了一个中间表
后面发现高并发的问题先不说 更多的是无效更新
所以我们打算把点赞数据存在缓存中进行更新
然后再定时推送到mysql中进行一个总数更新
缓存我们最先想到的是redis
所以选定redis后就是确定数据结构
很明显 我们的key一定要是业务id 但是业务id我们这里就是对应别的表的主键 比如问题表 课程表
在同一个表中雪花算法一般我们不考虑会重复的问题
但是我们这里有多种类型
所以我们的key决定由 业务的bizid跟bizType组成 这就默认不会重复了
那么value很明显 就是要跟用户相关 所以value 就是用户id
那么用户会取消点赞 所以我们如果用常规的集合 就会存在无效数据
所以我们用set就可以 在set的设置key 存在会返回0 0代表的就是false
所以流程就很清晰了
用户进来的时候 直接设置key 如果返回1那么就是设置成功没来签到
如果设置key失败 说明就是取消点赞 那么删除缓存即可
那么 用户的解决了 我们还要解决的一个点是总数 likedTimes的问题
那么同样考虑数据结构的问题
数据结构很明显
肯定要类似 bizType 开头 一个bizType又有很多个bizId bizid 有对应自己的点赞总数 likedTimes
所以第一个到的就是hash
但是hash会有个问题
就是我们多线程高并发的时候
设置值的时候
会跟别的线程出现串行的情况
所以我们需要再拿出来的时候 马上把这个数据删除 就可以了
所以zset有个pop 弹栈 弹出来就没了
为什么要弹min开始
就是因为数据量越小用户越敏感
整体思路就是这样
另外的优化思路还有
其他微服务主动感知点赞系统 有变化进行更新 缺点 业务耦合 没理由感知其他微服务的
不依赖mq 完全依赖定时任务 缺点 时间不好判断
伪装成mysql的从节点 要利用canal技术
读取binlog进行同步
缺点就是 又是中间件 加大mysql的压力了
总结 不要为了优化去优化 想想坏的 比如redis不稳定