|
sharding-jdbc分享
1.简介Sharding-JDBC 历史Sharding-JDBC 是当当应用框架 ddframe 中,从关系型数据库模块 dd-rdb 中分离出来的数据库水平分片框架,实现透明化数据库分库分表访问。Sharding-JDBC 是继 dubbox 和 elastic-job 之后, ddframe 系列开源的第 3 个项目。3.X 之后已经改变了名字,叫 ShardingSphere ,已交由 apache 进行孵化。ShardingSphere 简介ShardingSphere 是一套开源的分布式数据库中间件解决方案组成的生态圈,它由 Sharding-JDBC 、 Sharding-Proxy 和 Sharding-Sidecar (计划中)这 3 款相互独立的产品组成。他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如 Java 同构、异构语言、容器、云原生等各种多样化的应用场景。如果我们不需要向 mycat 一样,部署独立服务代理,那么其实我们只要关注 Sharding-JDBC 即可,目前最新的是 4.0.0-RC1 的版本。Sharding-JDBC 简介定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。适用于任何基于 Java 的 ORM 框架,如:JPA , Hibernate , Mybatis , Spring JDBC Template 或直接使用 JDBC 。基于任何第三方的数据库连接池,如:DBCP , C3P0 , BoneCP , Druid , HikariCP 等。支持任意实现 JDBC 规范的数据库。目前支持 MySQL , Oracle , SQLServer 和 PostgreSQL 。2.分库分表分库分表用于应对当前互联网常见的两个场景——大数据量和高并发分库分表-垂直拆分当一个数据库中存在着多种不同业务中的表时,各种业务需要同时操作这个 DB ,数据库过大过多会引起 IO 读写瓶颈,这个时候就需要垂直拆分,将一个库(表)拆分为多个库(表)。优点:拆分后业务清晰子系统之间的整合与扩展相对容易数据便于管理缺点:提高系统复杂度单业务量过大还是不能解决该问题存在跨库事务的一致性问题分库分表-水平拆分单业务量过大的情况下,比如订单交易量过大,会导致单 db 的 io 被打满, cpu 飙升,那么这个时候就需要对订单进行水平拆分,根据分片算法将一个库(表)拆分为多个库(表)优点:单库单表的数据容量可以维持在一个量级,有助于提高业务 SQL 的执行效率和系统性能可以提高业务系统的稳定性和负载能力缺点:数据水平切分后,分布在多库多表中,跨库 Join 查询比较复杂分片数据的一致性较为难保证对于历史数据的迁移和数据库的扩容需要较大的维护工作量3.原理解析真实库:表示在真实存在数据库中的物理库。比如 ordercenter_0 到 ordercenter_7真实表:表示在真实存在数据库中的物理表。比如 orders_0 到 orders_1023数据节点:ordercenter_0.orders_0逻辑表:水平拆分数据库中表的总称。比如 ordersSharding-JDBC 的整体架构图:分片规则配置支持分片策略自定义、复数分片键、多运算符分片等功能。如:根据用户 ID 分库分表;也可以根据年来分库,根据月份分表这种分库分表结合的分片策略。Sharding-JDBC 除了支持等号运算符进行分片,还支持 in/between 运算符分片,提供了更加强大的分片功能。JDBC 规范重写Sharding-JDBC 对 JDBC 规范的重写思路是针对 DataSource 、 Connection 、 Statement 、 PreparedStatement 和 ResultSet 五个核心接口封装,将多个真实 JDBC 实现类集合(如:MySQLJDBC 实现 /DBCPJDBC 实现等)纳入 Sharding-JDBC 实现类管理。SQL 解析SQL 解析作为分库分表类产品的核心,性能和兼容性是最重要的衡量指标目前常见的 SQL 解析器主要有 fdb/jsqlparser 和 Druid 。Sharding-JDBC 使用 Druid 作为 SQL 解析器,经实际测试, Druid 解析速度是另外两个解析器的几十倍。如:select id , name from t_user where status = 'active' and age > 18;SQL 改写SQL 改写分为两部分:将分表的逻辑表名称替换为真实表名称。根据 SQL 解析结果替换一些在分片环境中不正确的功能。第 1 个例子是 avg 计算。例如在分片的环境中,以 avg1 + avg2 + avg3 / 3 计算平均值并不正确,需要改写为( sum1 + sum2 + sum3 )/( count1 + count2 + count3 )第 2 个例子是分页。假设每 10 条数据为一页,取第 2 页数据。在分片环境下获取 limit 10 , 10 ,归并之后再根据排序条件取出前 10 条数据是不正确的结果。正确的做法是将分条件改写为 limit 0 , 20 ,取出所有前 2 页数据,再结合排序条件算出正确的数据select score from t_score order by score desc limit 1 , 2;SQL 路由SQL 路由分为:标准路由,直接路由和笛卡尔积路由例如:select o.* FROM orders o left join order_goods g ono.id = g.order_id where o.user_id in ( 1 , 2 );如果两个有绑定关系(用同种规则进行分库分表)则会解析成以下 2 条 SQL (标准路由)select o.* from orders_1 o left join order_goods_1g on o.id = g.order_id where o.user_id in ( 1 , 2 );select o.* from orders_2oleft join order_goods_2g on o.id = g.order_id where o.user_id in ( 1 , 2 );如果两个有没有绑定关系则会解析成以下 1024 * 1024 条 SQL (笛卡尔积路由)select o.* from orders_0oleft join order_goods_1 g on o.id = g.order_id where o.user_id in ( 1 , 2 );select o.* from orders_0oleft join order_goods_2 g on o.id = g.order_id where o.user_id in ( 1 , 2 );……select o.* from orders_1023 oleft join order_goods_1023g on o.id = g.order_id where o.user_id in ( 1, 2 );结果归并结果归并包括 4 类:普通遍历类、排序类、聚合类和分组类普通遍历类最为简单,只需按顺序遍历 ResultSet 的集合即可排序类结果将结果先排序再输出,因为各分片结果均按照各自条件完成排序,所以采用归并排序算法整合最终结果聚合类分为 3 种类型,比较型、累加型和平均值型。比较型包括 max 和 min ,只返回最大(小)结果。累加型包括 sum 和 count ,需要将结果累加后返回。平均值则是通过 SQL 改写的 sum 和 count 计算分组类最为复杂,需要将所有的 ResultSet 结果放入内存,使用 map-reduce 算法分组,最后根据排序和聚合条件做相关处理。最消耗内存,最损失性能的部分即是此,可以考虑使用 limit 合理的限制分组数据大小。标准分库算法标准分表算法快速接入实战引入 jar 包: org.apache.shardingsphere sharding-jdbc-spring-boot-starter 4.1.1 org.apache.shardingsphere sharding-jdbc-spring-namespace 4.1.1添加配置:#数据库分表规则#数据源配置spring.shardingsphere.datasource.names = master0#库master0 的连接配置spring.shardingsphere.datasource.master0.type = com.alibaba.druid.pool.DruidDataSourcespring.shardingsphere.datasource.master0.driver-class-name = com.mysql.jdbc.Driverspring.shardingsphere.datasource.master0.url = 数据库地址spring.shardingsphere.datasource.master0.username = 账号spring.shardingsphere.datasource.master0.password = 密码spring.shardingsphere.datasource.master0.initial-size = 10spring.shardingsphere.datasource.master0.min-idle = 5spring.shardingsphere.datasource.master0.maxActive = 200spring.shardingsphere.datasource.master0.maxWait = 60000spring.shardingsphere.datasource.master0.timeBetweenEvictionRunsMillis = 60000spring.shardingsphere.datasource.master0.minEvictableIdleTimeMillis = 300000spring.shardingsphere.datasource.master0.validationQuery = SELECT 1spring.shardingsphere.datasource.master0.testWhileIdle = truespring.shardingsphere.datasource.master0.testOnBorrow = falsespring.shardingsphere.datasource.master0.testOnReturn = falsespring.shardingsphere.datasource.master0.poolPreparedStatements = truespring.shardingsphere.datasource.master0.maxPoolPreparedStatementPerConnectionSize = 20spring.shardingsphere.datasource.master0.filters = stat,wall,log4j2spring.shardingsphere.datasource.master0.connectionProperties = druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000# 需要分表的表声明 spring.shardingsphere.sharding.tables.表名.actual-data-nodes = master0.表名$->{0..N}#分表字段spring.shardingsphere.sharding.tables.表名.table-strategy.inline.sharding-column = 分表字段X#分片算法表达式,简单的取模为例spring.shardingsphere.sharding.tables.表名.table-strategy.inline.algorithm-expression = 分表的表名$->{分表字段X % N}#打印sqlspring.shardingsphere.props.sql.show = false#校验表是否存在backlogSyncConfig.checkTableExist = false数据库表初始化后,就可以启动项目开始探索了~~官方文档地址https://shardingsphere.apache.org/index_zh.html招贤纳士团队一个富有激情、创造力和执行力的团队,Base 在风景如画的杭州。团队现有500多名研发小伙伴,既有来自阿里、华为、网易的“老”兵,也有来自浙大、中科大、杭电等校的新人。团队在日常业务开发之外,还分别在云原生、区块链、人工智能、低代码平台、中间件、大数据、物料体系、工程平台、性能体验、可视化等领域进行技术探索和实践,推动并落地了一系列的内部技术产品,持续探索技术的新边界。此外,团队还纷纷投身社区建设,目前已经是 google flutter、scikit-learn、Apache Dubbo、Apache Rocketmq、Apache Pulsar、CNCF Dapr、Apache DolphinScheduler、alibaba Seata 等众多优秀开源社区的贡献者。
|
|