阿里巴巴分布式数据库
-
Upload
griffith-fields -
Category
Documents
-
view
73 -
download
10
description
Transcript of 阿里巴巴分布式数据库
阿里巴巴分布式数据库—— 原理、实现和应用
2012.7
集团共享技术平台分布式数据库
邱硕
分布式数据库中间件App App App App
Cobar
Oracle MySQL MySQL MySQL
ErosaOracle
ErosaMySQL
ErosaMySQL
ErosaMySQL
Eromanga
Otter
Oracle MySQL MySQL
Otter
ErosaOracle
ErosaMySQL
ErosaMySQL
Eromanga
• 性能 容量 高可用• 数据消费时效性• 跨机房数据同步
ASCDW...
分布式数据库中间件App App App App
Cobar
Oracle MySQL MySQL MySQL
ErosaOracle
ErosaMySQL
ErosaMySQL
ErosaMySQL
Eromanga
Oracle MySQL MySQL
Otter
• 性能 容量 高可用• 数据消费时效性• 跨机房数据同步
ErosaOracle
ErosaMySQL
ErosaMySQL
Eromanga
OtterASCDW...
分布式数据库中间件App App App App
Cobar
Oracle MySQL MySQL MySQL Oracle MySQL MySQL
Otter
ErosaOracle
ErosaMySQL
ErosaMySQL
Eromanga
• 性能 容量 高可用• 数据消费时效性• 跨机房数据同步
ErosaOracle
ErosaMySQL
ErosaMySQL
ErosaMySQL
Eromanga
OtterASCDW...
分布式数据库中间件App App App App
Cobar
Oracle MySQL MySQL MySQL
ErosaOracle
ErosaMySQL
ErosaMySQL
ErosaMySQL
Eromanga
Oracle MySQL MySQL
ErosaOracle
ErosaMySQL
ErosaMySQL
Eromanga
• 性能 容量 高可用• 数据消费时效性• 跨机房数据同步
OtterASCDW... Otter
分布式数据库中间件App App App App
Cobar
Oracle MySQL MySQL MySQL
ErosaOracle
ErosaMySQL
ErosaMySQL
ErosaMySQL
Eromanga
Oracle MySQL MySQL
Otter
• 性能 容量 高可用• 数据消费时效性• 跨机房数据同步
ErosaOracle
ErosaMySQL
ErosaMySQL
Eromanga
OtterASCDW...
大纲
中间件引入
Cobar 策略
系统实现
实施应用
Cobar 之前• Oracle 单点数据库• 性能问题
– 中文站 offer 总数: 2008 年 1 亿 -> 2011 年 3 亿– 高峰时: load 30 、 cpu 使用率 90%
• 数据库连接过多• 可用性问题
– Standby 切换故障• 成本和伸缩性问题
– 依赖高成本的硬件设备
OracleMySQL MySQL MySQL
MySQL MySQL MySQL
MySQL MySQL MySQL
单点: MySQL 集群替换 Oracle
MySQL MySQL MySQL
• Oracle 单点数据库• 性能问题
– 中文站 offer 总数: 08 年 1 亿 -> 今天 3 亿– 高峰时: load 30 、 cpu 使用率 90%
• 数据库连接过多• 可用性问题
– Standby 切换故障• 成本和伸缩性问题
– 依赖高成本的硬件设备
Cobar 引入 水平拆分ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL
ID MEMBE_ID INFO
4 test1234 …
5 test1234 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
MySQL
MySQL
CobarApp
• Oracle 单点数据库• 性能问题
– 中文站 offer 总数: 08 年 1 亿 -> 今天 3 亿– 高峰时: load 30 、 cpu 使用率 90%
• 数据库连接过多• 可用性问题
– Standby 切换故障• 成本和伸缩性问题
– 依赖高成本的硬件设备
App ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL
ID MEMBE_ID INFO
4 test1234 …
5 test1234 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
MySQL
MySQL
App
App
App
App
App
App
App
Cobar 引入 连接复用App ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL
ID MEMBE_ID INFO
4 test1234 …
5 test1234 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
MySQL
MySQL
CobarProxy
App
App
App
App
App
App
App
• Oracle 单点数据库• 性能问题
– 中文站 offer 总数: 08 年 1 亿 -> 今天 3 亿– 高峰时: load 30 、 cpu 使用率 90%
• 数据库连接过多• 可用性问题
– Standby 切换故障• 成本和伸缩性问题
– 依赖高成本的硬件设备
Cobar 引入
ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL
CobarApp
X
Cobar 引入 failover
ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL Master1
CobarApp
ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQL Master2
X
MySQLReplication
Cobar 引入 failover
ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
CobarApp
ID MEMBE_ID INFO
1 pavarotti17 …
11 pavarotti17 …
MySQLReplication
MySQL Master1
MySQL Master2
大纲
中间件引入
Cobar 策略
系统实现
实施应用
OracleMySQL MySQL MySQL
MySQL MySQL MySQL
MySQL MySQL MySQL
MySQL MySQL MySQL
拆分数据表
水平拆分
ID MEMBE_ID INFO
1 pavarotti17 …
3 abcd …
4 test1234 …
5 test1234 …
9 abcd …
11 pavarotti17 …
20 abcd …
水平拆分
ID MEMBE_ID INFO
1 pavarotti17 …
3 abcd …
4 test1234 …
5 test1234 …
9 abcd …
11 pavarotti17 …
20 abcd …
拆分字段
水平拆分
ID MEMBE_ID INFO
1 pavarotti17 …
3 abcd …
4 test1234 …
5 test1234 …
9 abcd …
11 pavarotti17 …
20 abcd …
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
f(pavarotti17)= 库1
f(test12
34)=库 1
f(test12
34)=库 1
f(pava
rotti1
7)=库
1
f(abcd)= 库 2
f(abcd)= 库 2
f(abcd)=库2
库 1
库 2
拆分字段
水平拆分
ID MEMBE_ID INFO
1 pavarotti17 …
3 abcd …
4 test1234 …
5 test1234 …
9 abcd …
11 pavarotti17 …
20 abcd …
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
f(abcd)=库2
库 1
库 2
拆分字段
f(pavarotti17)= 库
1
f(test123
4)= 库 1
f(test123
4)= 库 1
f(pava
rotti1
7)=库
1
f(abcd)= 库 2
f(abcd)= 库 2
路由算法
路由算法pavarotti17
f(pavarotti17)= 库
1
路由算法pavarotti17
部分截取
hash( ) = 3170972965401
路由算法hash(pavarott) = 3170972965401 % 1024 = 537
0 1023
路由算法hash(pavarott) = 3170972965401 % 1024 = 537
0 255 256 511 512 767 768 1023
256256256256
分库 1 分库 2 分库 3 分库 4
路由算法hash(pavarott) = 3170972965401 % 1024 = 537
0 255 256 511 512 767 768 1023
256256256256
分库 1 分库 2 分库 3 分库 4
路由算法——扩容hash(pavarott) = 3170972965401 % 1024 = 537
0 127 128 255 256 383 384 511 512 639 640 767 768 895 896 1023
128 128 128 128 128 128 128 128
分库 1 分库 2 分库 3 分库 4
路由算法——扩容hash(pavarott) = 3170972965401 % 1024 = 537
0 127 128 255 256 383 384 511 512 639 640 767 768 895 896 1023
128 128 128 128 128 128 128 128
分库 1 分库 2 分库 3 分库 4 分库 5 分库 6 分库 7 分库 8
原
分库 1 分库 2 分库 3 分库 4
原 原 原
路由算法——非均匀分布hash(pavarott) = 3170972965401 % 1024 = 537
0 511 512 767 768 895 896 1023
512 256 128 128
分库 1分库 2 分库 3 分库 4
拆分表的数据访问—— SQL 转发
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
CobarApp
select * from tb1 where member_id=‘test1234’
拆分表的数据访问—— SQL 转发
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
CobarApp
select * from tb1 where member_id=‘test1234’
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
CobarApp
SELECT * FROM tb1 WHERE member_id IN (‘test1234’,’pavarotti17’,’abcd’)
拆分表的数据访问—— SQL 转发
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
CobarApp
select * from tb1 where member_id in (‘test1234’,’pavarotti17’)
select * from tb1 where member_id in (‘abcd’)
拆分表的数据访问—— SQL 转发
ID MEMBE_ID INFO
1 pavarotti17 …
4 test1234 …
5 test1234 …
11 pavarotti17 …
ID MEMBE_ID INFO
3 abcd …
9 abcd …
20 abcd …
ResultMerger
前台通信
ResultSet:row1row2
ResultSet:row3row4row5
ResultSet:row3row1row4row5row2
拆分表的数据访问——结果返回
多维水平拆分visit 表
product user info
Coca-Cola A …
pepsi C …
Fanta D …
Coca-Cola A …
Coca-Cola C …
Fanta B …
7Up D …
pepsi A …
product user info
Coca-Cola A …
Coca-Cola A …
Coca-Cola C …
product user info
pepsi C …
pepsi A …
product user info
Fanta D …
Fanta B …
product user info
7Up D …
SELECT * FROM visit WHERE user=‘A’
多维水平拆分visit 表
product user info
Coca-Cola A …
pepsi C …
Fanta D …
Coca-Cola A …
Coca-Cola C …
Fanta B …
7Up D …
pepsi A …
product user info
Coca-Cola A …
Coca-Cola A …
pepsi A …
product user info
pepsi C …
Coca-Cola C …
product user info
Fanta D …
7Up D …
product user info
Fanta B …SELECT * FROM visit WHERE product = ‘Coca-Cola’
分库 1 分库 2 分库 3 分库 4
分库 5 分库 6 分库 7 分库 8
分库 9 分库 10
分库 11
分库 12
分库 13
分库 14
分库 15
分库 16
product 值Hash 取模
user 值Hash 取模
0
1
2
3
0 1 2 3
visit 表
USER PRODUCT
• 一张表的多个字段同时作为拆分字段
Hash(“A”)%4 =
分库 1 分库 2 分库 3 分库 4
分库 5 分库 6 分库 7 分库 8
分库 9 分库 10
分库 11
分库 12
分库 13
分库 14
分库 15
分库 16
product 值Hash 取模
user 值Hash 取模
0
1
2
3
0 1 2 3
CocaColaA
Hash(“CocaCola”)%4
=
SELECT * FROM visit WHERE product=‘ColaCola’ AND user=‘A’
分库 1 分库 2 分库 3 分库 4
分库 5 分库 6 分库 7 分库 8
分库 9 分库 10
分库 11
分库 12
分库 13
分库 14
分库 15
分库 16
product 值Hash 取模
user 值Hash 取模
0
1
2
3
0 1 2 3
CocaCola
Hash(“CocaCola”)%4
=
SELECT * FROM visit WHERE product=‘ColaCola’
Hash(“A”)%4 = A
分库 1 分库 2 分库 3 分库 4
分库 5 分库 6 分库 7 分库 8
分库 9 分库 10
分库 11
分库 12
分库 13
分库 14
分库 15
分库 16
product 值Hash 取模
user 值Hash 取模
0
1
2
3
0 1 2 3
SELECT * FROM visit WHERE product=‘ColaCola’ AND user=‘A’
Cobar 的策略• MySQL 集群替代 Oracle 单点• 基于表的水平拆分和分布
– 根据字段值的一致性 Hash 分布– 多维拆分
• 数据查询方式– 根据 where 中的拆分字段分发
• SQL 语句其他元素的处理– 将 Cobar 收到的 SQL 语句做变换 分发到各个分库执行– 对执行结果合并、处理 保证返回前端的内容满足语义
JOIN 有限的处理• 跨库 JOIN 问题
SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2
ID MEMBER_ID ID NAME
1 efghijk 4 efghijk
5 abcd 6 abcd
2 zzzz 2 zzzz
4 xyzxyz 3 xyzxyz
迭代查询
SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2
FOR row1 IN select * FROM tb1{
ADD(SELECT * FROM tb2 WHERE tb2.name = row1.member_id)TO RESULT
}
跨库索引
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2ID1 ID2 JOIN_COL
2 2 zzzz
4 3 xyzxyz
idx
ID1 ID2 JOIN_COL
1 4 efghijk
5 6 abcd
idx
扫描 idx ,再根据每一行的 id1,id2 查到最终结果
跨库索引
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.id = 5
SELECT * FROM idx WHERE id1 = 5
再根据 id1,id2 查到最终结果
跨库索引
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2ID1 ID2 JOIN_COL
2 2 zzzz4 3 xyzxyz
idx
ID1 ID2 JOIN_COL
1 4 efghijk5 6 abcd
idx
一定以 JOIN_COL 为索引的拆分字段吗?
跨库索引SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600
ID MEMBE_ID GMT
2 zzzz 525
4 xyzxyz 1010
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID GMT
1 efghijk 1205
3 xxxxxx 131
5 abcd 604
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2
跨库索引
ID MEMBE_ID GMT
2 zzzz 525
4 xyzxyz 1010
ID NAME
4 efghijk
5 aaaa
6 abcd
ID MEMBE_ID GMT
1 efghijk 1205
3 xxxxxx 131
5 abcd 604
ID NAME
2 zzzz
3 xyzxyz
tb1
tb1 tb2
tb2
ID1 ID2 JOIN_COL
2 2 zzzz
4 3 xyzxyz
idx
ID1 ID2 JOIN_COL
1 4 efghijk
5 6 abcd
idx
ID MEMBE_ID
2 zzzz
4 xyzxyz
ID MEMBE_ID
1 efghijk
3 xxxxxx
5 abcd
tb1
tb1ID1 ID2 JOIN_COL
2 2 zzzz
4 3 xyzxyz
idx
ID1 ID2 JOIN_COL
1 4 efghijk
5 6 abcd
idx
SELECT idx.id2, tb1.* FROM idx INNER JOIN tb1 ON idx.id1=tb1.id WHERE t1.gmt>600
SELECT idx.id2, tb1.* FROM idx INNER JOIN tb1 ON idx.id1=tb1.id WHERE t1.gmt>600
SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600
跨库索引
跨库索引
ID MEMBE_ID GMT
2 zzzz 525
4 xyzxyz 1010
ID NAME TIME
4 efghijk 123
5 aaaa 922
6 abcd 222
ID MEMBE_ID GMT
1 efghijk 1205
3 xxxxxx 131
5 abcd 604
ID NAME TIME
2 zzzz 1201
3 xyzxyz 1111
tb1
tb1 tb2
tb2SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600 AND t2.time>600
ID1 ID2JOIN_C
OL TIME
2 2 zzzz 1201
4 3 xyzxyz 1111
idx
跨库索引
ID1 ID2 JOIN_COL TIME
2 2 zzzz 1201
4 3 xyzxyz 1111
idx
ID1 ID2 JOIN_COL TIME
1 4 efghijk 123
5 6 abcd 222
idx
• 索引表的拆分– WHERE 条件中的字段
所在表的拆分字段,作为索引拆分字段
• 索引包含– 两张表的主键– JOIN字段– WHERE中的其他字段
• 索引的更新– 分布式事务的支持
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
select ... order by c1 limit 0, 6
select ... order by c1 limit 0, 6
select ... order by c1 limit 0, 6
分库 1
分库 2
分库 3
cobar
Order By/Limit
分库 1
分库 2
分库 3
Order By/Limit
4 5 632
7 8 10651
11 13 14973
返回结果
返回结果
返回结果
8
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
分库 1
分库 2
分库 3
Order By/Limit
4 5 632
7 8 10651
11 13 14973
返回结果
返回结果
返回结果
80
最终结果集
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
分库 1
分库 2
分库 3
Order By/Limit
4 5 632
7 8 1065
11 13 14973
返回结果
返回结果
返回结果
81
最终结果集
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
分库 1
分库 2
分库 3
Order By/Limit
4 5 63
7 8 1065
11 13 14973
返回结果
返回结果
返回结果
82
最终结果集
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
分库 1
分库 2
分库 3
Order By/Limit
4 5 6
7 8 1065
11 13 14973
返回结果
返回结果
返回结果
83
最终结果集
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
分库 1
分库 2
分库 3
Order By/Limit
4 5 6
7 8 1065
11 13 1497
返回结果
返回结果
返回结果
84
最终结果集
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
最终结果集
分库 1
分库 2
分库 3
Order By/Limit
5 6
7 8 1065
11 13 1497
返回结果
返回结果
返回结果
84
4
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
最终结果集
分库 1
分库 2
分库 3
Order By/Limit
4
6
7 8 1065
11 13 1497
返回结果
返回结果
返回结果
84
5
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2
Order By/Limit 方案总结
select c1 from tb1 order by c1 limit 100000000, 2
• 所有分库都要查询 100000002 条数据• Cobar 需要遍历 100000002 条数据
• 对如下 SQL
• 一次交互得到结果• Offset 大小有限制
Order By / Limit 优化• 目标:解决
– 查询量大问题– 遍历量大问题
• 前提– 各个分库数据分布大致一样
select c1 from tb1 order by c1 limit 9999999, 4
select ... order by c1 limit 33333333, 4
select ... order by c1 limit 33333333, 4
select ... order by c1 limit 33333333, 4
分库 1
分库 2
分库 3
• step1: 分成 3 条语句发给分库
分库 1
分库 2
分库 3
74
53
86
9 10
76
119
返回结果
返回结果
返回结果
select c1 from tb1 order by c1 limit 9999999, 4
• 找出查询结果中最小和最大值
分库 1
分库 2
分库 3
74
53
86
9 10
76
119
返回结果
返回结果
返回结果
• step2: 以最小值和最大值为界再查询
select c1 from tb1 order by c1 limit 9999999, 4
3
11
53
11
分库 1
分库 2
分库 3
74
53
86
9 10
76
119
返回结果
返回结果
返回结果
• step3: 反查出每一个返回结果的 offset
select c1 from tb1 order by c1 limit 9999999, 4
3
11
53
11
33333331 条
33333333 条33333332 条
分库 1
分库 2
分库 3
74
53
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
3
11
53
119999996
分库 1
分库 2
分库 3
74
53
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
11
53
119999997
分库 1
分库 2
分库 3
74
5
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
11
53
119999998
分库 1
分库 2
分库 3
74
5
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
11
5
119999999
最终结果集
最终结果集
分库 1
分库 2
分库 3
7
45
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
11
5
119999999
最终结果集
分库 1
分库 2
分库 3
7
4 5
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
11
5
119999999
最终结果集
分库 1
分库 2
分库 3
7
4 5
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
115
119999999
最终结果集
分库 1
分库 2
分库 3
7
4 5
86
9 10
76
119
返回结果
返回结果
返回结果
• 类似于原始方案
select c1 from tb1 order by c1 limit 9999999, 4
115
119999999
Order By / Limit 再优化• Step1 不必得到全部结果
– select min(c1) mi, max(c1) ma from (select c1 from tb1 order by c1 limit 3333333,4) t
• Step2 和 Step3 合并– select * from
(select * from tb1 where c1 between mi and ma) t1, (select count(*) from tb1 where c1 <mi) t2
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
7.9131
8.8604
99.956
7.6131
4.4604
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
7.9131
8.8604
7.6131
4.4604
最终结果集
99.956
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
7.9131
8.8604
7.6131
4.4604
最终结果集
99.956
最终结果集
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
15.5131
8.8604
4.4604
99.956
最终结果集
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
15.5131
13.2604
99.956
最终结果集
Group By
SELECT sum(price) FROM tb1 GROUP BY c1
ID PRICE C1
1 12.3 2222
3 1.6 131
5 8.8 604
7 6.3 131
ID PRICE C1
2 4.4 604
4 7.6 131
6 99.9 56
SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1
12.32222
15.5131
13.2604
99.956
SQL 执行策略总结• WHERE - 基于 SQL 转发• JOIN - 迭代 分布式索引• ORDER BY/LIMIT - 多次查询减小数据量• GROUP BY - 增加 ORDER BY
Cobar 事务支持
前端连接 sql1sql2commit
Cobar 1.2 事务支持
前端连接
分库 1 连接sql1
sql2commit
Cobar 1.2 事务支持
前端连接
分库 1 连接sql1
commit 分库 2 连接sql2
分库 3 连接sql2
Cobar 事务支持
前端连接
分库 1 连接sql1
commit 分库 2 连接sql2
分库 3 连接sql2
• Commit 有先后:隔离性问题• Commit 有失败:一致性问题
大纲
中间件引入
Cobar 策略 水平拆分的数据分布 几种 SQL 元素的执行策略 事务策略
系统实现
实施应用
schema
tableSpace
dataNode
datasource
cndb pc2
主 备 主 备
default offer[0]
主 备
offer[1]
主 备
detail[0]
主 备
default
default offer detail detail
逻辑层次 —— 接口同 MySQLjdbc:mysql://cobarIp:8066/cndb?user=foo&password=bar
MySQL MySQL MySQL
Cobar 结构Front-end Communication
MySQL Protcol Adaptor (BIO)
Application1
MySQL
MySQL Protocol
MySQL MySQL
Data Nodes
Monitor
Configure
HA Pool
MySQLMySQL
Processor(1) Processor(n)
SQL Executor
SQL Router
SQL ParserResultMerger
SQL Executor
SQL Router
SQL ParserResultMerger...
Manager
MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol
Man
agem
ent
Pro
toco
l
MySQL MySQL MySQL
Cobar 结构Front-end Communication
MySQL Protcol Adaptor (BIO)
Application1
MySQL
MySQL Protocol
MySQL MySQL
Data Nodes
Monitor
Configure
HA Pool
MySQLMySQL
Processor(1) Processor(n)
SQL Executor
SQL Router
SQL ParserResultMerger
SQL Executor
SQL Router
SQL ParserResultMerger...
Manager
MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol
Man
agem
ent
Pro
toco
l
Application1
JDBC 和 Server 的通信协议
MySQLJDBCDriver
MySQLServer
MySQL Protocol
JDBC 和 Server 的通信协议PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345);ResultSet rs = ps.executeQuery();
MySQLServer
Application1
MySQLJDBCDriver
JDBC 和 Server 的通信协议
MySQLServer
Application1
MySQLJDBCDriver
PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345);ResultSet rs = ps.executeQuery();
<PREPARED>select * from tb1
where id=?
<OK>stmt_id/param_num/columm_num
<FIELD>parameter_type
<EOF>
<FIELD>column_type
<EOF>
JDBC 和 Server 的通信协议PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345);ResultSet rs = ps.executeQuery();
MySQLServer
Application1
MySQLJDBCDriver
JDBC 和 Server 的通信协议PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345);ResultSet rs = ps.executeQuery();
MySQLServer
Application1
MySQLJDBCDriver
<EXECUTE>stmt_id {param}+
<HEADER>field_count
<FIELD>column_type
<EOF>
<ROW_DATA>{column_val}+
<ROW_DATA>{column_val}+
<EOF>
JDBC 和 Server 的通信协议PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345);ResultSet rs = ps.executeQuery();
Application1
MySQLJDBCDriver
<EXECUTE>stmt_id {param}+
<HEADER>field_count
<FIELD>column_type
<EOF>
<ROW_DATA>{column_val}+
<ROW_DATA>{column_val}+
<EOF>
MySQLServer
JDBC 和 Server 的通信协议Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery( “select * from tb1 where id=12345”);
Application1
MySQLJDBCDriver
<QUERY>sql
<HEADER>field_count
<FIELD>column_type
<EOF>
<ROW_DATA>{column_val}+
<ROW_DATA>{column_val}+
<EOF>
MySQLServer
JDBC 和 Server 的通信协议Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery( “select * from tb1 where id=12345”);
Application1
MySQLJDBCDriver
<QUERY>sql
<HEADER>field_count
<FIELD>column_type
<EOF>
<ROW_DATA>{column_val}+
<ROW_DATA>{column_val}+
<EOF>
MySQLServer
CobarServer
Processor(1) Processor(n)
MySQL MySQL MySQL
Cobar 结构Front-end Communication
MySQL Protcol Adaptor (BIO)
Application1
MySQL
MySQL Protocol
MySQL MySQL
Data Nodes
Monitor
Configure
HA Pool
MySQLMySQL
SQL Executor
SQL Router
SQL ParserResultMerger
SQL Executor
SQL Router
SQL ParserResultMerger...
Manager
MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol
Man
agem
ent
Pro
toco
l
SQL +ParametersResultSetMetaDataResultSet(Rows)
Cobar 通信层• 统一管理 NIO 的 Buffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
共 16MB
Buffer Pool
Cobar 通信层• 统一管理 NIO 的 Buffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
共 16MB
Buffer Pool
<QUERY>select * from tb1 where id=?
Cobar 通信层• 统一管理 NIO 的 Buffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
共 16MB
Buffer Pool
<QUERY>select * from tb1 where id=?
Cobar 通信层• 统一管理 NIO 的 Buffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
4KBByteBuffer
共 16MB
Buffer Pool
15 万TPS
...
MySQL MySQL MySQL
Cobar 结构Front-end Communication
MySQL Protcol Adaptor (BIO)
Application1
MySQL
MySQL Protocol
MySQL MySQL
Data Nodes
Monitor
Configure
HA Pool
MySQLMySQL
Processor(1) Processor(n)
SQL Executor
SQL Router
ResultMerger
SQL Executor
SQL Router
ResultMerger
Manager
MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol
Man
agem
ent
Pro
toco
l
SQL Parser SQL Parser
SELECT id, member_id FROM wp_image WHERE member_id = ‘123’
SQL Parser
select
id member_id wp_image
=
member_id ‘123’
exprList from
架构演变• 基于 JavaCC生成 SQL Parser
– 性能较差,优化不方便
•仿照 ANTLR生成的 Parser 结构手写– 基于 LL(*)的识别器,中间对象过多
• 基于 LL(2) 识别器的手写
第一版
第二版
第三版
架构调整
Lexer
token token token token
Char Reader
Expression Parser
DML Parser
SQL String
Lexer
token
Expression Parser
DML Parser
SQL char[]
第三版 LL(2)
第二版 LL(*)
cache
功能对比第一版 第二版 第三版
‘don\’t’ NO YES YES
.123e-2 YES YES YES
7Eleven NO YES YES
_latin 0x123 NO YES YES
‘abc’ ‘def’ NO YES YES
INSERT('Quadratic', 3, 4, 'What') NO YES YES
TRIM(LEADING 'x' FROM 'xxxbarxxx') NO YES YES
Union select YES YES YES
table join PART PART YES
…… ……
基本元素
语法元素
MySQL 5.5 语法结构
Identifier Keyword Literal Punctuation
表达式Table ReferencesLimitOrderBy...
Delete Update Insert Replace Select
Call
Set/Show
SQL 语句
Variable
基本元素• Keyword
– 227个关键字,不区分大小写• Identifier
– schema 、 table 、 column 、 index 、 alias 、 keyword…• SELECT aNy FROM t1 WHERE id IN AnY (SELECT id FROM t2)
– `select` 、 table1 ./*spam*/id 、 7Up
• Punctuation– , 、 := 、 > 、 ! 、 ~ …
• Variable– User-Def – SystemVariable : @@version
基本元素 - Literal• String Literal
– N’abc’ 、 _latin1’abc’ 、’ abc’ ’def’– ”abc””d” 、’ abc\’d’
• Number Literal– 123 、 .123 、 123. 、 123.e4 、 .123E-4– 123e4 vs 123e4f
• Hex/Bit Literal– 0x89af 、 x’89af’ 、 0b101011 、 b’101011’
– _latin1 0x89af
基本元素
语法元素
MySQL 5.5 语法结构
Identifier Keyword Literal Punctuation
表达式Table ReferencesLimitOrderBy...
Delete Update Insert Replace Select
Call
Set/Show
SQL 语句
Variable
语法元素 – Table Referencestable_references: table_reference {',' table_reference}
table_reference: table_factor { ['INNER'|'CROSS‘] 'JOIN' table_factor [join_condition] | 'STRAIGHT_JOIN' table_factor ['ON' conditional_expr] | ('LEFT'|'RIGHT') ['OUTER‘] 'JOIN' table_reference join_condition | 'NATURAL' [('LEFT'|'RIGHT') ['OUTER‘] ] 'JOIN' table_factor }
table_factor: tbl_name [[’AS’] alias] [index_hint_list] | table_subquery [’AS’] alias | '(' table_references ')'
join_condition: 'ON' conditional_expr | 'USING' '('column_list')'
index_hint_list: index_hint {index_hint}index_hint: 'USE' ('INDEX'|'KEY') [ 'FOR' ('JOIN'|'ORDER' 'BY'|'GROUP' 'BY') ] '(' [index_list] ')' | 'IGNORE' ('INDEX'|'KEY') [ 'FOR' ('JOIN'|'ORDER' 'BY'|'GROUP' 'BY') ] '(' index_list ')' | 'FORCE' ('INDEX'|'KEY') [ 'FOR' ('JOIN'|'ORDER' 'BY'|'GROUP' 'BY') ] '(' index_list ')'index_list: index_name {',' index_name}
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
规则 1规则 2
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor
规则 1规则 2
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor
规则 1规则 2
table_reference
table_reference规则 2
table_factor
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor table_factor table_factor join_condition
规则 1规则 2
table_reference
table_reference
规则 1
规则 2
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor table_factor table_factor join_condition
规则 1规则 2
table_reference
table_reference
ERROR!规则 1
规则 2
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor table_factor table_factor
table_reference
join_condition
table_reference
table_factor table_factor table_factor join_condition
规则 1规则 2
table_reference
table_reference
ERROR!
规则 1
规则 1
规则 2
规则 2
MySQL 不支持的 MySQL 语法table_reference: table_factor 'JOIN' table_factor [join_condition]table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition
LEFT JOINtb1 t2 JOIN t3 USING (id)
table_factor table_factor table_factor
table_reference
join_condition
table_reference
table_factor table_factor table_factor join_condition
规则 1规则 2
table_reference
table_reference
ERROR!
规则 1
规则 1
规则 2
规则 2
Table References 的表达式特性table_references: table_reference {',' table_reference}table_reference : ’(’ table_references ')' | ’(’ query { ’UNION’ query} ’)’ [’AS’] alias query : ’(’ query ’)’ | ’SELECT ...’
( ( select ...) UNOIN (select...) ) AS t1
( ( t1, t2), t3 )
LL(1)
规则 1
规则 2
规则 2规则 1
expr: ’(’ expr ’)’ | tableRefs | subquery
类似于表达式:
基本元素
语法元素
MySQL 5.5 语法结构
Identifier Keyword Literal Punctuation
表达式Table ReferencesLimitOrderBy...
Delete Update Insert Replace Select
Call
Set/Show
SQL 语句
Variable
表达式• 优先级和结合型
– MySQL Manual 文档不精确– 文档+实验
• 特殊函数– Keyword 作为函数名: 23 个
• INSERT('Quadratic', 3, 4, 'What')
– 非规则参数列表: 13 个• SELECT TRIM(BOTH 'x' FROM 'xxxbarx')
• 特殊 Identifier– 1 >= any + 2– 1 >= any (select …)
simple: "select id from t1“
short: " seLEcT id, member_id , image_path \t , image_size , STATUS, gmt_modified from wp_image wheRe \t\t\n id = ? AND member_id\t=\t-123.456"
short2: "select count(*) from MESSAGE_REC_RECORD where RECEIVER_VACOUNT =? and RECEIVER_ID in ( ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? , ? ) and RECEIVER_STATUS in ( ? , ? ) and SPAM_STATUS in ( ? ) and DELETE_STATUS = ?"
long: "select ID, GMT_CREATE, GMT_MODIFIED, INBOX_FOLDER_ID, MESSAGE_ID, FEEDBACK_TYPE, TARGET_ID, TRADE_ID, SUBJECT, SENDER_ID, SENDER_TYPE, S_DISPLAY_NAME, SENDER_STATUS, RECEIVER_ID, RECEIVER_TYPE, R_DISPLAY_NAME, RECEIVER_STATUS, SPAM_STATUS, REPLY_STATUS, ATTACHMENT_STATUS, SENDER_COUNTRY, RECEIVER_COUNTRY,APP_FROM,APP_TO,APP_SOURCE,SENDER_VACOUNT,RECEIVER_VACOUNT, DISTRIBUTE_STATUS,ORG_RECEIVER_ID,CUSTOMER_ID,OPERATOR_ID,OPERATOR_NAME,FOLLOW_STATUS,DELETE_STATUS,FOLLOW_TIME,BATCH_COUNT from MESSAGE_REC_RECORD where RECEIVER_VACOUNT =? and ID = ?"
long2: "select A.ID , A.GMT_CREATE , A.GMT_MODIFIED , A.MESSAGE_ID , A.SENDER_COMPANY_ID, A.SENDER_ID, A.SENDER_IP, A.SENDER_TYPE, A.SENDER_COMPANY , A.SENDER_ADDRESS , A.SENDER_COUNTRY , A.SENDER_ZIP , A.SENDER_PHONE , A.SENDER_FAX , A.SENDER_EMAIL , A.RECEIVER_COMPANY_ID, A.RECEIVER_ID, A.RECEIVER_TYPE, A.RECEIVER_COMPANY , A.RECEIVER_ADDRESS , A.RECEIVER_COUNTRY , A.RECEIVER_ZIP , A.RECEIVER_PHONE , A.RECEIVER_FAX , A.RECEIVER_EMAIL , A.TARGET_ID, A.FEEDBACK_TYPE, A.FEEDBACK_CATEGORY, A.SUBJECT, A.APP_SOURCE , A.ATTACHMENT_IDS , B.REMARK , A.S_DISPLAY_NAME , A.R_DISPLAY_NAME , A.RELATED_FEEDBACK_IDS , A.NOTICE_MESSAGE , B.PROPERTIES, A.APP_FROM,APP_TO,A.SENDER_VACOUNT,A.RECEIVER_VACOUNT from MESSAGE_DETAIL A,MESSAGE_DETAIL_REMARK_PROPERTIES B where A.ID = ? and A.ID = B.ID"
性能对比单位微秒 第一版 第二版 手写 v2 手写 v2
sqlgenSimpl
e25.6 1.76 0.9
Short 43.2 8.6 4.1 5.2
Short2 63.4 17.6 9.8
Long 75.2 25.9 14.6
Long2 94.4 35.4 22.3
GC 对比YGC YGCT
第一版 2838 0.803
第二版 410 0.116
第三版 229 0.057
第三版 +sql生成 263 0.074
Processor(1) Processor(n)
MySQL MySQL MySQL
Cobar 结构Front-end Communication
Application1
MySQL
MySQL Protocol
MySQL MySQL
Monitor
Configure
MySQLMySQL
SQL Executor
SQL Router
SQL ParserResultMerger
SQL Executor
SQL Router
SQL ParserResultMerger...
Manager
MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol
Man
agem
ent
Pro
toco
l
MySQL Protcol Adaptor (BIO)
Data Nodes
HA Pool
后台数据访问逻辑层次
HA Pool
MySQL Protocol Adapter
Data Node
SM SM SM SM SM
ip:port/offer ip:port/offerip:port/ibank ip:port/ibankip:port/ibank
• 数据库连接– 基于协议数据包– 与 MySQL 交互
基于 MySQL协议
MySQL新 Cobar
select * from offerselect * from offer
基于 MySQL协议
MySQL新 Cobar
HEADER FIELD EOF ROW ROW ROW ROW ROW ROW ROW ROW ROW ROW ROW
select * from offer
Result 2GB
select * from offer
后台数据访问逻辑层次
SM
HA PoolMySQL Protocol Adapter
Data Node• 主备连接池
SM SM SM SM SM
后台数据访问逻辑层次
SM
• 心跳检测后端连接
SM SM SM SM SM
HA PoolMySQL Protocol Adapter
Data Node
X
后台数据访问逻辑层次
SM
• 心跳检测后端连接• 主库失效自动切换至备库
• 重置池中连接
SM SM SM SM SM
HA PoolMySQL Protocol Adapter
Data Node
分库 2 分库 3 分库 4 分库 5 分库 6分库 1
后台数据访问逻辑层次
SM
• 水平拆分的分库
SM SM SM SM SM
HA Pool
MySQL Protocol Adapter
Data Node
分库 2 分库 3 分库 4 分库 5 分库 6分库 1
物理机
灵活的层间对应关系
SM SM SM SM SMSM
物理机 物理机 物理机 物理机 物理机
大纲
中间件引入
Cobar 策略
系统实现 MySQL协议 通信 解析 后端连接
实施应用
Cobar 的部署
Cobar 集群 Cobar 集群
Cobar 集群
Cobar 集群 Cobar 集群
Cobar 集群 Cobar 集群
...
青岛 杭州 美国
中文站
国际站
offer/ibank/snapshot
……
messagecenter
hermes
product
... ... Cobar
ManagerCobar
ManagerCobar
Manager
Cobar 的部署
Cobar 集群
德胜机房Cobar 集群
兴义机房Cobar 集群
Cobar 集群
...
青岛 杭州 美国
... ... Cobar
ManagerCobar
ManagerCobar
Manager
Cobar 集群
MySQL Protocol
MyS
QL
Prot
ocol
MySQL Protocol
MySQL Protocol
MySQL Protocol
MyS
QL
Prot
oco
l
HTTP
数据迁移•场景
– MySQL 数据库节点扩容– 拆分规则更改
• 目标– 迁移过程中应用保持可用– 数据不能丢失、多余或者不一致
迁移步骤• 数据的全量 dump• 变更数据的增量 dump• 路由规则切换•清理 分库 1 分库 2
分库 1 分库 2 分库 3
数据分片数量变更
分库 2分库 1
全量 dump
分库 3
分库 1 分库 2 分库 3
分库 2分库 1
全量 dump
分库 3
分库 1 分库 2 分库 3
dump dump
• 此时仍使用两份分库的拆分规则
分库 2分库 1
全量 dump
分库 3
invisible invisible
让绿色数据对 SQL 语句不可见
… WHERE ( … ) AND 非绿色数据
• 全量 dump 过程中,数据会持续变更• 将 binlog 同步到新库中
分库 2分库 1
增量 dump
分库 3
invisible invisible
binlog binlogApply Apply
•暂停写入,等待 binlog 全部同步到新库• 将路由规则更新为三个分库
分库 2分库 1
路由规则切换
分库 3
invisible invisible
binlog binlogApply Apply
•删除老数据
清理
分库 2分库 1 分库 3
大纲
中间件引入
Cobar 策略
系统实现
实施应用 部署结构 平滑迁移
联系我们
http://code.alibabatech.com/wiki/display/cobarhttp://weibo.com/alicobarhttps://groups.google.com/group/ali-cobar