求教各位彦祖,点赞系统设计的最佳实践?

2021-07-27 10:57:48 +08:00
 GreatEscape

我们有一个类知乎的服务,日活 500 万左右;用户可以对文章进行点赞,但是用户只有在文章详情页才可以进行点赞相关的查询和操作,QPS 也不高,所以直接走数据库查询也没有太大性能问题。 最近产品提出将点赞按钮前置到文章列表中的需求,我们每次分页会查询 50 篇文章的信息,肯定不能直接走数据库了。 目前我初步想法是将用户点赞数据放到 Redis 位图中,考虑到用户点赞其实是个相对低频的操作,点赞、取消点赞都直接操作 Redis,异步刷新到 DB,这样牺牲了部分可靠性,比如 Redis 挂了导致用户操作没有同步到 DB 、或者 Redis 操作成功,但是 DB 操作失败如何处理,还要考虑如异步调用乱序如何处理。 所以想请教下各位 V2er,这类点赞系统的设计有没有一些最佳实践?比如走 ES 或 Mongo?

3474 次点击
所在节点    程序员
19 条回复
love2020
2021-07-27 11:06:09 +08:00
25 次点击,没人回答你的问题。 [也许 Redis 真的没那么容易挂。。]
securityCoding
2021-07-27 11:08:04 +08:00
redis-》进程内缓存-》 DB,完全能扛得住
GreatEscape
2021-07-27 11:14:02 +08:00
服了,发出来怎么换行等格式全没了。。。
bnrwnjyw
2021-07-27 11:22:30 +08:00
@GreatEscape markdown 要换两行
no1xsyzy
2021-07-27 11:34:13 +08:00
我猜测将「文章被点赞总数」一并进行存储再添加[用户,文章]联合索引即可满足性能需求。
最佳实践应是图数据库

ps.
markdown 换两行 = 分 <p>
空两格换一行 = <br>
hahasong
2021-07-27 12:00:43 +08:00
各家主流的做法是,点赞 /取消 界面 UI 实时反馈(与请求无关),然后上报一次事件。你可以把事件记在队列里。然后匀速消费,统计点赞数和记日志。你不记操作日志,点赞人进去怎么看到自己是点了还是没点


也可以简化做,不用队列,直接请求接口,但是 WAF 做下限流就行,大不了太多了返回 “操作频繁,请稍后再试”
DoctorCat
2021-07-27 12:04:18 +08:00
“ 直接操作 Redis,异步刷新到 DB,这样牺牲了部分可靠性 ” ,Redis 集群后可用性不是问题,而是一致性问题,实现最终一致性。

Redis 做点赞计数够用了。满足需求的前提下不用考虑其他更复杂的方案。
xuanbg
2021-07-27 12:16:55 +08:00
分页查询怎么就不能直接查表了? left join 点赞记录表就好了嘛
tedcon
2021-07-27 15:07:53 +08:00
点赞的数量 也就是读操作可以放到缓存。写操作先入 db 然后同步到缓存。这不是常规操作吗?
GreatEscape
2021-07-27 16:17:56 +08:00
@xuanbg 看 QPS 的,我们之前点赞列表直接联表查,有次做活动,直接引导用户跳转到自己的点赞列表,联表查就差点查挂了。
bthulu
2021-07-28 09:02:47 +08:00
写入浏览器本地数据库就行了, 每次用户登录或退出登录的时候, 随登录或退出登录接口传到后端存入数据库即可
GreatEscape
2021-07-28 09:59:45 +08:00
@tedcon 重点不在于点赞数量,而是用户对该文章的点赞状态,写 DB 同步到缓存会导致用户快速操作时出现缓存不一致的问题。
waibunleung
2021-07-28 10:43:52 +08:00
像上面 @hahasong 说的,先界面 UI 实时响应,然后前端 /客户端先把用户点赞过的内容先缓存起来,后端用队列来将点赞数据落地到 DB 。请求用户点赞状态 /计数的时候,返回结果带上一个版本号,前端通过版本号来对比来决定是否+1 或者替换掉服务端的数据,这样是否可以?

点赞这种东西,不需要强一致性的,只需要保持最终一致就好了。至于数据丢失,肯定会有的,CAP 理论,看你们怎么取舍而已。保证 BASE 可用就好了。个人理解,欢迎友好交流~
a719031256
2021-07-28 13:58:10 +08:00
我到觉得你先做出来再谈优化,楼主给我的感觉跟我现在带的同事好像,东西没做就想这想那
ospider
2021-07-28 14:11:42 +08:00
我真是特别讨厌叫人「彦祖」这种提问方式,不是每个人都喜欢明星的
tedcon
2021-07-28 16:17:47 +08:00
@GreatEscape 这个就需要前端控制啊 不管是点赞还是其他操作。前端肯定要有个 state=pending 然后等待 response,成功了才将点赞+1,pending 的时候无法再次点赞。
shadowfish0
2021-07-29 01:11:08 +08:00
@ospider 这只是个梗吧,意思和喊帅哥差不多
ljzxloaf
2021-07-29 10:10:08 +08:00
先更新计数(建议用可持久化的 kv 数据库如 etcd,redis 是用来做缓存的),具体请求先写到消息队列,异步更新到数据库。还有评论啊点赞啊这些东西都是要做频率控制的
ljzxloaf
2021-07-29 10:41:59 +08:00
@ljzxloaf #18 etcd 好像没有相关的 api,还是用 redis 吧。。注意下可用性

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/792004

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX