1. 赛题描述
题目主要解决的是数据同步领域范畴:实时增量同步,主要的技术挑战为模拟数据库的主备复制,提供"高效"的实时同步能力。即给定一批固定的增量数据变更信息,程序需要收集增量变更信息,并进行一定的数据重放计算,然后将最终结果输出到给定的目标文件中。增量数据的变更信息为了简化处理,会给出明文的数据,主要包含数据库的 insert/update/delete 三种类型的数据。具体的增量数据变更信息的数据格式见环境描述部分。数据重放主要是指模拟数据库的 insert/update/delete 语义,允许使用一些中间过程的存储。
2. 环境描述:
2.1 整体格式
有 2 台机器,简称 A、B 机器,A 机器里会保存增量数据文件并且在固定的目录下提供 10 个文本文件,每个文本文件大概为 1GB 左右。每个文件有若干条变更信息。每条变更信息的记录由多列构成。文本中每行记录的格式为:
binaryId | timestamp | schema | table | 变更类型 | 列信息 | 变更前列值 | 变更后列值 | 列信息 | 列值 | ... |
---|
2.2 格式解释
a. binaryId: 一个唯一的字符串编号,例子:000001:106
b. timestamp
- 数据变更发生的时间戳,毫秒精度,例子:1489133349000
c. schema/table
- 数据变更对应的库名和表名
d. 变更类型(主要分为 I/U/D)
- I 代表 insert, U 代表 update, D 代表 delete
d. 列信息
- 列信息主要格式为,列名:类型:是否主键
- 类型主要分为 1 和 2
- 1 代表为数字类型,数字类型范围为 0<= x <= 2^64-1
- 2 代表为字符串类型,0<= len <= 65536
- 是否主键:0 或者 1 (0 代表否,1 代表是)
- 例 1: id:1:1 代表列名为 id,类型为数字,是主键
- 例 2: name:2:0 代表列名为 name,类型为字符串,非主键
e. 列值
- 主要分为变更前和变更后,NULL 代表物理值为 NULL(空值),(可不考虑字符串本身为"NU LL"的特殊情况)
- insert 变更,只有变更后列值,其变更前列值为 NULL,会包含所有的列信息
- upadate 变更,都会有变更前和后的列值,会包含主键和发生变更列的信息(未发生变更过的列不会给出,不是全列信息)
- delete 变革,只有变更前列值,会包含所有的列信息
2.3 格式例子
实际例子:
- 000001:106|1489133349000|test|user|I|id:1:1|NULL|102|name:2:0|NULL|ljh|score:1:0||98|
- 000001:106|1489133349000|test|user|U|id:1:1|102|102|score:1:0|98|95| //执行了变更 update score=95 where id=102
2.4 注意事项
- 每一行代表一条变更数据,注意几个数据变更场景
- 表的主键值也可能会发生 update 变更
- 表的一行记录也可能发生先 delete 后 insert
- 整个数据变更内容是从零条记录开始构建的,即为任意一条行记录的 update 之前一定会有对应行的 insert 语句,delete 之前也一定有一条 insert,不考虑 DDL 变更产生列类型变化,也不需要考虑其他异常情况
3. 解决方案架构
3.1 测评环境
-
JDK 环境及 JVM 参数
Java version "1.7.0_80"
Java(TM) SE Runtime Environment (build 1.7.0_80-b15)
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)-XX:InitialHeapSize=3221225472 -XX:MaxDirectMemorySize=209715200 -XX:MaxHeapSize=3221225472 XX:MaxNewSize=1073741824 -XX:MaxTenuringThreshold=6 -XX:NewSize=1073741824 -XX:OldPLABSize=16 -XX:OldSize=2147483648 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UseCompressedOops -XX:+UseConcMarkSweepGC -XX:+UseParNewGC
-
磁盘信息:数据文件全部放在内存,从内存加载 8G 数据时的性能如下,大概写 1.6GB/S,读 4GB/S。
写性能
$ sudo time dd if=/dev/zero of=/home/admin/myram/test bs=8k count=1000000
1000000+0 records in
1000000+0 records out
8192000000 bytes (8.2 GB) copied, 5.15673 s, 1.6 GB/s
0.08user 5.07system 0:05.15elapsed 100%CPU (0avgtext+0avgdata 832maxresident)k
0inputs+0outputs (0 major+249minor)pagefaults 0swaps
读性能
$ sudo time dd if=/home/admin/myram/test of=/dev/null bs=8k count=1000000
1000000+0 records in
1000000+0 records out
8192000000 bytes (8.2 GB) copied, 2.02892 s, 4.0 GB/s
0.07user 1.95system 0:02.02elapsed 99%CPU (0avgtext+0avgdata 832maxresident)k
0inputs+0outputs (0 major+249minor)pagefaults 0swaps
- 网络:100M/S
3.2 整体架构
主要解决的问题:最大并行化和主键更新
-
多线程解析和多线程重放(通用版本)
单线程读,多线程解析和重放,采用分离的 Map 来解决多线程安全问题(不同步),最终结果由主线程合并多个 Map 得到。
-
多线程解析,边解析边重放(大数组跑分版本)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于