社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  DATABASE

小红书自研Binlog Server守护MySQL数据0丢失

小红书技术REDtech • 3 周前 • 90 次点击  


异常情况下的数据丢失问题将极大地影响业务的可用性,尤其在一些核心场景的数据恢复过程更是耗时耗力。在业务支持上我们亟需一种方案,当数据库在发生故障既要保证数据一致性也要减少切换时间,尽可能减少甚至彻底免除人工的介入。


小红书数据库团队提出一种基于Binlog Server的数据一致性解决方案,通过提升半同步复制性能,加速日志传输,在故障时可无侵入现有数据库架构地实现自动补数据,保证数据一致性。现推出的自研 Binlog Server 与 ORC 高可用方案,经过实践已证明可做到:

1)使用极少的资源(1C1G)即可将复制速度提升至300MB/s+,实现了复制性能翻倍;

2)优化了故障切换效率,按照一致性优先原则使用Binlog Server为新主库补数据,有效降低运维成本和业务风险,实现数据库快速数据恢复。

目前该方案已经100%部署于小红书半同步复制集群,在多次切换中为新主库补数据,守护了核心数据库的安全。



2017年 GitLab 数据库工程师误操作,导致18个小时的服务中断并且部分数据永久性丢失,丢失数据影响了大约 5000 个客户和 700 个项目。


2022年某云厂商部分区域 RDS 服务不可用,影响了业务大约 3+小时。


2023年某云数据库出现了自动清理数据的 Bug,导致部分用户的最新数据删除且不可恢复。


2023年 Digital Ocean 托管的部分数据库异常切换,导致部分用户永久丢失 2-5 分钟数据。


核心场景的数据库一旦出现了数据丢失,会极大的影响了业务的可用性。因此,数据库的高可用性和一致性始终是核心业务系统的关键诉求。比如,DBA 同学也刚刚经历了这样惊心动魄的一幕:


💥 某天,数据库 P0 告警突发,核心集群主库宕机!XX同学需要立即与上下游业务紧急联动,定位到数据丢失并完成数据修正。经过一个小时的“救火”操作后,业务才逐渐恢复正常。这一“救火”场景出现,既消耗了大量的人力成本,也影响了系统整体稳定性。因此,亟需一种方案,当数据库在发生故障切换下也能自动保障数据一致性和完整性,彻底免除人工介入


在展开方案介绍之前,我们先来了解 2 个知识:


🙋 什么是 RPO=0?RPO=0 意味着在任何切换或灾难发生后,数据一条都不丢! 如果实现了 RPO=0,当数据库发生宕机时,新的数据库能够100% 自动补齐所有数据,上下游业务不用再担心数据修复事务,极大降低运维压力和业务风险,在高可用里面实现了数据恢复的闭环。


🙋 业内主流OLTP数据库如何实现 RPO=0?业内主流方案主要分为以下三种:



MySQL 复制分为异步复制和半同步复制,其中半同步复制要求从库至少有一台复制成功响应,这样保证至少一台从库保存了日志数据。所以半同步复制的速度决定了主库写入速度的上限。但社区半同步实现复杂,其复制速度较慢,影响了主库写入速度。Facebook方案使用 Binlog Server 加快半同步复制速度,从而提升了主库写入性能,让更多的场景可以使用半同步复制。如果复制延迟太大(网络或者CPU耗尽等场景下),复制会出现自动降级,从半同步复制退化为异步复制,被称为半同步退化半同步退化将影响数据一致性(本质是一种异步复制场景)。


基于方案复杂性和稳定性考虑,我们对比后决定采用 Binlog Server 方案,来实现小红书 MySQL 的 RPO=0,并满足以下条件:


  1. 将半同步复制速度翻倍,Binlog复制速度提升到 300MB/s+;


  2. 对现有 MySQL 架构和复制方案无侵入;


  3. 无缝支持现有 MySQL 高可用架构的切换方案。


1.1 收益概述


