【中间件比赛】复赛题目及解决方案架构

本贴最后更新于 2502 天前,其中的信息可能已经斗转星移

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 注意事项

  1. 每一行代表一条变更数据,注意几个数据变更场景
  2. 表的主键值也可能会发生 update 变更
  3. 表的一行记录也可能发生先 delete 后 insert
  4. 整个数据变更内容是从零条记录开始构建的,即为任意一条行记录的 update 之前一定会有对应行的 insert 语句,delete 之前也一定有一条 insert,不考虑 DDL 变更产生列类型变化,也不需要考虑其他异常情况

3. 解决方案架构

3.1 测评环境

  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

  2. 磁盘信息:数据文件全部放在内存,从内存加载 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	
  1. 网络:100M/S

3.2 整体架构

主要解决的问题:最大并行化和主键更新

  1. 多线程解析和多线程重放(通用版本)
    单线程读,多线程解析和重放,采用分离的 Map 来解决多线程安全问题(不同步),最终结果由主线程合并多个 Map 得到。
    Java 中间件比赛

  2. 多线程解析,边解析边重放(大数组跑分版本)
    Java 中间件比赛

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...