Go 进阶训练营 – 评论系统架构设计四:可用性设计

Singleflight

image-20221022151628414

对于热门的主题,如果存在缓存穿透的情况,会导致大量的同进程、跨进程的数据回源到存储层,可能会引起存储过载的情况,如何只交给同进程内,一个人去做加载存储?
使用归并回源的思路:https://pkg.go.dev/golang.org/x/sync/singleflight,同一时间只有一个协程去拿数据,拿到数据前,相同任务目标的其他协程都阻塞,拿到数据后,所有协程一起返回
同进程只交给一个人去获取 mysql 数据,然后批量返回。同时这个 lease owner 投递一个 kafka 消息,做 index cache 的 recovery 操作。这样可以大大减少 mysql 的压力,以及大量透穿导致的密集写 kafka 的问题。这是单个进程内的Singleflight,多节点下也会出现重复构建缓存的情况。可通过kafaka根据objId和objType进行分发消息,保证同一个缓存构建任务都分发到同一个job进程,同时这是串行执行,每次执行前先判断下缓存内是否有miss的key,有的话就drop当前任务。

这种套路很常见,例如CDN避免大量请求到源站,可能会使用多级单飞节点。

为什么不用分布式锁之类的思路?

太复杂,一般锁的key很快就过期了,不好调试。

极端情况下如何保证高可用

  1. redis集群
  2. 对mysql的操作做熔断

热点

读热点

流量热点是因为突然热门的主题,被高频次的访问,因为底层的 cache 设计,一般是按照主题 key 进行一致性 hash 来进行分片,但是热点 key 一定命中某一个节点,这时候 remote cache 可能会变为瓶颈,因此做 cache 的升级 local cache 是有必要的,我们一般使用单进程自适应发现热点的思路,附加一个短时的 ttl local cache,可以在进程内吞掉大量的读请求。牺牲短时间的一致性,例如1秒,用户不容易感知。

image-20221022154639252

在内存中使用 hashmap 统计每个 key 的访问频次,这里可以使用滑动窗口统计,即每个窗口中,维护一个 hashmap,之后统计所有未过去的 bucket,汇总所有 key 的数据。之后使用小堆计算 TopK 的数据,自动进行热点识别。

一个统计周期拆分成多个窗口的原因是用平均值削平毛刺qps(在某个点突发的qps)对整体的影响。

写热点

  1. job里有推送消息到某个用户的操作,对某个用户的评论进行大量评论时,这个推送操作下游服务处理太慢,从而影响job服务对kafaka的消费能力下降,最终导致这个kafaka partion的任务都受影响。解决方案:
    1. 抽取推送操作为单独服务,通过读取写评论后的mysql binlog,进行异步操作。
    2. 优化分发partion,虚拟出更多的partion。

参考

  1. Sentinel 基于滑动窗口的实时指标数据统计
作者:Yuyy
博客:https://yuyy.info

评论

  1. yanliang
    Macintosh Chrome
    6天前
    2022-11-25 15:26:14

    请问有具体的实现吗?

  2. Yuyy
    博主
    Linux Chrome
    6天前
    2022-11-25 15:31:20

    没有哈,主要是理论知识

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