如果您的业务规模较大,有多地容灾部署的需求,可以参考本文档实现多地容灾的 Session 管理。

前提条件

• 已分别创建3个区域用于保存会话的云数据库Redis实例,实例不需要额外开通其他服务。
• 所有Redis实例与应用所部署的ECS实例均在同一VPC中。
• 已将ECS实例的内网IP地址设置到Redis实例的白名单中。

背景说明

随着业务用户规模不断扩大,用户可能会在全国各地甚至全球使用业务服务,这种规模下,通常都需要有异地容灾部署的架构来支持。一是多地部署可以优化用户访问的速度,尽可能的实现就近服务。二是一旦单点发生故障,异地容灾可以快速转移到正常服务,为用户提供更好的支持。

在这种情况下,session 信息需要做到一致性,可以获得比较好的用户体验,并且具备容灾功能。比如用户在上海登录注册后,出差到北京时,这时即使使用了异地的服务,依然能读取到用户的会话信息,而不是重新登录一次。而当上海服务出现问题时,上海用户也能快速切换服务至北京,服务不会受到太大的影响。

容灾切换 redis预热 redis 异地容灾_Redis

以下我们着重说明一下如何实现多地容灾的Session管理。

场景案例

场景需求

业务用户范围覆盖全国,有多地容灾的需求,要求在单地发生故障时,可以尽量不影响用户的会话管理。

场景分析

• 由于业务用户范围覆盖全国,因此在考虑多地容灾建议地域间隔较远,可以尽量覆盖全国。比如,我们这里地域的选择可以考虑上海(华东),北京(华北)和河源(华南)。
• 单地故障可切换,意味着需要做多地的数据同步,所以功能设计上主要聚焦这点。

功能设计

DTS 目前只能提供 Redis 实例间的单向同步,因此考虑在业务层实现数据同步,主要基于以下考虑:

  1. 具备更好的灵活性,业务层可以根据具体的数据时效性,来决定采用同步还是异步的方式实现数据同步。
  2. 在进行读操作的时候,可以适当做一些补偿回写机制,这时不会产生额外的写同步操作。

写操作:当用户在某地创建session时,服务端会同时异步将数据Push到其他两地。

IF (OK == Redis_SH-> Set (sessionid, sessionInfo, 600))
    Redis_BJ-> Set(sessionid, sessionInfo, 600)
    Redis_HY-> Set(sessionid, sessionInfo, 600)
读操作:如果用户流量因某种原因被切换到了异地,那么优先从当地的Redis读取。如果异地Redis没有查询到该条数据,则返回源机房的Redis实例中读取数据。然后再将该数据写回到当地。
IF (localIp match Heyuan)
   sessionInfo = Redis_HY-> GET(sessionid)
   IF sessionInfo == NULL
   sessionInfo = Redis_SH-> GET(sessionid)

上述操作中有个名词叫源机房,源机房就是指创建该session的机房。
那么服务端是如何知道该session的源机房在哪里?这里做了一个session数据结构的设计。为了区分出用户写入的区域,我们在生成 sessionid 之后,会替换掉 session 的第一个字符。比如上海写入的sessionid 首字符是s,北京写入的为b,河源写入的为h。这样用户在发起请求时,服务端就可以知道该会话信息源自哪里。
如果用户在 sessionId 有效期内地域发生了变更,那他第二次所在的地域更新数据时,会同步写入当前地域和 sessionid中记录的源机房,再异步推动到其他地域,这样就可以保证 sessionID 对应信息的一致性。

总结

基于Redis实现会话管理的多地容灾方案,不依赖 Redis 产品的异地数据同步功能,而是通过业务层实现数据间同步,可以具备更好的灵活性,满足更多大规模应用的服务需求。