相对于社区MySQL半同步+开源ORC高可用组件,自研Binlog Server+自研ORC高可用在半同步复制速度、轻量化部署、数据一致性优先和运维便捷性等场景进行优化,保证 RPO=0。



得益于Binlog Server性能的提升,当出现写入大压力的场景时,Binlog Server可以跟上主库写入速度,并且在故障场景下为新主库提供日志数据。



1.2 性能验证


当前线上采用了同城异可用区 Binlog Server 部署形式,也就是在 MySQL 集群内部署一个同城、不同机房、半同步连接的 Binlog Server 实例,如下图所示:



这样做的目的是为了提升 MySQL 故障恢复的“数据 0 丢失”半径 ,确保在发生机房级故障时,ORC 的切换机制依然能够保证数据的一致性。Binlog Server 的性能显著优于普通从库,在小事务压测条件下,其写入速度可达 300MB/s,且资源消耗极低。凭借高吞吐、低资源消耗的优势,Binlog Server 完全可以部署于异地机房,大幅提升系统在机房级故障下的数据恢复能力,实现 0 数据丢失的主库故障切换。



1.3 切换效果验证


得益于 Binlog Server 的高吞吐能力,以及半同步复制特性,可以确保 Binlog Server 中的数据始终保持最新。即使遇到如机房断网等严重故障场景,结合 ORC 的选主策略,可以实现 MySQL 故障切换过程中数据 0 丢失。



目前 Binlog Server 配合 ORC 的数据一致性方案已经开始灰度,线上已经覆盖到半同步核心集群,半同步集群覆盖比例达到100%


下面的案例的切换效果如下,详细展示了切换过程中Binlog Server作为临时主库给下游补充数据。




2.1 复制速度分析


首先关注一下影响主从延迟的原因。下图是MySQL主从复制的完整的数据链路图。绿色框表示执行线程,黄色框表示实例(主库/从库)的Binlog,因为Binlog Event中带有时间戳,所以主从延迟表示为从库的Binlog时间 - 主库的Binlog时间。红色的框为Relaylog,可以理解为从库来不及处理的数据的临时在磁盘存储的文件。紫色为每个worker thread对应的处理队列(内存结构)。


从图中可以看到,整个复制链路经历的环节特别多,任何一个环节速度跟不上都会造成主从延迟比较大。其中IO Thread和Dispatch Thread之间的干扰会降低半同步复制速度(包括不限于共享Mutex锁,IO串行化,共享复制位点信息等),如果IO线程处理速度慢将影响Master节点对业务响应的速度。复制速度慢一直是MySQL社区存在的问题,否则也不会有各种Binlog Server方案。



2.2 行业方案调研


在MySQL不满足需求的情况下,参考调研市场上已有的Binlog Server,总结各个方案的优缺点。



根据行业的调研和数据库现状,从上面的部署来看,Facebook Binlog Server方案是最合适的,其功能丰富,和现有系统能兼容。但其实现未开源,将按照其设计思路设计自研Binlog Server。


2.3 需求定位


  1. 功能:支持半同步,提供RPO=0的方案;支持级联架构,在主从切换时为从库补充Binlog数据;


  2. 性能:半同步复制时提供更高复制速度,相对于主库无丢失;


  3. 运维:支持MySQL管理命令,无需外部系统改造;轻量化部署,1C1G资源即可满足需求;


  4. 稳定性:支持crash recovery,保证数据一致性;


  5. 兼容性:兼容MySQL 生态的各种解析工具,无需单独开发。



Binlog Server架构与其基本数据流和控制流基本如下图所示。下图所示为级联架构(对Binlog Server来说最复杂的场景),同时支持Master和Slave分别作为上下游,表现类似一个MySQL实例。其中绿色线表示Binlog Server控制流,主要是从Admin管理员发送的管控SQL,在SQL解析器处理后,在Manage模块进行处理,可以对MasterSession(和主库的连接),SlaveSession(和下游从库的连接),Binlog(本地存储文件)进行管理。红色线就是数据流,主要是存放主库发送来的Binlog数据,存储在本地并通过SlaveSession向下游发送。具体模块将一一展开介绍。


