摘要:7月20日,腾讯云北京三区部分云硬盘IO异常,导致前沿数控技术公司的线上生产数据完全丢失。腾讯云方面回应这是极小概率事件。即使是再小的概率,一旦发生,对于企业而言面临的可能都是灭顶之灾。本文将带你深入解读在面对数据安全性要求更为严苛的金融场景下,OceanBase是如何从容应对和处理“静默错误”的。
本文作者
陈群,现任蚂蚁金服OceanBase团队高级技术专家,2010年加入支付宝后从事分布式事务框架的研发,2013年加入Oceanbase团队,目前负责存储引擎相关的研发工作。
“数据丢失事件”回溯
7月20日,北京清博数控科技有限公司所属“前沿数控”平台一块操作系统云盘,因受腾讯云北京三区部分物理硬盘固件版本bug导致的静默错误(写入数据和读取出来的不一致)影响,文件系统元数据损坏。
7月20日,腾讯云用户告知故障状态,并组织技术专家尝试修复数据,最终仍有部分数据完整性校验失败。
随即,“前沿数控技术”通过网媒发声,表示他们对腾讯云“99.9999999%数据可靠性,搭载了云硬盘三副本存储策略”非常存疑,认为有夸大之嫌。
腾讯云则表示,硬盘静默错误是在极小概率下被触发,他们随即对固件版本有bug的硬盘全部进行下线处理。
静默错误
腾讯云丢失数据的事件一经爆出就受到广泛热议,根据官方给出的说法,原因大概可以归结为以下两点:
- 首先,一个数据副本中的数据出现了静默错误
- 其次,在数据迁移的过程中违规操作,关闭了数据校验,导致三副本均复制了错误的数据
OceanBase的应对和处理
OceanBase作为分布式数据库,同样也使用了三副本的容灾模式,由于应用于金融场景,事实上对于数据安全性的要求会更加苛刻。那么对于静默错误,OceanBase是如何从容应对和处理的呢?
和传统数据库不同,OceanBase的存储引擎是基于LSM-Tree架构的,数据被分为两部分:动态数据(MemTable)和静态数据(SSTable)。所有的数据修改(插入、更新、删除)都会先写入MemTable,并通过Paxos协议将Redo Log同步到三副本;MemTable中的数据会在合适的时候通过合并的方式转入SSTable,SSTable是只读的。在整个过程中,数据会有多次落盘,写Redo Log时每个副本都需要将Redo Log落盘;在合并时,每个副本都需要将合并后的SSTable落盘。
Redo Log是如何应对静默错误的?
在每条Redo Log的头部,我们都会记录这条RedoLog的校验和,在做网络传输和日志回放时,都会强制对每条日志的校验和进行校验。这样我们保证了三副本同步到的内存数据至少是不会错的,如果一条日志中的数据出现了静默错误,那么这条日志一定不会被同步到其他副本。
比较麻烦的是进程重启,在进程重启时,如果之前落盘的Redo Log出现了静默错误,校验和仍然可以帮助我们将错误识别出来,但是整个进程会重启失败。考虑到三台服务器同时出现静默错误的概率不是特别大,另外两个副本的Redo Log仍然可以帮助我们把数据补齐。
SSTable是如何应对静默错误的?
在数据结构上,一个SSTable是由很多宏块组成的,宏块是定长的,大小是2M,类似于MySQL或者Oracle的Extent,宏块是最小的写IO单位;一个宏块又由很多微块组成,微块是变长的,默认大小大约是16K,类似于MySQL或者Oracle的Page,微块是最小的读IO单位。
首先对于每个微块,我们都会在微块头部记录整个微块的校验和,在每次数据读取时,我们都会对微块根据校验和进行校验,这样我们就保证用户读到的数据一定是正确的。其次对于宏块,我们会在宏块头记录整个宏块的校验和,用于数据的复制迁移。当服务器出现故障或者需要做负载均衡时,系统会自动做数据副本的复制迁移,在目的端写入数据之前,会对每个宏块的校验和进行校验,保证写入的数据是正确的,这样我们就保证静默错误不会扩散。
出了静默错误后能够处理当然还是不够的,我们还需要能够将静默错误尽早识别出来,因此我们在后台会有个定期巡检的任务,定期读取磁盘上的宏块来做校验,一旦发现有数据错误就会进行预警。发生静默错误后,我们可以把错误的数据副本删除掉,再通过复制迁移的方式从其他服务器将副本拷贝过来补齐。
冷备——最后的保障
在线上操作时,运维同学通常承担着巨大的风险,一旦操作不慎就会导致灾难性后果。三副本只是尽量保证在硬件故障下,数据不会丢失;但如果运维同学操作失误,直接将数据删除,那么我们如何将数据找回呢?
OceanBase提供了备份恢复的功能,可以将数据备份到外部的NFS或者是分布式存储上。当发生运维失误时,还是可以通过备份恢复的方式将数据找回。而对于NFS或者分布式存储,可以通过RAID或者纠删码的方式来再做一份容灾。
不止于此,我们希望做得更多
目前OceanBase已经通过以上几种手段来保证容灾,那么做到这些就足够了么?当然不是,我们还需要做的更多。对于运维同学drop table、truncate table之类的操作,OceanBase已经提供了回收站的功能,来帮助做数据恢复。但是对于Delete之类的操作,目前仍然只能通过冷备的方式来找回数据。未来我们会提供FlashBack的功能来方便做快速的数据找回。
此外对于静默错误,目前我们也只能通过复制SSTable的方式来做恢复,同时静默错误也会影响到数据查询。考虑到出现静默错误的数据通常不会太多,我们可以通过拷贝宏块的方式做内部的自恢复。不影响用户查询的同时,也会极大减轻运维同学的负担。