干货 | 携程Redis海外机房数据同步实践
作者简介
孟文超,携程技术中心框架研发部高级经理。2016年加入携程,目前负责框架数据(数据库,缓存)及相关项目。此前曾在大众点评工作,任基础架构部门通信团队负责人。
随着携程国际化业务的发展,为了给海外用户提供更好的服务,公司开始在欧洲部署业务(使用Amazon云),欧洲的用户访问欧洲的本地服务。携程机票业务重依赖于Redis,同时目前的数据产生大部分都在上海,这样就对Redis数据同步至欧洲产生了极大的需求,部署在欧洲的业务只需读取Redis数据即可。
数据传输如果走专线,将会产生高昂的专线费用(1MB的带宽,每月约1万RMB),如果能够通过公网,基本可以将数据传输费用降低到忽略不计。这样产生了第二个需求:数据传输走公网。
XPipe(https://github.com/ctripcorp/x-pipe)是携程内部开源的一套Redis多机房系统,现有的功能在以往的基础上继续扩展,可以参考公众号的另外一篇文章《携程Redis多数据中心解决方案-XPipe》。
二、系统分析设计
在这样的需求背景下,产生了下面几个问题:
公网数据网络传输性能不可靠,Redis内存缓存的增量数据有限,是否会产生频繁的全量同步?
数据如何从上海内网传输至公网,再传输至Amazon内网?
公网传输的性能能满足业务需求吗,会不会导致延时过高,甚至无法追上上海的数据产生速度?
2.1 Redis全量同步问题
Redis数据复制本身的工作原理可以参考一下官方手册:
https://redis.io/topics/replication。
本质上是说在Redis Master内存里面会以RingBuffer的数据结构缓存一段增量数据;如果网络瞬断的话,slave将会继续从自上一次中断的位置同步数据,如果续不上,就会进行一次全量同步。
因为数据在内存中缓存,而内存有限且昂贵,一个思路就是将数据缓存在磁盘里面。
在我们的具体方案中,设计了一个Keeper节点,作为Redis Slave向Master同步数据,同时将同步后的数据存入本地磁盘,海外数据同步通过Keeper进行数据传输,这样就产生了下面的结构:
关于Keeper的高可用及其相关的设计,可以参考前文所述的公众号文章。
2.2 数据从上海内网传输到公网问题
公网到内网调用可以使用反向代理软件,因为Redis协议为基于TCP自定义的文本协议,因此我们要使用支持TCP的反向代理工具。
Http的反向代理可以通过域名、URL等信息进行路由,定位到目标服务器;TCP协议的反向代理通过暴漏的端口来路由到不同的服务器集群。
公司内部的的Redis集群非常多,如果使用目前的反向代理软件,就意味着要在公网开多个端口,不同的端口路由到不同的Redis集群,单个IP支持的端口有限,过多端口也会带来更多的安全以及管理问题。
基于此,我们设计了支持动态路由的TCP Proxy,假设有四个点:S(Source) P1(Proxy) P2(Proxy) D(Destination),A需要通过Proxy建立到D的连接,整个过程如下:
S建立到P1的TCP连接
S发送路由信息:proxy route P2 D
P1收到信息后建立到P2的tcp连接
P1发送路由信息:proxy route D
P2收到路由信息后建立到D的tcp连接
整体架构图如下:
如上图所示,上述箭头方向为数据传输方向,TCP连接建立方向正好相反。Pxory本身无状态,所以天然可以做到高可用;Proxy本身支持数据加密、压缩等功能。
用户可能会产生疑问,为什么欧洲还需要一组Proxy集群,而不是Keeper直接连接上海的Proxy?
这个主要是基于功能隔离的考虑,Proxy专注处理好加密、压缩等传输层需要考虑的问题,Keeper只需要考虑业务相关的功能。加密、压缩算法的优化和变更不会影响Keeper 。
2.3 公网传输性能问题
一般考虑网络问题时,需要考虑带宽、延时、丢包三组要素,公网传输是高带宽,高延时,高丢包。网络上有很多关于Long Fat Network以及网络性能调优的文章,具体不赘述,这里主要描述一下整个实践过程。
首先我们调整了TCP的发送接收窗口:
net.core.wmem_max=50485760 net.core.rmem_max=50485760 net.ipv4.tcp_rmem=4096 87380 50485760 net.ipv4.tcp_wmem=4096 87380 50485760 |
上海到欧洲的网络延时在200ms左右,调整完成之后发现在24小时的稳定性测试中,会有多个时间点带宽无法打上去,导致数据同步延时过高。仔细观察了一下当时TCP连接的状态(通过ss命令),发现发送数据时,TCP发送窗口(cwnd)因为时不时的丢包,导致一直很小,问题主要出在数据发送方。
据此,我们在测试环境比较了多种发送端的拥塞控制(CongestionControl)算法:Cubic, Reno, Htcp. BBR,下面是在1%丢包率下不同算法带宽比较:
算法 | 平均带宽 |
Cubic | 0.15 MBytes/sec |
Htcp | 0.11 MBytes/sec |
Reno | 0.09 MBytes/sec· |
BBR | 13.6 MBytes/sec· |
在测试Case下,BBR算法的带宽比其他算法提升了几乎100倍,其他丢包率的情况下,也有更好的表现。关于BBR算法的更多资料可以参考:
https://netdevconf.org/1.2/papers/bbr-netdev-1.2.new.new.pdf
因为我们的场景中数据发送方是在上海,所以在上海端的服务器部署了BBR算法,下面是在10MB数据传输速率下,公网24小时延时测试数据(单位为纳秒),数据最大延迟为88S。
公网和专线比较:
公网 | 专线 | |
丢包 | 高(约1%) | 低(约0.05%) |
带宽 | 高 | 低 |
延时 | 中 | 中 |
价格 | 非常低 | 高,1W RMB/MByte/月 |
2.4 监控、报警
整个系统中最重要的指标是数据从上海到欧洲的延时是多少。根据此数据可以判定系统是否健康。系统延时监控架构如下图所示:
测试Client Publish一个时间戳数据给Master,然后将这个数据从Slave这边订阅收回,整个延时测试时间为:T1+T2+T3+T4。将数据收回计算延时时间主要是为了避免不同服务器时钟不一致产生的影响。
为什么数据订阅走专线?
监控系统两秒Publish一个时间戳,数据量足够小,不会占用过大专线带宽
我们关注的延时其实主要是T1+T2的时间。专线比较稳定,如果数据传输到欧洲走公网,订阅回来也走公网,可能会导致延时测试数据不准确
为什么数据订阅通过Proxy转发?
这个主要是公司安全策略问题,欧洲的服务器只暴漏出了有限的端口供上海访问,而Redis服务器可能部署在很多的端口上面,这样可以通过Proxy进行转发代理。
2.5 整体系统架构
整体系统架构如上图所示。Console用来管理多机房的元信息数据,同时提供用户界面,供用户进行配置和DR切换等操作。Keeper负责缓存Redis操作日志。Proxy主要解决公网传输问题。Meta Server管理单机房内的所有Keeper状态,并对异常状态进行纠正。Zookeer用来供Meta Server和Keeper进行Leader选举。
三、实践结果
整个系统目前从2018年7月上线,稳定运行至今。下图是某一业务集群的一个分片30天延时监控数据(单位为微秒)。平均延时180ms左右,最大可能波动到1-2min。
同时,整个系统已开源:
XPipe:https://github.com/ctripcorp/x-pipe(点击阅读原文直达)
【推荐阅读】