Go 训练营第 5 周——评论系统架构设计
架构设计
本质:理解客户真正的需求,解决其问题。
写评论的压力问题:通过 kafka 消峰、分区扩容的能力解决。
数据设计
mysql 一定需要配置主键,且数据必须顺序写,避免 IO 分裂影响写性能;
考虑评论内容比较大,mysql IO 每次只有 16KB 数据,考虑读写性能,将评论内容、评论元数据独立成两个表,评论的点赞、更新评论数等操作只需要更新元数据表,且每次 IO 可以捞出更多的评论 ID(评论内容表的主键),再通过 ID 点查到评论内容。另外内容和元数据独立也符合读写分离的业务场景。
for update 容易死锁的原因:多个更新同时依赖多个数据,可能会交叉锁对方的资源,导致死锁,可以在操作前先保证操作顺序,避免同一数据行下的多个锁同时出现。
分页:使用流标接口。
思考:图存储更好?
缓存设计
缓存重建问题:一般会采用预加载数据到缓存,但如果预加载过多可能会产生惊群现象,这里采用预加载请求到 kafka,然后通过 job 消费处理预加载。
redis sorted set 冗余多份排序后的数据,解决排序数据的快速加载;
评论内容优化:protobuf 序列化后存入缓存;
可用性设计
缓存穿透问题:
单飞的方式,避免一个进程里多个请求同时去回源数据。
go 的单飞支持:https://pkg.go.dev/golang.org/x/sync/singleflight
缓存抖动:参考https://www.usenix.org/system/files/conference/nsdi13/nsdi13-final170_update.pdf
热点
写热点:消息队列缓冲压力
读热点:local cache,因为内存限制,可以用环形数组+滑动窗口统计数据,再取 topk 出来做 local cache。
加餐
GC 优化:
小对象初始化时用内联方式,避免多次 new 以减少内存小对象。
内联方式,如果用指针的话,得 new 外层的 Group,再 new sync.Mutex,这里没加指针就是自动创建,且跟外层在同一个内存对象。
mono_repo
基础库
CI/CD
评论