下面介绍3.1-3.5节为各个模块实现细节,3.6节将介绍Binlog Server和ORC配合主从切换。


3.1 MySQL协议支持


为了满足上面的数据流程,需要支持如下协议的解析&处理:


  1. BinlogServer->Master,Slave->BinlogServer进行认证、连接和状态获取SQL

  2. Admin->BinlogServer管理线程的认证和连接

  3. Admin->BinlogServer发送的COM命令

  4. BinlogServer->Admin发送的ResultSet

  5. Master->BinlogServer, BinlogServer->Slave发送的Event格式


这里需要按照MySQL协议规定的注册、握手、COM格式、ResultSet格式以及EVENT格式处理, 对于协议的发送将复用MySQL Client的库,但是协议解析和数据包封装需要Binlog Server处理。以Binlog为例,其基本格式如下图所示,需要分别对Header和Footer处理,提取各个字段。








3.2 SQL语法支持


为了方便ORC进行管理,对现有的运维系统和高可用系统无侵入。需要Binlog Server支持SQL语法,可以减少周围系统的开发和适配成本。在这里我们制作了一个语法解析器支持特定SQL类型。联调和部署时遇到新SQL支持,十分方便进行新语法的支持。


这里无法采用MySQL解析器,因为MySQL的词法解析部分全部自行编写,而不是采用FLEX(全局变量,不支持多线程并发),以提升SQL解析性能,从而支持每秒几十万次的SQL解析速度,缺点就是代码非常复杂,难以将所需功能进行剥离。但是Binlog Server的SQL语法只是用来做运维管控,没有对高并发的需求,所以在FLEX词法解析过程即使串行化,依然有几千次的解析速度,完全满足管控SQL需求。可以使用AI写bison和flex文件语法解析器文件,效果非常好。


如下图所示,当输入的字符串经过词法解析器(取出token)和语法解析器(获得语法树),就可以提取需要的语法树信息。



从整个SQL执行视角来看,SQL执行分为三个阶段:


  1. 语法解析阶段

  2. SQL命令执行阶段

  3. SQL结果输出阶段


支持 start slave 和 stop slave 等运维命令,保持slave的启停方式和MySQL一致。以start salve为例,下面展示了 SQL 解析和执行过程,首先会建立一个新 session 和 MySQL 客户端保持联系,然后用户发出 start slave 命令,按照COM_QUERY进行解析。在自定义语法解析器中,将start slave 标记为 SQLCOM_START_SLAVE,然后执行 节点注册过程(详细过程见下一节),最终返回结果集。



3.3 节点注册


Binlog Server支持级联架构,既可以作为Slave节点从上游接收并保存Binlog,也可以作为Master向下游发送Binlog。因此其必须具有双向注册能力,需要遵守MySQL节点注册的规范,模拟作为从库或者主库进行注册。




3.4 半同步支持


和异步复制相比,半同步发送Binlog过程有变化,这将影响BinlogServer处理的过程。如下图所示,Master节点生成了Binlog文件(由一个个Event构成),在发送Event时,会在每个Event前添加Header。每个Header由2字节构成,第一字节为0xEF(Magic Number)用于校验,第二字节为0x1/0x0,用于指示从库是否发送ACK。当数据发送到BinlogServer以后,会先处理Header信息,确定是否需要发送ACK,如果需要发送,就将MasterLog位点信息发送给主库。主库收到ACK后确认这些数据已经在下游持久化,即可在主库InnoDB进行提交(AFTER_SYNC模式)。


这里需要注意一点,如果ACK信息丢了,后面的ACK确认的位点会自动包含前面的位点,这样保证发送过程不至于中断。



3.5 文件管理和数据一致性


Binlog文件管理主要分为两部分,第一是Binlog文件管理;第二是Crash时的数据一致性。


  1. 文件管理:参考MySQL Binlog设计,使用索引文件记录Binlog元数据信息。所以采用索引文件+数据文件结合的方式记录。


  2. 数据一致性:Crash Safe重点强调宕机场景(非预期场景),但是对于预期内的关机也保持了一致性。



