美文网首页码农的世界@IT·互联网程序员
分布式session平滑迁移,我们是这样做的

分布式session平滑迁移,我们是这样做的

作者: Misa527528 | 来源:发表于2018-05-30 23:30 被阅读130次
题图:非洲草原上的动物大迁徙

背景/需求

用户Session数据的特点和缓存具有一定的相似性:较高的读写性能要求、会失效,具有TTL。但不同点在于:缓存的数据允许丢失,在缓存数据丢失时可以通过加载DB中的数据以保障服务的可用性;而session一般不会落库到传统的关系型DB中,这意味着在数据失效前是不允许数据丢失的。
像很多公司一样,有赞最初把用户的session信息存储在codis集群中。在高并发的场景下,codis提供的存储方案可以很好的满足性能和吞吐量的要求;但是codis在有赞的内部的定位仅仅为缓存而非内存数据库,这意味着允许数据的丢失,从高可用的角度来看把session信息存储在codis中是不安全的。为此有赞搭建了一套自有的内存数据库,支持Key-Value存储,将session信息从codis迁移到KV中。

项目方案

数据迁移的方案选择一般有两种:一是停机迁移,这种方案的好处是操作简单,迁移速度快,但牺牲了服务的可用性。二是平滑迁移,在不影响服务可用性的情况下进行迁移,缺点是需要较长的时间,应用的逻辑需要改动。在服务可用性要求很高的互联网领域中,方案二成为了必选项。
平滑迁移一般分为三个阶段:1.数据双写 2. 灰度读阶段 3. 下掉双写代码

双写阶段

双写阶段需要将数据写入到codis和KV存储集群中,这是平滑迁移的第一个阶段。


双写阶段

在笔者的具体实践中,数据双写分为两个子阶段执行。
首先是进行异步写KV、同步写Codis,这一阶段主要是目标是:保证数据正常写入KV的同时,观察KV操作的性能和KV存储集群的稳定性。在有赞内部,可以通过调用链工具监控到具体操作的执行时间,同时对比原来操作codis写方法的时间的大小,从而判断是否进入下一个阶段。
第二个子阶段是同步写阶段,将数据同步写入到codis和KV存储集群中。同步写可以验证session服务最终写入接口的稳定性,为了做到实时可控(秒级别的响应),在有赞内部可以通过diamond或者Apollo中间件来控制同步写入KV Store的流量,即通过灰度的方式来切流,逐步切到100%。

灰度读阶段

在数据正常写入到KV之后,接下来便是灰度读阶段。


灰度读阶段

笔者也将灰度读分为三个子阶段进行。
第一个子阶段为异步读KV,同步读codis,并将读codis的结果传递给异步任务,在异步任务中比较codis和KV的结果是否一致。在做数据对比时要注意避免放大读codis的流量——在高并发的场景下,由于不是实时比较,读到的KV数据可能不一致。在这个阶段只需要做到粗略的对比,检验数据是否存在其他不一致的情况;同时观察读KV的接口性能以及是否需要优化。
第二个子阶段为实时比较,在这个阶段将两个数据源的数据进行实时比较,这个阶段目标是做到数据的强一致性。根据CAP理论,应用会损耗一部分的性能,为了规避风险,做到秒级别响应,笔者同样使用中间件进行灰度控制。
在第二个阶段完成之后,理论上已经可以保证数据的一致性了;随即可以进行第三个子阶段,将部分读流量切到KV Store,通过灰度的方式逐步切流。这个阶段仍然需要做好监控,一旦发现数据存在异样,建议第一时间关闭灰度的功能,排查出原因再决定是否继续切流。

下掉双写、灰度读代码,去除依赖

在灰度读KV的流量达到100%之后,此时session服务的数据读取已经全部依赖于KV Store,数据可以无需再写入到Codis,即应用可以摘抄掉codis存储。将应用中的读写codis的相关代码删掉即可,结束整个迁移过程。


迁移完成

相关文章

网友评论

    本文标题:分布式session平滑迁移,我们是这样做的

    本文链接:https://www.haomeiwen.com/subject/wygtlftx.html