在《醍醐灌顶!异地多活架构设计看这篇就够了》一文中,基于容灾需要,讨论了数据写入的架构模型。数据读取方面,重点在于解决读取请求的负载分担、路由选择的问题,对于容灾架构的选择影响不大。不过,其中的“写后立即读”场景,是个一致性范畴的问题,即写入的数据和写入后读到的数据是否一致的问题,本文不展开讨论各种一致性模型,只关注“写后立即读”的要求是数据写入后短时间内到来的读请求能够读取到最新写入的值这一具体问题,这是互联网应用中数据读取中比较独特和典型的场景,值得深入探讨,本文尝试分析一下这个问题的细节并探讨相应的解决思路。
关注腾讯云开发者,一手技术干货提前解锁👇
1.1 解决思路方向
写后立即读的问题是指一份数据在写完之后,很短时间内来读这份数据,读不到最新写入的值。解决这个问题,就需要读操作能够从最新写入了数据的节点获取数据,有几个方向:
在接入层、逻辑层、数据层的基础架构中,数据库层面具有最全貌的数据复制细节,可以刻画最精确的数据状态,如果能从数据库层面来着手,将从根本上解决写后立即读问题且做到业务无关,业务侧也会更轻松,例如上面的读时复制在数据库层面就比较容易做。不过,很多业务并不是运行在这么理想的数据库系统之上,还是不得不从业务侧来考虑解决思路。
NRW 是各节点对等的议会制度,用多数派解决读到新值的问题,根据读写量级压力调节 R 和 W 的数值来使系统达到一个较好的状态。这种模型,有请求量放大的问题,不管怎么调节 R 和 W 的数值,都只是把 R 和 W 的负载情况相对均衡,整体的读写代价增加是不可避免的。在跨城容灾场景下,NRW 方案成本较高,不太能接受,因为:
所以,很多业务都不采用对等机制来维护数据,而是采用主从模式,主写点写入之后,出于容灾的考虑,会等主写点数据复制到部分从节点后才算成功写入。为什么不复制到所有的从节点呢?因为重点在容灾,保证在主写点之外有冗余数据,并不追求各节点的数据完全一致。这样,就等同于 NRW 中的 W 是 1 < W < N,但是这一批写入点不是对等的,而是通过主从复制达到写 W 个节点的效果。读操作方面,基本都是读1次,这样就不能满足 N < R + W 了。在这种主从架构下,要想写后立即读到新值,基本就是去读主写点了,退化成了“单写单读”的情况,这就是本文要讨论的模型了。
1.2 业务架构案例
为了避免过于宽泛,下面以作者工作中碰到的典型的三地五中心跨城容灾架构来展开讨论,希望针对该典型模型的探讨能把问题核心聊清楚,在结合实际情况设计方案的时候有所启发。关于下图架构的几点说明:
1.3 解决方案模型
从业务架构案例的架构图来看,好像和NRW的多R情况类似,每次读都在做跨城读取。其实不然,可以把“写后立即读”细拆如下几点来看:
可以看到,解决写后立即读问题,并不需要所有请求都去主写节点,只要把“刺头”挑出来即可,也就是要寻找一种方案:该方案需要标识出哪些数据有写入操作,在特定时间段内特定场景的读请求到来时,数据不确定是否同步到从副本的情况下,引导这部分请求去读主写点。在异地多活场景下,读请求到来的接入点所在地和数据所在地可能是跨城的,如果读请求的时延要求比较敏感,还需要在写入后的短时间内新数据能够提供就近访问,避免跨城。总结一下要点如下:
这4点,是基于局部特征,层层下钻的过程,下面分别来看看。
区分业务场景,指的是如何把有写后立即读的“刺头”场景标识出来。基本可以从服务调用方和服务提供方两端视角来看:
明确了读写场景,每个用户读请求到来的时候,判断一下场景属性,如果是不需要写后立即读的场景,访问本地就近的数据副本即可,无需关心该副本是否有最新数据。对于有写后立即读需要的场景,则需要做进一步的判断处理。
如何标识某份数据有写入,有两个方向:
不管是用户端传递携带写入记录标识,还是后台存放写入记录标识,都在数据库之外引入了一套额外的依赖机制,会增加复杂度,引入的机制可靠性上相较于数据库来说,也是会有所折损的。不过,写后立即读主要解决的是用户体验层面的问题,应该说一般是能够接受的。当然,具体还是需要结合业务实际仔细评估。
有了写入数据的标识,用户读请求到来的时候,先读取一下最近写入的标识,判断一下,如果最近没有写入,说明本地副本已经有了最新的数据,访问本地就近的数据副本即可。如果最近有写入,那么需要进一步判断处理。
读场景往往有较高的性能要求,处理时延是一个很重要的指标,在异地多活的跨城架构中,都会提供本地的就近访问副本,以达到低延时的目标。不过,普通的读副本并不具备提供最新写入数据的访问能力。写后立即读的情况,其时延需要要考虑的主要因素包括:
明确了业务的时延要求后,对于要读到最新值的读请求,如果时延要求没那么高的,引导读主写点即可,否则,就需要提供就近访问能力。下面是以比较通用的后台记录写入标识模式来说明时延的示意图。
写后立即读的就近访问,要求提供就近访问的副本保证有最新数据,而我们讨论的数据层架构是保证不了的,这就需要业务层在把数据成功写入数据层后,额外往各读请求接入所在地写一份数据,以达到就近访问的目的。这种情况下,可以扩展上文“标识写入数据”提到的写入记录,不光记录写入标识,同时记录写入的具体数据。下面是简化的处理示意图,就近副本的定位,是用来解决写后立即读的问题,结合读请求不会污染数据,以及业务侧来实现强一致比较麻烦,设计上可以轻量化,例如:
写后立即读是比较典型的局部性问题,如果能够在数据库层面根据主从数据复制细节,刻画局部特征,解决起来会事半功倍。本文根据该问题的局部性特征,从业务侧角度,总结了区分业务场景、标识写入数据、判断时延要求、提供就近访问四步的解决思路,层层递进下钻,细化局部特征。
-End-
原创作者|熊章俊
你的业务是否有类似的问题,具体实践是怎样的呢?欢迎评论留言。我们将选取1则优质的评论,送出腾讯云定制文件袋套装1个(见下图)。12月4日中午12点开奖。
📢📢欢迎加入腾讯云开发者社群,享前沿资讯、大咖干货,找兴趣搭子,交同城好友,更有鹅厂招聘机会、限量周边好礼等你来~