什么是数据库的复制延迟
数据库的复制延迟就是当线上服务需要多个数据库时(比如为了分散流量),一条信息从源头数据库传递到下游数据库时经过的延迟。
举个例子:
- 目前互联网中,用户流量(有用户的各种活动而生成的事件数据)是非常巨大的。有些系统要求实时的捕获这些数据,并不断存储在后台数据库中。这些存放在数据库中的用户数据会被各种应用程序和其他服务读取
- 在消费这些数据的时候,理论上来说,数据的消费者可以直接连到后台数据库,去读取这些数据。但是,这些用户数据流具有大数据的几个特性,包括大规模和高可变性,并不适合直接连接到后台数据库。因为,这会对后台数据库造成很大压力,而且不能保证读取的延迟。
为了应对这一挑战,当前互联网公司,往往部署一整套的数据处理系统。这一整套系统通由几个模块组成,包括数据事件的捕获、数据的存储、数据的复制传输、数据的读取。
在这个系统中,数据的复制传输的作用很特别,是用来隔离数据库和数据使用者的。
采用数据复制传输模块的好处非常大,它可以减轻源头数据库的压力。因为复制传输可以进行级联,分散了用户流量,能够让系统的可扩展性更好。但这里有个前提,必须保证数据的复制延迟不能太大,否则会造成很糟糕的业务影响。
那如何通过合理是容量规划的分析,来控制数据的复制延迟呢?
生产环境中的用户流量特性
下面的图显示了一个互联网服务的在线用户流量。
时间范围是连续的六周,也就是 42 天的流量。你可以看到,用户流量呈现出了非常强的重复模式:基本上是以一周为一个周期,每周内五个工作日流量比较大,而周末的两天流量比较小。而且无论哪天,每天内部都有一个峰值。
我们接着研究每一天内流量的周期性模式。对于每个工作日和周末,流量的形状也是非常有规律的曲线。下图显示了一个工作日中,也就是 24 小时内的流量变化。你可以清楚地看到,每天都会有一段时间的高峰期,约为 8 小时
我们也对比了工作日和周末的流量变化,结果也是毫不奇怪的:工作日峰值一般远高于周末的峰值。二者的峰值之间,差不多有 4 倍的差距。
只有了解了用户流量特征,才能在实际操作中选对模型。
了解了生产环境中的用户流量特征后,还必须了解数据传输复制系统。当前系统有如下几个模块:事件生成、数据库存储、数据复制/传输、数据的消费/读取
具体来讲,当用户与公司的网页互动时,相应的用户更新事件就被发送到了数据库。这些事件包括:用户点击了其他链接、阅读了其他用户的动态、向其他用户发信息等等。每个用户事件都由数据复制模块传输,并提供给下游消费者服务。
同一个用户数据,可能被很多应用程序和服务模块读取,所以这样上下游级联的系统设计,有比较好的扩展性,可以轻松应对规模的扩展。比如,如果数据复制模块不堪重负,而成为性能瓶颈,那么可以采用发散式级联的方式来扩展,从而分散读取的流量。
需要注意的是,数据传输模块除了可以提供高扩展性,也可以提供数据的一致性。因为互联网流量分布在多个数据库或者多个数据中心,所以就需要一个整合而一致的数据视图。这样一个目的,是可以通过传输复制实时数据库事件来得到的。
这个系统的另外一个特性是,虽然用户流量可能随着时间变化很大,但是数据复制和传输的能力相对稳定。我们通过测量和观察,发现复制传输模块的吞吐量能力非常稳定,如下图:
那么面对不断变化的客户流量(也就是事件流量),我们要如何规划整个系统,来让稳定的数据复制能力去适应用户流量的不稳定性呢?
怎么解决数据库复制延迟问题?
要达成目的,我们必须做好容量规划和分析。
要减少数据库复制延迟,我们在进行容量规划的时候需要考虑几个因素,包括用户流量、复制模块的吞吐量、复制的延迟以及复制的SLA(Service Leevel Agreements),服务水平协议;从而确保所需的复制延迟,不要超过SLA的规定。
另外,通过充分考虑用户流入的流量和赋值容量,我们还可以做出一些预测,比如未来一定时间内的预期数据复制延迟。而且,大多数互联网公司的流量往往有不断增长的趋势,我们需要持续的提高复制处理的能力,来应对数据流量的增加。
数据库复制的容量规划和分析,其实就是在三个基本变量中辗转反侧。哪三个变量呢?就是用户流量大小、传输复制容量的能力以及传输复制的延迟。给定任何两个变量,都可以确定第三个 变量。
具体来说,数据库复制的容量规划和分析可以帮助回答以下几个问题:
- 未来的流量预测
- 根据历史流量的数据,预期未来的流量
- 数据复制延迟的预测
- 给定传入流量和复制处理能力,预期的复制延迟是多少?
- 这些数据,可以帮助我们确定复制延迟的 SLA。
- 确定数据复制的容量
- 在假设给定传入流量和最大允许的复制延迟(SLA)的情况下,确定我们需要部署多少数据复制容量?
- 这将有助于定义复制容量需求。
- 确定用户流量的增长空间
- 在给定复制的容量和延迟的 SLA 的情况下,确定最大可以支持多少用户流量?
- 这有助于计划将来的容量要求。
- 帮助确定延迟SLA
- 是在给定输入流量,现在或将来的复制处理能力的情况下,如何确定适当的 SLA?
- 不能过度承诺或低估 SLA。
解决方案如何落地
必须知道一点的是,数据的传输复制模块,其实是一个排队系统,是一个有无限缓冲的先入先出队列
- 从输入角度来讲,所有的用户流量数据都进入一个先入先出队列,然后传输复制模块会一个个的处理
- 如果在任何时候,用户流量大小超过传输能力,那么队列就会加长。反之,队列就会变短
- 这里,我们需要关注的是所有事件的“最长”等待时间,并根据这个值来决定SLA
你还记得我们在最开始对用户流量特征的观察吗?基于前面对流量的观察和测量,你认为该用什么模型来预测未来数据呢?
- 没错,最好把用户流量看出是一个时间序列模型,并通过这个模型来预测未来的数据
- 对于这类时间序列数据,通常选择 ARIMA(Autoregressive Integrated Moving
Average,自回归积分移动平均线)模型,来进行建模和预测。 - 什么是 ARIMA 呢?ARIMA 是一个常见的统计模型,是用来对时间序列进行预测的模型。它的全称是自回归移动平均模型(ARIMA, Autoregressive Integrated Moving Average Model)。
ARIMA 的工作机制有较大的计算开销,所以 ARIMA 不太适合大规模的建模,比如超过几百个数据点就不太合适了。
- 一般来讲,对于一年内的预测,ARIMA 只能预测到每天的尺度,因为一年只有 365 天。
- 对这个模型来讲,比天更细的粒度,不太适合。
- 但是我们这里的容量规划,又偏偏需要获取更加精细粒度的数据,比如每小时的预测数据,而不仅仅是每天的数据。
考虑到这几个特点,对于较长期的预测,比如半年期间的话,该怎么办呢?我们提出了两步预测模型来获取未来的每小时流量
- 第一步是工作在星期这个粒度上,获取每周的聚合流量;
- 第二步再将聚合数字“分布”(或“转换”)到一天内的每个小时。
这样做的好处是,一方面减少了数据的点数,比如一年也就 52 周;另一方面仍然可以得到每小时的数据。
这个第二步的转换,也就是流量从一周到小时的“转换”,是怎么做的呢?
- 采用了一个季节性指数,该指数大致代表一周内每小时的流量部分。你也可以直观地把这个指数看作是一个分配函数。
- 下图就是一周到小时的季节指数展示。一周内有 168 小时,也就是有 168 个数据点。这些数据点的值大小,其实就是分布概率。所有的数据点的值加在一起正好等于 1。
具体来说,该模型包括两个步骤:
- .使用 ARIMA 模型,预测未来几周的每周总体流量;
- 使用季节指数,预测一周内每个小时的流量
采用这个模型就可以回答我们前面提出的问题了,比如可以轻松地预测未来每小时的流量。
那么具体的算法怎么实现呢?比如回答与容量规划相关的其他几种类型的问题,我们采用了数值计算和二进制搜索的类似机制。
这里的二进制搜索原理,不难理解,其实就是不断地尝试,直到找到一个最合适的值为止。比如我们需要一个确定总的容量,一方面希望容量越小越好(因为省钱);另一方面又不能违反传输复制延迟的 SLA。
怎么用二进制搜索呢?
- 就是随便假定一个容量值,然后带入模型去推导出传输复制的延迟,然后判断这个延迟是否违反了 SLA。如果违反了,说明我们一开始的容量值太小,应该增加一点。
- 怎么寻找呢,就是每次取中间的值,重新推导。这个过程如同二进制搜索。
为了便于理解,我们假设时间粒度为每小时。
- 一旦获得流量,则将使用数值计算方法,来判断任何时间点的复制延迟。
- 基于数值计算的结果,也就可以使用二进制搜索,来获得特定流量所需的数据复制容量。
同样的道理,还可以用此模型,来确定任何固定场景可以支持的最大用户流量,以及相应的将来日期。也就是根据预测的增长,未来什么时候用户的流量就会超越这个最大用户流量。
最后,检查每种场景下的预期复制延迟,我们还可以确定适当的复制延迟 SLA。
任何针对流量的预测模型,都不可避免地会出现误差。产生预测误差的主要原因是网络流量的高变化性。
当实际流量小于预测流量时,实际的复制延迟也将低于预期延迟。注意,这种低估误差不会违反基于预测值定义的延迟性能 SLA。唯一付出的成本,是部署了一些额外的资源。但是,当预测的流量小于实际流量时,就可能会违反延迟 SLA。
为了解决此问题,在确定各种指标(例如 SLA)时,有必要预留一定的空间来避免预测误差。预留的量取决于一系列因素,包括:
- 预测模型的历史表现,也就是预测的精准度;
- 违反延迟 SLA 的后果,包括业务付出的成本
- 过度部署容量资源的成本。
好了,到这里这个规划和分析模型就讲完了,内容比较多,我们来复习一下。对于数据库复制系统来说,可以把它当作一个排队系统来对待。不断到来的输入流量,是一个有季节性的不断变化的时间序列。通过对这个时间序列来适当建模,我们可以比较准确地预测未来的输入流量。有了预测的输入流量,就可以根据服务处理的速度和复制延迟的关系,来计算出其他结果:比如预期的复制延迟,所需要的复制容量等等。