当当网架构部总监张亮:分布式数据库中间件的设计与实现

2020-02-27 541浏览

  • 1.分布式数据库中间件 的设计与实现 全球敏捷演运讲维人峰:会张亮北京站
  • 2.互联网领域数据库面临的问题 高可用 存储稳定性要求高 并发访问频繁 数据海量 全球敏捷运维峰会 北京站
  • 3.各种数据库方案对比 RDBMS NoSQL SQL支持 原生 不支持 事务 ACID+XA BASE 存储引擎 成熟 较成熟 数据分片 有限支持 支持 动态扩容 不支持 有限支持 NewSQL 不完善 F1 待验证 支持 支持较好 全球敏捷运维峰会 北京站
  • 4.RDBMS解决方案的优缺点 开发友好,面向SQL 存储引擎稳定 单节点事务引擎成熟 未达阀值的单机性能高 单节点并发访问频率受限 单节点数据承载量受限 分布式事务性能难以接受 分布式扩展困难 全球敏捷运维峰会 北京站
  • 5.当当数据库中间层的关注重点 治理 •配置动态化 •数据源自动切 换 事务 • 弱XA • 柔性事务 分片 • 分库分表 • 读写分离 • 分布式主键 全球敏捷运维峰会 北京站
  • 6.单库 App Server 1 App Server 2 App Server 3 read/write • 可用性差 • 访问量瓶颈受限 • 性能低下 全球敏捷运维峰会 北京站
  • 7.读写分离 read sync App Server 1 App Server 2 • 可用性略提升 • 访问量瓶颈提升 • 性能改善 • 数据短期不一致 App Server 3 write 全球敏捷运维峰会 北京站
  • 8.分库分表+读写分离 read sync App Server 1 write App Server 2 • 可用性提升 • 无访问量瓶颈 • 性能大幅改善 • 数据短期不一致 • 复杂 App Server 3 全球敏捷运维峰会 北京站
  • 9.引入数据库中间层 App Server 1 App Server 2 App Server 3 数据库中间层 • 可维护性提升 • 简明清晰 全球敏捷运维峰会 北京站
  • 10.分片类型 垂直分片 • 业务拆分 水平分片 • 算法规则拆分 全球敏捷运维峰会 北京站
  • 11.垂直分片 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_order WHERE id=1 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_order WHERE id=1 全球敏捷运维峰会 北京站
  • 12.水平分片 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_user WHERE id=2 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_user WHERE id=2 全球敏捷运维峰会 北京站
  • 13.水平分片策略 哈希 复合 范围 时间 标签 全球敏捷运维峰会 北京站
  • 14.哈希取模分片策略 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_user WHERE id=2 user_1 user_2 全球敏捷运维峰会 北京站
  • 15.范围分片策略 SELECT * FROM t_user WHERE id=1 SELECT * FROM t_user WHERE id=1001 SELECT * FROM t_user WHERE id=2001 全球敏捷运维峰会 北京站 user_1 1~1000 user_2 1001~2000 user_3 >2000
  • 16.标签分片策略 SELECT * FROM t_user WHERE location=‘bj’ SELECT * FROM t_user WHERE location =‘sh’ user_bj user_sh 全球敏捷运维峰会 北京站
  • 17.时间分片策略 SELECT * FROM t_order WHERE year=2015 SELECT * FROM t_order WHERE year=2016 SELECT * FROM t_order WHERE year=2017 全球敏捷运维峰会 北京站 db_2015 db_2016 db_2017
  • 18.复合分片策略 SELECT * FROM t_order WHERE user_id=1 AND order_id=1001 SELECT * FROM t_order WHERE user_id=1 AND order_id=1002 order_1 order_2 SELECT * FROM t_order WHERE user_id=2 AND order_id=2001 order_1 SELECT * FROM t_order WHERE user_id=2 AND order_id=2002 order_2 全球敏捷运维峰会 北京站 user_1 user_2
  • 19.实现方案 非透明 • 业务修改SQL • 指定数据源 透明化 • 完全屏蔽分片细则 全球敏捷运维峰会 北京站
  • 20.透明化实现方案选型 Proxy 数据库 单一 ORM 任意 异构语言 任意 性能 损耗略高 ORM 任意 单一 仅Java 损耗低 JDBC 任意 任意 仅Java 损耗低 全球敏捷运维峰会 北京站
  • 21.Sharding-JDBC是什么 • 开源的分布式数据库中间件,它无需额外 部署和依赖,旧代码迁移成本几乎为零。 • 面向开发的微服务与云原生的基础类库。 • 完整的实现了分库分表、读写分离和分布 式主键功能,并初步实现了柔性事务,治 理正在功能开发中。 全球敏捷运维峰会 北京站
  • 22.Sharding-JDBC兼容性 ORM支持 •Mybatis •JPA •Hibernate •JDBC •MySQL •Oracle •SQLServer •PostgreSQL 数据库支 持 •DQL •DML •DDL SQL支持 全球敏捷运维峰会 北京站
  • 23.应用 业务代码 Sharding- JDBC 分片架构图 应用 业务代码 Sharding- JDBC Sharding-JDBC 内部实现 分片规则配置 JDBC规范改写 SQL解析 SQL路由 结果归并 SQL改写 SQL执行 全球敏捷运维峰会 北京站
  • 24.JDBC规范改写 DDatDaataSatoSauoSruocruecrece initialize ShardingResultSet merge ShardingDataSource ResultSet create execute get ShardingConnection Sharding(Prepared)Statement route create wrap CConConnoenncentceiotcinotinon create (Prepared)Statement 全球敏捷运维峰会 北京站
  • 25.为什么需要解析SQL 无需解析SQL的场景 • 仅分库的单分片查询 • 仅分库的跨分片的无聚合、排序、分组查询 需要解析SQL的场景 •包含分表的查询 •跨分片的聚合、排序、分组查询 •复杂查询,如:OR、UNION、子查询等 全球敏捷运维峰会 北京站
  • 26.SQL解析示例 SELECT HIGH_PRIORITY STRAIGHT_JOIN SQL_BUFFER_RESULT SQL_NO_CACHE id, name FROM table_x WHERE id=1 INTO OUTFILE 'file_a' LOCK IN SHARE MODE SELECT id, name FROM table_a WHERE id=1 { table : table_x sharding-column : id sharding-value : 1 } SELECT HIGH_PRIORITY STRAIGHT_JOIN SQL_BUFFER_RESULT SQL_NO_CACHE id, name FROM token WHERE id=1 INTO OUTFILE 'file_a' LOCK IN SHARE MODE 全球敏捷运维峰会 北京站
  • 27.SQL解析 初版 使用Druid Druid Lexer Parser AST OutputVisitor SQLBuilder AbstractMySQLVisitor 问题(仅针对专注于 Sharding的解析) • 性能 • 需解析全SQL,语法树复杂 • 需二次访问语法树,再次生 成解析结果 • 准确性 • 重新生成导致原SQL变化 • 易读性 • 针对OutputVisitor重写,编 码零散 • 兼容性 • Druid升级后不兼容之前版本 ParseContext 全球敏捷运维峰会 北京站
  • 28.SQL解析 再版 自研SQL解析 Lexer SQLBuilder Parser ParseContext 提升 • 性能 • 仅解析与分片相关部分 • 无需二次访问语法树 • 准确性 • 使用原SQL,无需再生成 • 易读性 • 代码聚合,无零散编码 • 稳定性 • 减少依赖,剥离第三方lib升 级兼容问题 全球敏捷运维峰会 北京站
  • 29.路由算法 Standard • 单分片键 • 精确路由(=,IN) + 范围路由(Between) Inline • 单分片键 • Inline表达式,eg:t_user_${userid % 8} Complex • 多分片键 • 分片算法的复杂度由用户自行控制 Hint • 无分片键 • 通过Hint直接指定DataNode None • 不分片 全球敏捷运维峰会 北京站
  • 30.路由类型 单表 • SQL中仅存在单一表 级联表 • SQL中仅存在多表, 但分表策略完全一致 笛卡尔积 • SQL中仅存在多表, (不推荐OLTP) 且分表策略不一致 全球敏捷运维峰会 北京站
  • 31.SQL改写 表名称 • 标记Token LIMIT • LIMIT m, n => LIMIT 0, n AVG • AVG(expr) => SUM(expr), COUNT(expr) ORDER BY • 排序列生成补列 GROUP BY • 分组列生成补列 • ORDER BY补充 自增主键 • 主键生成补列 全球敏捷运维峰会 北京站
  • 32.为何改写Limit 表t_score_0 score 100 90 80 表t_score_1 score 95 85 75 SELECT score FROM t_score ORDER BY score DESC LIMIT 1,2 SQL不改写的查询结果 表t_score_0 score 90 80 表t_score_1 score 85 75 最终归并结果 score 85 80 全球敏捷运维峰会 北京站
  • 33.为何改写Limit SQL改写 SELECT score FROM t_score ORDER BY score DESC LIMIT 0,3 SQL改写后的查询结果 表t_score_0 score 100 90 80 表t_score_1 score 95 85 75 最终归并结果 score 95 90 全球敏捷运维峰会 北京站
  • 34.为何补列 • 无需补列的场景 SELECT id, name FROM t_user WHERE ORDER BY name • 需要补列的场景 SELECT id, age FROM t_user WHERE ORDER BY name SELECT id, name AS n FROM t_user WHERE ORDER BY name SELECT u.* FROM t_user AS u JOIN t_order AS o ON u.user_id=o.user_id WHERE ORDER BY name 全球敏捷运维峰会 北京站
  • 35.结果归并 LIMIT • LIMIT m, n => LIMIT 0, n • 跳过前n条数据 MIN,MAX • 比较并返回最小(大)值 SUM,COUNT • 多结果集累加,DISTINCT暂未实现 AVG ORDER BY GROUP BY • AVG(expr) => SUM(expr), COUNT(expr) • return SUM / COUNT • 排序列生成补列 • 多结果集归并排序 • 分组列生成补列 • 所有结果集加载至内存进行分组、聚合、排序 全球敏捷运维峰会 北京站
  • 36.读写分离 仅读写分离 仅分库分表 分库分表+读写分离 全球敏捷运维峰会 北京站
  • 37.其他功能 Inline表达式 分布式自增序列 柔性事务 全球敏捷运维峰会 北京站
  • 38.Sharding-JDBC注意事项 分片键设计应尽量让读写请求均衡负载 分布式查询不带分片键导致的全路由 LIMIT语句offset过大导致的内存问题 全球敏捷运维峰会 北京站
  • 39.Roadmap 配置动态化(进行中) • 数据源动态切换 • 数据库访问层治理 更多SQL的支持 •子查询深度支持 •OR •批量INSERT 柔性事务 • TCC 全球敏捷运维峰会 北京站
  • 40.Sharding-JDBC成绩单https://shardingjdbc.ioGithub Star 2759 fork 1198 获得开源中国2016年最受欢迎的开源软件 第17名 入选码云年度GVP项目 明确采用公司24家 全球敏捷运维峰会 北京站
  • 41.THANK YOU! 全球敏捷运维峰会 北京站