阿里巴巴分布式数据库 ——原理、实现和应用 集团共享技术平台 分布式数据库 邱硕 2012.7
分布式数据库中间件 性能 容量 高可用 数据消费时效性 跨机房数据同步 ... App App App App Oracle MySQL Cobar Oracle MySQL MySQL MySQL Oracle MySQL MySQL 解决数据的性能/容量、可用性、容灾、变更数据消费问题 Erosa Oracle Erosa MySQL Erosa MySQL Erosa MySQL Erosa Oracle Erosa MySQL Erosa MySQL Eromanga Eromanga ... DW ASC Otter Otter
分布式数据库中间件 Cobar 性能 容量 高可用 数据消费时效性 跨机房数据同步 ... App App App App Oracle MySQL MySQL MySQL Oracle MySQL MySQL Erosa Oracle Erosa MySQL Erosa MySQL Erosa MySQL Erosa Oracle Erosa MySQL Erosa MySQL Eromanga Eromanga ... DW ASC Otter Otter
分布式数据库中间件 性能 容量 高可用 数据消费时效性 跨机房数据同步 Erosa Oracle Erosa MySQL App App App App Cobar Oracle MySQL MySQL MySQL Oracle MySQL MySQL Erosa Oracle Erosa MySQL Erosa MySQL Erosa MySQL Erosa Oracle Erosa MySQL Erosa MySQL Eromanga Eromanga ... DW ASC Otter Otter
分布式数据库中间件 Otter Otter 性能 容量 高可用 数据消费时效性 跨机房数据同步 ... App App App App Cobar Oracle MySQL MySQL MySQL Oracle MySQL MySQL Erosa Oracle Erosa MySQL Erosa MySQL Erosa MySQL Erosa Oracle Erosa MySQL Erosa MySQL Eromanga Eromanga ... DW ASC Otter Otter
分布式数据库中间件 Cobar 性能 容量 高可用 数据消费时效性 跨机房数据同步 ... App App App App Oracle MySQL MySQL MySQL Oracle MySQL MySQL Erosa Oracle Erosa MySQL Erosa MySQL Erosa MySQL Erosa Oracle Erosa MySQL Erosa MySQL Eromanga Eromanga ... DW ASC Otter Otter
大纲 中间件引入 Cobar策略 系统实现 实施应用
Cobar之前 Oracle单点数据库 性能问题 数据库连接过多 可用性问题 成本和伸缩性问题 中文站offer总数:2008年1亿 -> 2011年3亿 高峰时:load 30、cpu使用率90% 数据库连接过多 可用性问题 Standby切换故障 成本和伸缩性问题 依赖高成本的硬件设备
Oracle 单点:MySQL集群替换Oracle MySQL MySQL MySQL MySQL MySQL MySQL MySQL
Cobar引入 水平拆分 Oracle单点数据库 性能问题 数据库连接过多 可用性问题 成本和伸缩性问题 MySQL Oracle单点数据库 性能问题 中文站offer总数:08年1亿 -> 今天3亿 高峰时:load 30、cpu使用率90% 数据库连接过多 可用性问题 Standby切换故障 成本和伸缩性问题 依赖高成本的硬件设备 ID MEMBE_ID INFO 1 pavarotti17 … 11 Cobar MySQL ID MEMBE_ID INFO 3 abcd … 9 20 App MySQL ID MEMBE_ID INFO 4 test1234 … 5
Oracle单点数据库 性能问题 数据库连接过多 可用性问题 成本和伸缩性问题 中文站offer总数:08年1亿 -> 今天3亿 MySQL App Oracle单点数据库 性能问题 中文站offer总数:08年1亿 -> 今天3亿 高峰时:load 30、cpu使用率90% 数据库连接过多 可用性问题 Standby切换故障 成本和伸缩性问题 依赖高成本的硬件设备 ID MEMBE_ID INFO 1 pavarotti17 … 11 App App MySQL ID MEMBE_ID INFO 3 abcd … 9 20 App App App MySQL App ID MEMBE_ID INFO 4 test1234 … 5 App
Cobar引入 连接复用 MySQL App App App MySQL Cobar Proxy App App App MySQL App ID MEMBE_ID INFO 1 pavarotti17 … 11 App Cobar Proxy App MySQL ID MEMBE_ID INFO 3 abcd … 9 20 App App App MySQL App ID MEMBE_ID INFO 4 test1234 … 5 App
Cobar引入 Oracle单点数据库 性能问题 数据库连接过多 可用性问题 成本和伸缩性问题 中文站offer总数:08年1亿 -> 今天3亿 高峰时:load 30、cpu使用率90% 数据库连接过多 可用性问题 Standby切换故障 成本和伸缩性问题 依赖高成本的硬件设备 MySQL ID MEMBE_ID INFO 1 pavarotti17 … 11 Cobar X App
Cobar引入 failover X MySQL Master1 Cobar App MySQL Replication ID MEMBE_ID INFO 1 pavarotti17 … 11 Cobar X App MySQL Replication MySQL Master2 ID MEMBE_ID INFO 1 pavarotti17 … 11
Cobar引入 failover MySQL Master1 Cobar App MySQL Replication ID MEMBE_ID INFO 1 pavarotti17 … 11 Cobar App MySQL Replication MySQL Master2 ID MEMBE_ID INFO 1 pavarotti17 … 11
大纲 中间件引入 Cobar策略 系统实现 实施应用
Oracle 拆分数据表 MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
水平拆分 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20
水平拆分 拆分字段 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20
水平拆分 库1 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20 拆分字段 库1 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20 f(pavarotti17)=库1 f(test1234)=库1 f(test1234)=库1 f(pavarotti17)=库1 库2 f(abcd)=库2 ID MEMBE_ID INFO 3 abcd … 9 20 f(abcd)=库2 f(abcd)=库2
水平拆分 库1 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20 拆分字段 路由算法 库1 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 ID MEMBE_ID INFO 1 pavarotti17 … 3 abcd 4 test1234 5 9 11 20 f(pavarotti17)=库1 f(test1234)=库1 f(test1234)=库1 f(pavarotti17)=库1 库2 f(abcd)=库2 ID MEMBE_ID INFO 3 abcd … 9 20 f(abcd)=库2 f(abcd)=库2
路由算法 pavarotti17 f(pavarotti17)=库1
路由算法 hash( ) = 3170972965401 pavarotti17 部分截取
路由算法 hash(pavarott) = 3170972965401 % 1024 = 537 0 1023
路由算法 256 256 256 256 hash(pavarott) = 3170972965401 % 1024 = 537 分库1 0 255 256 511 512 767 768 1023 256 256 256 256 分库1 分库2 分库3 分库4
路由算法 256 256 256 256 hash(pavarott) = 3170972965401 % 1024 = 537 分库1 0 255 256 511 512 767 768 1023 256 256 256 256 分库1 分库2 分库3 分库4
路由算法——扩容 hash(pavarott) = 3170972965401 % 1024 = 537 分库1 分库2 分库3 分库4 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 分库1 分库2 分库3 分库4 原 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 0 511 512 767 768 895 896 1023 512 256 128 128 分库3 分库4 分库2 分库1
拆分表的数据访问——SQL转发 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 App select * from tb1 where member_id=‘test1234’ App Cobar Cobar 1.0只转发SQL,不更改SQL内容 ID MEMBE_ID INFO 3 abcd … 9 20
拆分表的数据访问——SQL转发 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 App select * from tb1 where member_id=‘test1234’ App Cobar ID MEMBE_ID INFO 3 abcd … 9 20
拆分表的数据访问——SQL转发 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 App SELECT * FROM tb1 WHERE member_id IN (‘test1234’,’pavarotti17’,’abcd’) App Cobar ID MEMBE_ID INFO 3 abcd … 9 20
拆分表的数据访问——SQL转发 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 App select * from tb1 where member_id in (‘test1234’,’pavarotti17’) App Cobar select * from tb1 where member_id in (‘abcd’) ID MEMBE_ID INFO 3 abcd … 9 20
拆分表的数据访问——结果返回 ID MEMBE_ID INFO 1 pavarotti17 … 4 test1234 5 11 ResultSet:row1 row2 ResultSet:row3 row1 row4 row5 row2 Result Merger 前台 通信 ResultSet:row3 row4 row5 ID MEMBE_ID INFO 3 abcd … 9 20
多维水平拆分 visit表 SELECT * FROM visit WHERE user=‘A’ product user info Coca-Cola A … C visit表 product user info Coca-Cola A … pepsi C Fanta D B 7Up product user info pepsi C … A SELECT * FROM visit WHERE user=‘A’ product user info Fanta D … B product user info 7Up D …
多维水平拆分 visit表 product user info Coca-Cola A … pepsi product user info Fanta D B 7Up product user info Fanta B … SELECT * FROM visit WHERE product = ‘Coca-Cola’ product user info pepsi C … Coca-Cola product user info Fanta D … 7Up
一张表的多个字段同时作为拆分字段 3 2 1 1 2 3 分库13 分库14 分库15 分库16 分库9 分库10 分库11 分库12 user值 Hash取模 3 分库13 分库14 分库15 分库16 2 分库9 分库10 分库11 分库12 1 分库5 分库6 分库7 分库8 分库1 分库2 分库3 分库4 visit表 product值 Hash取模 1 2 3 USER PRODUCT
3 2 1 1 2 3 分库13 分库14 分库15 分库16 分库9 分库10 分库11 分库12 Hash(“A”)%4 = 分库5 SELECT * FROM visit WHERE product=‘ColaCola’ AND user=‘A’ user值 Hash取模 3 分库13 分库14 分库15 分库16 2 分库9 分库10 分库11 分库12 CocaCola A Hash(“A”)%4 = 1 分库5 分库6 分库7 分库8 分库1 分库2 分库3 分库4 product值 Hash取模 1 2 3 Hash(“CocaCola”)%4 =
3 2 1 1 2 3 分库13 分库14 分库15 分库16 分库9 分库10 分库11 分库12 分库5 分库6 分库7 分库8 分库1 SELECT * FROM visit WHERE product=‘ColaCola’ user值 Hash取模 CocaCola 3 分库13 分库14 分库15 分库16 2 分库9 分库10 分库11 分库12 1 分库5 分库6 分库7 分库8 分库1 分库2 分库3 分库4 product值 Hash取模 1 2 3 Hash(“CocaCola”)%4 =
3 2 1 1 2 3 分库13 分库14 分库15 分库16 分库9 分库10 分库11 分库12 Hash(“A”)%4 = 分库5 SELECT * FROM visit WHERE product=‘ColaCola’ AND user=‘A’ user值 Hash取模 3 分库13 分库14 分库15 分库16 2 分库9 分库10 分库11 分库12 A Hash(“A”)%4 = 1 分库5 分库6 分库7 分库8 分库1 分库2 分库3 分库4 product值 Hash取模 1 2 3
Cobar的策略 MySQL集群替代Oracle单点 基于表的水平拆分和分布 数据查询方式 SQL语句其他元素的处理 根据字段值的一致性Hash分布 多维拆分 数据查询方式 根据where中的拆分字段分发 SQL语句其他元素的处理 将Cobar收到的SQL语句做变换 分发到各个分库执行 对执行结果合并、处理 保证返回前端的内容满足语义
JOIN有限的处理 跨库JOIN问题 tb1 tb2 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME ID MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz ID MEMBER_ID NAME 1 efghijk 4 5 abcd 6 2 zzzz xyzxyz 3 tb1 tb2 ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd
迭代查询 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME tb1 tb2 MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz FOR row1 IN select * FROM tb1{ ADD( SELECT * FROM tb2 WHERE tb2.name = row1.member_id )TO RESULT } tb1 tb2 ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd
跨库索引 扫描idx,再根据每一行的id1,id2查到最终结果 idx tb1 tb2 idx tb1 tb2 ID1 ID2 JOIN_COL 2 zzzz 4 3 xyzxyz ID MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz idx tb1 tb2 ID1 ID2 JOIN_COL 1 4 efghijk 5 6 abcd ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd 扫描idx,再根据每一行的id1,id2查到最终结果
跨库索引 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.id = 5 tb1 tb2 ID MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz SELECT * FROM idx WHERE id1 = 5 tb1 tb2 ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd 再根据id1,id2查到最终结果
跨库索引 一定以 JOIN_COL 为索引的拆分字段吗? zzzz xyzxyz efghijk abcd idx tb1 tb2 4 3 xyzxyz ID MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz idx tb1 tb2 ID1 ID2 JOIN_COL 1 4 efghijk 5 6 abcd ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd 一定以 JOIN_COL 为索引的拆分字段吗?
跨库索引 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600 tb1 tb2 ID MEMBE_ID GMT 1 efghijk 1205 3 xxxxxx 131 5 abcd 604 ID NAME 2 zzzz 3 xyzxyz tb1 tb2 ID MEMBE_ID GMT 2 zzzz 525 4 xyzxyz 1010 ID NAME 4 efghijk 5 aaaa 6 abcd
跨库索引 idx tb1 tb2 idx tb1 tb2 ID1 ID2 JOIN_COL 1 4 efghijk 5 6 abcd ID MEMBE_ID GMT 1 efghijk 1205 3 xxxxxx 131 5 abcd 604 ID NAME 2 zzzz 3 xyzxyz idx tb1 tb2 ID1 ID2 JOIN_COL 2 zzzz 4 3 xyzxyz ID MEMBE_ID GMT 2 zzzz 525 4 xyzxyz 1010 ID NAME 4 efghijk 5 aaaa 6 abcd
跨库索引 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600 idx tb1 tb2 SELECT idx.id2, tb1.* FROM idx INNER JOIN tb1 ON idx.id1=tb1.id WHERE t1.gmt>600 ID1 ID2 JOIN_COL 1 4 efghijk 5 6 abcd ID MEMBE_ID 1 efghijk 3 xxxxxx 5 abcd ID NAME 2 zzzz 3 xyzxyz idx tb1 tb2 SELECT idx.id2, tb1.* FROM idx INNER JOIN tb1 ON idx.id1=tb1.id WHERE t1.gmt>600 ID1 ID2 JOIN_COL 2 zzzz 4 3 xyzxyz ID MEMBE_ID 2 zzzz 4 xyzxyz ID NAME 4 efghijk 5 aaaa 6 abcd
跨库索引 SELECT * FROM tb1 INNER JOIN tb2 ON t1.MEMBER_ID=t2.NAME WHERE t1.gmt>600 AND t2.time>600 tb1 tb2 ID MEMBE_ID GMT 1 efghijk 1205 3 xxxxxx 131 5 abcd 604 ID NAME TIME 2 zzzz 1201 3 xyzxyz 1111 idx ID1 ID2 JOIN_COL TIME 2 zzzz 1201 4 3 xyzxyz 1111 tb1 tb2 ID MEMBE_ID GMT 2 zzzz 525 4 xyzxyz 1010 ID NAME TIME 4 efghijk 123 5 aaaa 922 6 abcd 222
跨库索引 索引表的拆分 索引包含 索引的更新 WHERE条件中的字段所在表的拆分字段,作为索引拆分字段 两张表的主键 JOIN字段 分布式事务的支持 idx ID1 ID2 JOIN_COL TIME 1 4 efghijk 123 5 6 abcd 222 idx ID1 ID2 JOIN_COL TIME 2 zzzz 1201 4 3 xyzxyz 1111
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 cobar 分库1 select ... order by c1 limit 0, 6 1, 8, 9 2, 3, 4 limit 1,2 2,3,4 5,6,7 分库2 select ... order by c1 limit 0, 6 分库3 select ... order by c1 limit 0, 6
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 分库1 返回结果 2 3 4 5 6 8 分库2 返回结果 1 5 6 7 8 10 分库3 返回结果 3 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 分库1 返回结果 2 3 4 5 6 8 分库2 返回结果 1 5 6 7 8 10 最终结果集 分库3 返回结果 3 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 1 分库1 返回结果 2 3 4 5 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 分库3 返回结果 3 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 2 分库1 返回结果 3 4 5 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 分库3 返回结果 3 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 3 分库1 返回结果 4 5 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 分库3 返回结果 3 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 4 分库1 返回结果 4 5 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 分库3 返回结果 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 4 分库1 返回结果 5 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 4 分库3 返回结果 7 9 11 13 14
SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 Order By/Limit SELECT c1 FROM tb1 ORDER BY c1 LIMIT 4, 2 4 分库1 返回结果 6 8 分库2 返回结果 5 6 7 8 10 最终结果集 4 5 分库3 返回结果 7 9 11 13 14
Order By/Limit 方案总结 一次交互得到结果 Offset大小有限制 对如下SQL 所有分库都要查询100000002条数据 select c1 from tb1 order by c1 limit 100000000, 2 所有分库都要查询100000002条数据 Cobar需要遍历100000002条数据
Order By / Limit 优化 目标:解决 查询量大问题 遍历量大问题 前提 各个分库数据分布大致一样
step1:分成3条语句发给分库 select c1 from tb1 order by c1 limit 9999999, 4 分库1 select ... order by c1 limit 33333333, 4 分库2 select ... order by c1 limit 33333333, 4 分库3 select ... order by c1 limit 33333333, 4
找出查询结果中最小和最大值 select c1 from tb1 order by c1 limit 9999999, 4 返回结果 分库1 7 9 10 分库2 返回结果 3 5 6 7 分库3 返回结果 6 8 9 11
step2:以最小值和最大值为界再查询 select c1 from tb1 order by c1 limit 9999999, 4 返回结果 分库1 3 4 7 9 10 11 分库2 返回结果 3 5 6 7 11 分库3 返回结果 3 5 6 8 9 11
step3:反查出每一个返回结果的offset select c1 from tb1 order by c1 limit 9999999, 4 step3:反查出每一个返回结果的offset 33333332条 返回结果 分库1 3 4 7 9 10 11 33333333条 分库2 返回结果 3 5 6 7 11 33333331条 分库3 返回结果 3 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999996 返回结果 分库1 3 4 7 9 10 11 分库2 返回结果 3 5 6 7 11 分库3 返回结果 3 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999997 返回结果 分库1 4 7 9 10 11 分库2 返回结果 3 5 6 7 11 分库3 返回结果 3 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999998 返回结果 分库1 4 7 9 10 11 分库2 返回结果 5 6 7 11 分库3 返回结果 3 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999999 返回结果 分库1 4 7 9 10 11 最终结果集 分库2 返回结果 5 6 7 11 分库3 返回结果 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999999 返回结果 分库1 7 9 10 11 最终结果集 4 分库2 返回结果 5 6 7 11 分库3 返回结果 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999999 返回结果 分库1 7 9 10 11 最终结果集 4 5 分库2 返回结果 6 7 11 分库3 返回结果 5 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999999 返回结果 分库1 7 9 10 11 最终结果集 4 5 5 分库2 返回结果 6 7 11 分库3 返回结果 6 8 9 11
类似于原始方案 select c1 from tb1 order by c1 limit 9999999, 4 9999999 返回结果 分库1 7 9 10 11 最终结果集 4 5 5 6 分库2 返回结果 7 11 分库3 返回结果 6 8 9 11
Order By / Limit 再优化 Step1不必得到全部结果 Step2和Step3合并 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 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 7.9 131 8.8 604 12.3 2222 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56 99.9 56 7.6 131 4.4 604
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 7.9 131 8.8 604 12.3 2222 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56 99.9 56 7.6 131 4.4 604
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 99.9 56 7.9 131 8.8 604 12.3 2222 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56 7.6 131 4.4 604
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 99.9 56 8.8 604 12.3 2222 15.5 131 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56 4.4 604
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 99.9 56 12.3 2222 15.5 131 13.2 604 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56
Group By SELECT sum(price), c1 FROM tb1 GROUP BY c1 ORDER BY c1 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 99.9 56 15.5 131 13.2 604 ID PRICE C1 2 4.4 604 4 7.6 131 6 99.9 56 12.3 2222
SQL执行策略总结 WHERE - 基于SQL转发 JOIN - 迭代 分布式索引 ORDER BY/LIMIT - 多次查询减小数据量 GROUP BY - 增加ORDER BY Order by 下推限制:不能处理此类SQL: SELECT * FROM tb1, tb2 ORDER BY tb2.col2, tb1.col1, tb2.col2
Cobar 事务支持 前端连接 commit sql2 sql1
Cobar 1.2 事务支持 分库1连接 sql1 前端连接 commit sql2
Cobar 1.2 事务支持 分库1连接 sql1 前端连接 commit 分库2连接 sql2 分库3连接 sql2
Cobar 事务支持 Commit有先后:隔离性问题 Commit有失败:一致性问题 分库1连接 sql1 前端连接 commit 分库2连接 sql2 Sql执行中,有一个分库发生错误,则全部回滚。 前端的commit操作会并发转发至后端 分库3连接 sql2 Commit有先后:隔离性问题 Commit有失败:一致性问题
大纲 中间件引入 Cobar策略 水平拆分的数据分布 几种SQL元素的执行策略 事务策略 系统实现 实施应用
jdbc:mysql://cobarIp:8066/cndb?user=foo&password=bar schema cndb pc2 tableSpace default offer detail detail dataNode default offer[0] offer[1] detail[0] default data source 主 备 主 备 主 备 主 备 主 备
... Cobar结构 Application1 MySQL Protocol Front-end Communication Processor(1) Processor(n) Manager Monitor Configure SQL Parser Result Merger SQL Parser Result Merger ... SQL Router SQL Router Management Protocol SQL Executor SQL Executor Data Nodes HA Pool MySQL Protcol Adaptor (BIO) MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
... Cobar结构 Application1 MySQL Protocol Front-end Communication Processor(1) Processor(n) Manager Monitor Configure SQL Parser Result Merger SQL Parser Result Merger ... SQL Router SQL Router Management Protocol SQL Executor SQL Executor Data Nodes HA Pool MySQL Protcol Adaptor (BIO) MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
JDBC和Server的通信协议 MySQL Protocol MySQL JDBC MySQL Server Driver Application1 MySQL JDBC Driver MySQL Server MySQL Protocol
JDBC和Server的通信协议 PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345); ResultSet rs = ps.executeQuery(); Application1 MySQL JDBC Driver MySQL Server
JDBC和Server的通信协议 PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345); ResultSet rs = ps.executeQuery(); <PREPARED> select * from tb1 where id=? Application1 MySQL JDBC Driver MySQL Server <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(); Application1 MySQL JDBC Driver MySQL Server
JDBC和Server的通信协议 PreparedStatement ps = conn.prepareStatement( "select * from tb1 where id=?"); ps.setLong(1, 12345); ResultSet rs = ps.executeQuery(); <EXECUTE> stmt_id {param}+ Application1 MySQL JDBC Driver MySQL Server <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(); <EXECUTE> stmt_id {param}+ Application1 MySQL JDBC Driver MySQL Server <HEADER> field_count <FIELD> column_type <EOF> <ROW_DATA> {column_val}+ <ROW_DATA> {column_val}+ <EOF>
JDBC和Server的通信协议 Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( “select * from tb1 where id=12345”); <QUERY> sql Application1 MySQL JDBC Driver MySQL Server <HEADER> field_count <FIELD> column_type <EOF> <ROW_DATA> {column_val}+ <ROW_DATA> {column_val}+ <EOF>
JDBC和Server的通信协议 Cobar Server Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery( “select * from tb1 where id=12345”); <QUERY> sql Application1 MySQL JDBC Driver Cobar Server MySQL Server <HEADER> field_count <FIELD> column_type <EOF> <ROW_DATA> {column_val}+ <ROW_DATA> {column_val}+ <EOF>
ResultSetMetaData ResultSet(Rows) Cobar结构 Application1 MySQL Protocol Front-end Communication Processor(1) Processor(n) Manager Monitor Configure SQL Parser Result Merger SQL Parser Result Merger SQL +Parameters ResultSetMetaData ResultSet(Rows) ... SQL Router SQL Router Management Protocol SQL Executor SQL Executor Data Nodes HA Pool MySQL Protcol Adaptor (BIO) MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
Cobar 通信层 统一管理NIO的Buffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 共16MB 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer Buffer Pool
<QUERY> select * from tb1 where id=? Cobar 通信层 统一管理NIO的Buffer 共16MB 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer <QUERY> select * from tb1 where id=? 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer Buffer Pool
<QUERY> select * from tb1 where id=? Cobar 通信层 统一管理NIO的Buffer 共16MB 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer <QUERY> select * from tb1 where id=? 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer Buffer Pool
15万 Cobar 通信层 TPS 统一管理NIO的Buffer 4KB ByteBuffer 4KB ByteBuffer 共16MB 15万 TPS 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer 4KB ByteBuffer Buffer Pool
... Cobar结构 Application1 MySQL Protocol Front-end Communication Processor(1) Processor(n) Manager Monitor Configure SQL Parser Result Merger SQL Parser Result Merger ... SQL Router SQL Router Management Protocol SQL Executor SQL Executor Data Nodes HA Pool MySQL Protcol Adaptor (BIO) MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
SELECT id, member_id FROM wp_image WHERE member_id = ‘123’ SQL Parser select exprList from = id member_id wp_image member_id ‘123’
架构演变 基于JavaCC生成SQL Parser 仿照ANTLR生成的Parser结构手写 基于LL(2)识别器的手写 第一版 第二版 性能较差,优化不方便 仿照ANTLR生成的Parser结构手写 基于LL(*)的识别器,中间对象过多 基于LL(2)识别器的手写 第一版 第二版 第三版
架构调整 第三版LL(2) 第二版LL(*) DML Parser Expression Parser DML Parser token Lexer token Lexer cache Char Reader SQL char[] SQL String 第三版LL(2) 第二版LL(*)
功能对比 第一版 第二版 第三版 ‘don\’t’ .123e-2 7Eleven _latin 0x123 ‘abc’ ‘def’ NO YES .123e-2 7Eleven _latin 0x123 ‘abc’ ‘def’ INSERT('Quadratic', 3, 4, 'What') TRIM(LEADING 'x' FROM 'xxxbarxxx') Union select table join PART …… 版本: 1.0.4: http://svn.alibaba-inc.com/repos/ali_cn/commons/amoeba/tags/cobar-1.0.6-r/ Druid: http://code.alibabatech.com/svn/druid/trunk -r 262 手写v2: http://svn.alibaba-inc.com/repos/ali_platform/cobar/app/branches/20110613_1.2.0-dev/ -r 95254
MySQL 5.5 语法结构 SQL语句 Set/Show Delete Update Insert Replace Select 语法元素 Call ... OrderBy Limit Table References 表达式 基本元素 Identifier Keyword Variable Literal Punctuation
基本元素 Keyword Identifier Punctuation Variable 227个关键字,不区分大小写 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 Number Literal Hex/Bit 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 语法结构 SQL语句 Set/Show Delete Update Insert Replace Select 语法元素 Call ... OrderBy Limit Table References 表达式 基本元素 Identifier Keyword Variable Literal Punctuation
语法元素 – Table References table_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语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 tb1 LEFT JOIN t2 JOIN t3 USING (id)
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor table_factor table_reference 规则2 table_reference
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor table_factor table_factor join_condition 规则1 table_reference 规则2 table_reference
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) ERROR! 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor table_factor table_factor join_condition 规则1 table_reference ERROR! 规则2 table_reference
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) ERROR! 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 table_reference 规则2 table_reference 规则1 table_factor table_factor table_factor join_condition tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor table_factor table_factor join_condition 规则1 table_reference ERROR! 规则2 table_reference
MySQL不支持的MySQL语法 tb1 LEFT JOIN t2 JOIN t3 USING (id) ERROR! 规则1 table_reference: table_factor 'JOIN' table_factor [join_condition] table_reference: table_factor 'LEFT' 'JOIN' table_reference join_condition 规则2 table_reference 规则2 table_reference 规则1 table_factor table_factor table_factor join_condition tb1 LEFT JOIN t2 JOIN t3 USING (id) table_factor table_factor table_factor join_condition 规则1 table_reference ERROR! 规则2 table_reference
Table References的表达式特性 table_references: table_reference {',' table_reference} table_reference : ’(’ table_references ')' | ’(’ query { ’UNION’ query} ’)’ [’AS’] alias query : ’(’ query ’)’ | ’SELECT ...’ 规则1 规则2 规则2 ( ( select ...) UNOIN (select...) ) AS t1 规则1 ( ( t1, t2), t3 ) LL(1) 类似于表达式: expr: ’(’ expr ’)’ | tableRefs | subquery
MySQL 5.5 语法结构 SQL语句 Set/Show Delete Update Insert Replace Select 语法元素 Call ... OrderBy Limit Table References 表达式 基本元素 Identifier Keyword Variable Literal Punctuation
表达式 优先级和结合型 特殊函数 特殊Identifier 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 sqlgen Simple 25.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 单位微秒 126
GC对比 YGC YGCT 第一版 2838 0.803 第二版 410 0.116 第三版 229 0.057 第三版+sql生成 263 0.074 127
... Cobar结构 Application1 MySQL Protocol Front-end Communication Processor(1) Processor(n) Manager Monitor Configure SQL Parser Result Merger SQL Parser Result Merger ... SQL Router SQL Router Management Protocol SQL Executor SQL Executor Data Nodes HA Pool MySQL Protcol Adaptor (BIO) MySQL Protocol MySQL Protocol MySQL Protocol MySQL Protocol MySQL MySQL MySQL MySQL MySQL MySQL MySQL MySQL
MySQL Protocol Adapter 后台数据访问逻辑层次 数据库连接 基于协议数据包 与MySQL交互 Data Node HA Pool MySQL Protocol Adapter ip:port/ibank ip:port/ibank ip:port/ibank ip:port/offer ip:port/offer M S M S M S M S M S
基于MySQL协议 MySQL 新Cobar select * from offer select * from offer
基于MySQL协议 MySQL select * from offer select * from offer 新Cobar HEADER FIELD EOF ROW Result 2GB
MySQL Protocol Adapter 后台数据访问逻辑层次 主备连接池 Data Node HA Pool MySQL Protocol Adapter M S M S M S M S M S M S
MySQL Protocol Adapter 后台数据访问逻辑层次 心跳检测后端连接 Data Node HA Pool MySQL Protocol Adapter X M S M S M S M S M S M S
MySQL Protocol Adapter 后台数据访问逻辑层次 心跳检测后端连接 主库失效自动切换 至备库 重置池中连接 Data Node HA Pool MySQL Protocol Adapter M S M S M S M S M S M S
MySQL Protocol Adapter 后台数据访问逻辑层次 水平拆分的分库 Data Node HA Pool MySQL Protocol Adapter 分库1 分库2 分库3 分库4 分库5 分库6 M S M S M S M S M S M S
灵活的层间对应关系 M S M S M S M S M S M S 分库1 分库2 分库3 分库4 分库5 分库6 物理机 物理机 物理机
大纲 中间件引入 Cobar策略 系统实现 MySQL协议 通信 解析 后端连接 实施应用
offer/ibank/snapshot …… Cobar 的部署 青岛 杭州 美国 offer/ibank/snapshot …… 中文站 Cobar集群 Cobar集群 message center Cobar集群 Cobar集群 Cobar集群 国际站 hermes product Cobar集群 Cobar集群 ... ... ... Cobar Manager Cobar Manager Cobar Manager
... ... ... Cobar 的部署 青岛 杭州 美国 Cobar集群 德胜机房 Cobar集群 Cobar集群 Cobar Manager Cobar Manager Cobar Manager
Cobar集群 MySQL Protocol HTTP MySQL Protocol MySQL Protocol
数据迁移 场景 MySQL数据库节点扩容 拆分规则更改 目标 迁移过程中应用保持可用 数据不能丢失、多余或者不一致
迁移步骤 数据的全量dump 变更数据的增量dump 路由规则切换 清理 分库1 分库2 数据分片 数量变更 分库1 分库2 分库3
全量dump 分库1 分库2 分库3 分库1 分库2 分库3
全量dump 分库1 分库2 分库3 分库1 分库2 分库3 dump dump
全量dump 此时仍使用两份分库的拆分规则 让绿色数据对SQL语句不可见 分库1 分库2 分库3 invisible … WHERE ( … ) AND 非绿色数据 分库1 分库2 分库3 invisible invisible
增量dump 全量dump过程中,数据会持续变更 将binlog同步到新库中 分库1 分库2 分库3 invisible binlog Apply Apply
路由规则切换 暂停写入,等待binlog全部同步到新库 将路由规则更新为三个分库 分库1 分库2 分库3 invisible Apply
清理 删除老数据 分库1 分库2 分库3
大纲 中间件引入 Cobar策略 系统实现 实施应用 部署结构 平滑迁移
联系我们 http://code.alibabatech.com/wiki/display/cobar http://weibo.com/alicobar https://groups.google.com/group/ali-cobar https://github.com/alibaba/cobar