我们有一个类知乎的服务,日活 500 万左右;用户可以对文章进行点赞,但是用户只有在文章详情页才可以进行点赞相关的查询和操作,QPS 也不高,所以直接走数据库查询也没有太大性能问题。 最近产品提出将点赞按钮前置到文章列表中的需求,我们每次分页会查询 50 篇文章的信息,肯定不能直接走数据库了。 目前我初步想法是将用户点赞数据放到 Redis 位图中,考虑到用户点赞其实是个相对低频的操作,点赞、取消点赞都直接操作 Redis,异步刷新到 DB,这样牺牲了部分可靠性,比如 Redis 挂了导致用户操作没有同步到 DB 、或者 Redis 操作成功,但是 DB 操作失败如何处理,还要考虑如异步调用乱序如何处理。 所以想请教下各位 V2er,这类点赞系统的设计有没有一些最佳实践?比如走 ES 或 Mongo?
1
love2020 2021-07-27 11:06:09 +08:00
25 次点击,没人回答你的问题。 [也许 Redis 真的没那么容易挂。。]
|
2
securityCoding 2021-07-27 11:08:04 +08:00
redis-》进程内缓存-》 DB,完全能扛得住
|
3
GreatEscape OP 服了,发出来怎么换行等格式全没了。。。
|
4
bnrwnjyw 2021-07-27 11:22:30 +08:00
@GreatEscape markdown 要换两行
|
5
no1xsyzy 2021-07-27 11:34:13 +08:00
我猜测将「文章被点赞总数」一并进行存储再添加[用户,文章]联合索引即可满足性能需求。
最佳实践应是图数据库 ps. markdown 换两行 = 分 <p> 空两格换一行 = <br> |
6
hahasong 2021-07-27 12:00:43 +08:00
各家主流的做法是,点赞 /取消 界面 UI 实时反馈(与请求无关),然后上报一次事件。你可以把事件记在队列里。然后匀速消费,统计点赞数和记日志。你不记操作日志,点赞人进去怎么看到自己是点了还是没点
也可以简化做,不用队列,直接请求接口,但是 WAF 做下限流就行,大不了太多了返回 “操作频繁,请稍后再试” |
8
xuanbg 2021-07-27 12:16:55 +08:00
分页查询怎么就不能直接查表了? left join 点赞记录表就好了嘛
|
9
tedcon 2021-07-27 15:07:53 +08:00
点赞的数量 也就是读操作可以放到缓存。写操作先入 db 然后同步到缓存。这不是常规操作吗?
|
10
GreatEscape OP @xuanbg 看 QPS 的,我们之前点赞列表直接联表查,有次做活动,直接引导用户跳转到自己的点赞列表,联表查就差点查挂了。
|
11
bthulu 2021-07-28 09:02:47 +08:00
写入浏览器本地数据库就行了, 每次用户登录或退出登录的时候, 随登录或退出登录接口传到后端存入数据库即可
|
12
GreatEscape OP @tedcon 重点不在于点赞数量,而是用户对该文章的点赞状态,写 DB 同步到缓存会导致用户快速操作时出现缓存不一致的问题。
|
13
waibunleung 2021-07-28 10:43:52 +08:00
像上面 @hahasong 说的,先界面 UI 实时响应,然后前端 /客户端先把用户点赞过的内容先缓存起来,后端用队列来将点赞数据落地到 DB 。请求用户点赞状态 /计数的时候,返回结果带上一个版本号,前端通过版本号来对比来决定是否+1 或者替换掉服务端的数据,这样是否可以?
点赞这种东西,不需要强一致性的,只需要保持最终一致就好了。至于数据丢失,肯定会有的,CAP 理论,看你们怎么取舍而已。保证 BASE 可用就好了。个人理解,欢迎友好交流~ |
14
a719031256 2021-07-28 13:58:10 +08:00
我到觉得你先做出来再谈优化,楼主给我的感觉跟我现在带的同事好像,东西没做就想这想那
|
15
ospider 2021-07-28 14:11:42 +08:00
我真是特别讨厌叫人「彦祖」这种提问方式,不是每个人都喜欢明星的
|
16
tedcon 2021-07-28 16:17:47 +08:00
@GreatEscape 这个就需要前端控制啊 不管是点赞还是其他操作。前端肯定要有个 state=pending 然后等待 response,成功了才将点赞+1,pending 的时候无法再次点赞。
|
17
shadowfish0 2021-07-29 01:11:08 +08:00 1
@ospider 这只是个梗吧,意思和喊帅哥差不多
|
18
ljzxloaf 2021-07-29 10:10:08 +08:00
先更新计数(建议用可持久化的 kv 数据库如 etcd,redis 是用来做缓存的),具体请求先写到消息队列,异步更新到数据库。还有评论啊点赞啊这些东西都是要做频率控制的
|