Skip to content

主从全量同步磁盘 & 网卡限速

Patryk Kaminski edited this page Apr 14, 2022 · 1 revision
  1. 背景
    • 社区版本的redis在主从全量同步时, 不会进行资源控制, 会导致磁盘IO或者网络IO被打满, 影响同机部署的其他实例
  2. 调研
    • 阿里云采用的是令牌桶算法, 令牌桶算法的原理是系统会以一个恒定的速度往桶里放入令牌,而如果请求需要被处理,则需要先从桶里获取一个令牌,当桶里没有令牌可取时,则拒绝服务
    • 除了令牌桶, 还有漏桶算法, 漏桶可以看作是一个带有常量服务时间的单服务器队列. 在网络中,漏桶算法可以控制端口的流量输出速率,平滑网络上的突发流量,实现流量整形,从而为网络提供一个稳定的流量
    • 对比分析: 漏桶算法与令牌桶算法的区别在于,漏桶算法能够强行限制数据的传输速率,令牌桶算法能够在限制数据的平均传输速率的同时还允许某种程度的突发传输. 在全量同步限速的需求中, 我们期望的是任意时刻都不要超过我们传输的速率, 而漏桶算法的可控性更强, 更加满足需求. 其次, 在实现的复杂度上来说, 漏桶算法相对实现成本更低, 更加符合redis的设计理念, 所以, 我们选择漏桶算法.
  3. 设计目标
    • 可支持最小粒度1MB/s, 偏差在10%之内
  4. 实现设计
    • 配置项修改: 增加配置项 max-repl-send-rate, 单位为M/s, 默认不限速(0), 支持config set/get/rewrite
    • 限速算法: Redis中, 水滴的大小是16KB(PROTO_IOBUF_LEN), 所以, 我们限制水滴的流出速度即可达到限速效果, 具体计算方式如下:
      • send_cnt_per_second = (max-repl-send-rate / 16KB) 次
    • 我们利用Redis的定时触发机制, 进行次数的控制. 具体实现方式是, 在同步数据时, 每次发送 PROTO_IOBUF_LEN 大小的数据(与Redis原有机制一致), 之后判断速度限制的大小, 并进行等待, 等待时间(wait_time_after_send)就是1000000微妙除以 send_cnt_per_second, 计算方式如下:
      • wait_time_after_send = 1000000us / send_cnt_per_second
    • 限制 & 特殊处理: 如果 max-repl-send-rate < 16KB, 则不进行限速, 最大限速为16G/s
  5. 参考资料