数据一致性校验算法 #
适用场景:数据迁移、弹性伸缩、数据同步。
CRC32 一致性校验 #
类型 : CRC32_MATCH
可配置属性
无
说明:适用于 MySQL 及衍生数据库,仅限存量数据,需要停写,匹配所有记录的 CRC32。
使用示例
CHECK MIGRATION jobId BY TYPE (NAME='CRC32_MATCH');
CHECK RESHARDING jobId BY TYPE (NAME='CRC32_MATCH');
数据匹配一致性校验 #
类型 : DATA_MATCH
匹配所有记录的所有字段值。 适用于所有类型的数据库。
可配置属性 :
| 属性名称 | 数据类型 | 默认值 | 说明 |
|---|---|---|---|
| chunk-size | int | 1000 | 一次查询操作返回的最大记录数 |
| streaming-range-type | String | SMALL | 流式查询范围类型。选填。取值:SMALL(小范围流式查询)、LARGE(大范围流式查询) |
| query-logic-table-name | String | 校验哪个业务表;没配置query-condition的情况校验全表。选填。 | |
| query-condition | String | 校验业务表的条件。选填。前后必须以英文括号开头和结尾(),示例:(id>=1001 AND id<2000) |
streaming-range-type属性补充说明:
| 取值 | 说明 | 优势 | 劣势 | 逻辑查询 SQL 示例 |
|---|---|---|---|---|
| SMALL | 小范围流式查询,一次查询的记录数限制在chunk-size的100倍 | 1)所有数据库都可以支持,2)执行查询次数较少,性能好或较好(视不同数据库而定) | 分片表情况下,由于 MySQL 协议设计的局限性,关闭 ResultSet 会读完剩余记录,对性能有损耗 | SELECT * FROM sbtest1 ORDER BY id ASC LIMIT 100000 |
| LARGE | 大范围流式查询,查询范围是全部 | 执行查询的次数少,性能好 | 1)部分数据库支持不好,2)部分数据库使用代价偏高,3)单次查询占用数据库连接时间长 | SELECT * FROM sbtest1 ORDER BY id ASC |
校验范围说明:
- 如果指定了校验范围(通过
query-logic-table-name和query-condition参数),可以进行多轮部分数据校验。当前表或分段校验不通过的话过段时间再次校验,校验通过后不断迭代校验范围继续校验。可以校验完所有记录或者抽样校验其中部分记录,根据需要自行选择。当判定数据校验没问题后即可进行流量切换。 - 如果没有指定校验范围,仅校验一轮所有存量数据,校验的时候需要业务停写。
使用示例 :
CHECK MIGRATION jobId BY TYPE (NAME='DATA_MATCH', PROPERTIES('chunk-size'='1000','streaming-range-type'='SMALL'));
CHECK MIGRATION jobId BY TYPE (NAME='DATA_MATCH', PROPERTIES('chunk-size'='1000','streaming-range-type'='LARGE'));
CHECK RESHARDING jobId BY TYPE (NAME='DATA_MATCH', PROPERTIES('chunk-size'='1000','streaming-range-type'='SMALL'));
CHECK RESHARDING jobId BY TYPE (NAME='DATA_MATCH', PROPERTIES('chunk-size'='1000','streaming-range-type'='LARGE'));
CRC32 一致性校验(商业版) #
类型 : SphereEx:BATCH_CRC32_MATCH, SphereEx:DATA_CONSISTENCY_CHECK_CRC32_MATCH
可配置属性:
无。
说明:适用于 MySQL 及衍生数据库,仅限存量数据。需要停写,批量匹配所有记录的 CRC32。
使用示例 :
CHECK MIGRATION jobId BY TYPE (NAME='SphereEx:BATCH_CRC32_MATCH');
CHECK RESHARDING jobId BY TYPE (NAME='SphereEx:BATCH_CRC32_MATCH');
实时一致性校验(商业版) #
实验性功能
类型 : SphereEx:DATA_DIFF
可配置属性 :
| 属性名称 | 数据类型 | 默认值 | 说明 |
|---|---|---|---|
| chunk-size | int | 1000 | 一次查询操作返回的最大记录数 |
| streaming-range-type | String | SMALL | 流式查询范围类型。选填。取值:SMALL(小范围流式查询)、LARGE(大范围流式查询) |
| diff-storage-type | String | 数据差异存储介质类型。取值:DATABASE(存储到某个 proxy 存储单元) | |
| diff-storage-unit-name | String | 数据差异存储到哪个 proxy 存储单元,比如 ds_0。diff-storage-type为DATABASE时必填 | |
| diff-table-name | String | 数据差异存储到哪个表(需要确保该表名没有被占用)。diff-storage-type为DATABASE时必填 | |
| incremental-idle-seconds-threshold | int | 5 | 增量数据不再活动的时间阈值(单位:秒),超过这个时间即可认为本轮次没有增量数据了。diff-storage-type为DATABASE时必填 |
| inventory-ignored | bool | false | 是否忽略存量数据校验。数据同步场景可以设置为true |
| query-logic-table-name | String | 校验哪个业务表;没配置query-condition的情况校验全表。选填。开启后会自动关闭增量数据校验 | |
| query-condition | String | 校验业务表的条件。选填。前后必须以英文括号开头和结尾(),示例:(id>=1001 AND id<2000) |
说明:动态匹配所有记录的所有字段值,源端和目标端的数据差异会记录到配置的存储介质(一般是差异表),当最终3个轮次检测到没有增量数据且没有差异数据即为校验通过。
diff-table-name差异表名补充说明:需要确保该表名没有被占用。因为多个校验作业可以并发运行,如果不小心使用了相同的差异表,最终结果大概率会出问题。为了避免这样的情况发生,所以在校验作业启动的时候会检查指定的差异表是否已经存在,如果已经存在那会报错并终止校验作业的运行。操作方法:1)选取新的不冲突的表名,2)如果确定已存在的差异表没有用了,可以先删除,然后复用这个名称。
streaming-range-type属性补充说明:
| 取值 | 说明 | 优势 | 劣势 | 逻辑查询 SQL 示例 |
|---|---|---|---|---|
| SMALL | 小范围流式查询,一次查询的记录数限制在chunk-size的100倍 | 1)所有数据库都可以支持,2)执行查询次数较少,性能好或较好(视不同数据库而定) | 分片表情况下,由于 MySQL 协议设计的局限性,关闭 ResultSet 会读完剩余记录,对性能有损耗 | SELECT * FROM sbtest1 ORDER BY id ASC LIMIT 100000 |
| LARGE | 大范围流式查询,查询范围是全部 | 执行查询的次数少,性能好 | 1)部分数据库支持不好,2)部分数据库使用代价偏高,3)单次查询占用数据库连接时间长 | SELECT * FROM sbtest1 ORDER BY id ASC |
使用示例 1:
CHECK MIGRATION jobId BY TYPE (NAME='SphereEx:DATA_DIFF', PROPERTIES('diff-storage-type'='DATABASE','chunk-size'='1000','streaming-range-type'='SMALL','diff-storage-unit-name'='ds_2','diff-table-name'='spex_cnschk_1','incremental-idle-seconds-threshold'='999999999'));
CHECK RESHARDING jobId BY TYPE (NAME='SphereEx:DATA_DIFF', PROPERTIES('diff-storage-type'='DATABASE','chunk-size'='1000','streaming-range-type'='SMALL','diff-storage-unit-name'='ds_2','diff-table-name'='spex_cnschk_1','incremental-idle-seconds-threshold'='999999999'));
以上示例代表分别给数据迁移和弹性伸缩做实时一致性校验,存储到 proxy ds_2存储单元、spex_cnschk_1表。
增量数据不再活动的时间阈值999999999秒。这种配置下数据一致性校验作业不会主动退出,需要人工判断好退出时机并手动执行 DistSQL 操控。
使用示例 2:
CHECK MIGRATION jobId BY TYPE (NAME='SphereEx:DATA_DIFF', PROPERTIES('diff-storage-type'='DATABASE','chunk-size'='1000','streaming-range-type'='SMALL','diff-storage-unit-name'='ds_2','diff-table-name'='spex_cnschk_2','query-logic-table-name'='sbtest1','query-condition'='(id>=1 AND id<2000)'));
CHECK RESHARDING jobId BY TYPE (NAME='SphereEx:DATA_DIFF', PROPERTIES('diff-storage-type'='DATABASE','chunk-size'='1000','streaming-range-type'='SMALL','diff-storage-unit-name'='ds_2','diff-table-name'='spex_cnschk_2','query-logic-table-name'='sbtest1','query-condition'='(id>=1 AND id<2000)'));
以上示例代表分别给数据迁移和弹性伸缩做实时一致性校验,只校验sbtest1表,限定校验范围(id>=1 AND id<2000);差异存储到 proxy ds_2存储单元、spex_cnschk_2表。
优势:
- 适用于所有数据库。当前在 MySQL 数据库较为成熟。
- 支持存量数据和增量数据校验,不需要停写业务才能开始校验,只需要在最后阶段短暂停写。
流量切换时机评估 #
1,增量数据需要校验、校验过程一直有人值守(大数据量情况下有操作难度):
- 可以把
incremental-idle-seconds-threshold设置为一个较小的数值,比如15秒;停写后每隔一段时间查询一致性校验进度,当status达到FINISHED即已经完成所有数据的校验,此时已经停止校验。
2,增量数据需要校验、不确定校验完成时间:
- 可以把
incremental-idle-seconds-threshold设置为一个很大的数值,比如999999999秒;这种配置下数据一致性校验作业不会主动退出,会持续校验增量数据直到用户手动停止校验。 - 提前在测试环境验证好,停写后多长时间可以消化完差异表的多少记录数。到线上环境后,查看差异表(配置的
diff-table-name)的记录数以及里面的记录是否会快速迭代,预估差异表的记录数是否会在可接受的时间内消化完。业务停写后观察差异表,当差异表为空持续一段时间,手动抽查重要表的最新增量数据是否同步成功,都确认没问题后即可进行流量切换。
3,小范围多轮校验(部分增量数据可能校验不到):
- 给每个业务表分别指定校验范围做校验(通过
query-logic-table-name和query-condition参数),当前表或分段校验不通过的话过段时间再次校验,校验通过后不断迭代校验范围继续校验。可以校验完所有记录或者抽样校验其中部分记录,根据需要自行选择。当判定数据校验没问题后即可进行流量切换。