为了保证Binlog索引文件和数据文件的一致性,参考MySQL修改Binlog的方式。变动时先修改Binlog索引文件,创建新的临时文件,然后再修改Binlog数据文件,最后将临时的索引文件覆盖写为正式的索引文件。这个过程中如果出现了宕机等场景,那么根据临时文件和Binlog文件是否修改,决定该操作是提交还是回滚,从而保证了数据的一致性。


3.6 高可用支持


当主库宕机时,希望最终选举出来一个同机房的新主库为业务提供服务。但是同机房的从库不一定是数据最多的从库。因此需要增加补数据的环节,如下图所示。




高可用组件ORC在数据切换的时候,会分为两个阶段进行。


1M:根据GTID最大原则选出第一轮备选主库,开始补数据。这一轮没有偏好,尽量选择GTID最长的作为Master来给所有节点补数据。


2M:根据同机房 & GTID最长选择第二轮主库,作为新的Master。这一轮存在偏好,例如选择和老主库在同一个机房的Slave作为新主库。



主库故障和恢复流程简化过程上图所示。部署形态上采用Master挂载2个半同步的BinlogServer以保证数据不丢失,Master同时挂载若干个异步复制的Slave节点。


如果主库宕机(不可恢复),如图2所示:


  1. ORC 1M阶段,将选择两个Binlog Server中GTID最长的一个作为临时Master,给其他所有节点补数据。这一轮选举大概率是同机房的Binlog Server。如果同机房Slave和Binlog Server GTID相同(写入量很小,所有机器数据没有延迟), ORC选择没有偏好,能将GTID补上即可。


  2. ORC 2M阶段,同机房的Slave将作为新的主库,将其他所有的节点挂载到新主库上。


  3. 经过ORC 2M阶段,数据库集群即可对外提供服务。同时在本机房内,异步补充一台新从库。


  4. 新从库补充完毕后,整体的部署将和故障前完全一致。


在这个过程中,Binlog Server的添加不会对ORC选举额外造成负担。因为1M选择时,仍然按照GTID最长原则。所以Binlog Server提供足够高的性能后,ORC会自然选择到Binlog Server。只是在2M选择的时候,需要排除Binlog Server作为新的备选主库即可。



Binlog Server是一个消耗资源极少的轻量化Binlog 存储节点(1C1G即可)。除了提供一致性解决方案以外,未来也可以在其他使用Binlog的场景中发挥作用。


  1. 在从库扩容、库表拆分的场景中使用Binlog Server补充Binlog数据;


  2. Binlog Server支持标准MySQL协议,DTS、Canel等可以从Binlog Server拉取数据,降低主库压力;


  3. Binlog Server后端使用S3(配合S3FS)作为存储,将节省Binlog保存成本,保持更长时间的Binlog数据。



张凡凡

小红书关系型数据库研发工程师,主要负责小红书关系型数据库内核研发。


周旭峰

小红书关系型数据库研发工程师,主要负责小红书关系型数据库高可用系统研发。



正式员工招聘


NoSQL数据库研发工程师/研发专家  (KV/Redis/KVCache等方向)

分布式数据库研发工程师/专家-存储&数据库  (图/表/向量/多模数据库等方向)

分布式存储研发工程师/研发专家 (块/文件/对象/存储底座等方向)


以上岗位点击链接即可直达投递入口~


也欢迎感兴趣的朋友投递简历至:

REDtech@xiaohongshu.com

并抄送至下方邮箱以获得最快速响应:

linzi@xiaohongshu.com


图片
图片
往期精彩内容指路 

小红书hi lab开源多语言文档布局解析模型dots.ocr,1.7B小模型实现SOTA性能

小红书JDK升级带来10%整体性能提升,这份升级指南收好了!

万字干货:小红书 hi lab 团队关于奖励模型的一些探索



添加小助手,了解更多内容

微信号 / REDtech01

图片

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/185428
 
90 次点击