- 提供路由管理服务,能让客户端Proxy快速定位要访问的数据位于哪个Cache服务器上。
- 控制Cache服务进行主备切换。
- 当集群性能不足或容量不够的情况下,提供数据迁移的调度功能。
由于数据分布在多个cache服务器上,客户端访问数据时,就需要通过路由来快速定位要访问的数据位于哪个cache服务器。具体来说就是客户端Proxy根据Router提供的路由信息,去定位业务的key落到哪个Cache服务上。这个路由信息就是一张路由表,下面是一个路由表的例子:
编号 | 业务模块名 | 开始页 | 结束页 | 路由目的服务器组名 |
---|---|---|---|---|
4 | SQQProfile | 0 | 143165 | SQQProfileGroup0 |
16 | SQQProfile | 143166 | 286330 | SQQProfileGroup1 |
28 | SQQProfile | 286331 | 429497 | SQQProfileGroup2 |
在DCache中,不同的业务模块有自己独立的路由表,而每个模块又分成了多个cache组,每个cache组都对应了一条自己的路由信息,负责存储一段路由页。 路由页:业务数据的key有各种含义,比如QQ号码、电话号码或字符串MD5值等,但我们都可以将key通过一致性hash算法转换到0~4294967295 (unsigned int)范围内,以方便我们做路由。 由于分组数不会太多,所以实际的路由范围是以页为单位,每一页包含了连续的10000个hash值,所以路由范围就是0~429497(页)。[图片:路由查找流程]
数据的路由是基于路由表的。但由于机器性能不足,或者容量不够的情况下,数据需要从一台机器迁到另一台机器,路由表也需要做相应的变动。这个过程就叫做数据迁移。 但这个过程中业务还在读写,不能在迁移过程中屏蔽业务的所有读写操作。所以数据迁移的重要目标的就是业务无感知。
迁移采用的是先复制数据后改路由表的策略。每次迁移10页(可以配置),迁移过程中不允许写这10页的数据。虽然这10页的数据不可写,但由于我们有42W的页数,10页的的占比很小,而且proxy在迁移过程中出错会有重试的机制(重试一次),因此由迁移导致的写失败业务侧无感知。
- 迁移流程先通知目的组,把要迁移的页范围锁住,然后做些数据清理的动作;
- 然后通知迁移源组,把要迁移的页范围锁住不可写,然后从内存读取数据,把数据发送到目的组,完成之后返回给router;
- router收到迁移完成之后,把最新路由信息推送给源组和目的组,然后修改DB和内存的路由表信息。
- 整个迁移流程结束。
其中Proxy是通过定时获取路由的变更状态来获取最新的路由。当迁移结束到proxy获取到最新的路由有一个时间窗口,这个时候proxy还会访问到旧的cache。 这时由于cache拥有最新的路由信息,会判断请求是否属于本cache负责,如果发现请求不属于本cache,会回复路由错误的信息给proxy,proxy就随后立即更新路由信息再次访问。 通过这样的方式来保证路由变更不会影响业务数据的一致性。
RouterServer中还支持了Cache服务的自动切换,包括主备机的自动切换,镜像的自动切换和备机不可读切换。自动切换的主要逻辑是在RouterServer内部实现。DCache的自动切换功能提高了集群容灾容错能力,减少了系统异常对业务的影响,也使得运维工作更加轻松高效。 自动切换保证的两个基本目标是: A.防止误切(例如网络波动的影响),这都就要求严格的宕机检测。 B.切换过程中保证所有接入机的写操作不会同时写到两个master(切换前的master,和切换后的master),从而导致数据错乱或丢失。
主备机以及镜像会定时向RouterServer发送自身的心跳信息,心跳超时后即会启动自动切换检测流程,满足一定条件后便会执行自动切换。
具体来说,Router执行主备切换的逻辑是这样的:
- 判断Cache主机心跳超时。
- 判断备机心跳没有超时。
- 向Cache主机发送探测包,确认主机没有响应。
- 向备机发送探测包,确认备机存活。
- 通知备机断开与主机之间的连接。
- 通知主机降级。
- 修改路由信息并同步新的路由到Proxy,切换完成。