一、ShardingProxy快速使用

ShardingProxy的功能同样是分库分表,但是他是一个独立部署的服务端,提供统一的数据库代理服务。
注意,ShardingProxy目前只支持MySQL和PostgreSQL。
并且,客户端连接ShardingProxy时,最好使用MySQL的JDBC客户端。
下面我们来部署一个ShardingProxy服务。

1、ShardingProxy部署

ShardingProxy在windows和Linux上提供了一套统一的部署发布包。我们可以从ShardingSphere官网下载4.1.1版本的ShardingProxy发布包apache-shardingsphere-4.1.1-sharding-proxy-bin.tar.gz,解压到本地目录。配套资料中已经提供
注意不要有中文路径
首先,我们需要把MySQL的JDBC驱动包mysql-connector-java-8.0.20.jar手动复制到ShardingProxy的lib目录下。ShardingProxy默认只附带了PostgreSQL的JDBC驱动包,而不包含MySQL的JDBC驱动包。
然后,我们需要到conf目录下,修改server.yaml,将配置文件中的authentication和props两段配置的注释打开。

  1. authentication:
  2. users:
  3. root:
  4. password: root
  5. sharding:
  6. password: sharding
  7. authorizedSchemas: sharding_db
  8. props:
  9. max.connections.size.per.query: 1
  10. acceptor.size: 16 # The default value is available processors count * 2.
  11. executor.size: 16 # Infinite by default.
  12. proxy.frontend.flush.threshold: 128 # The default value is 128.
  13. # LOCAL: Proxy will run with LOCAL transaction.
  14. # XA: Proxy will run with XA transaction.
  15. # BASE: Proxy will run with B.A.S.E transaction.
  16. proxy.transaction.type: LOCAL
  17. proxy.opentracing.enabled: false
  18. proxy.hint.enabled: false
  19. query.with.cipher.column: true
  20. sql.show: false
  21. allow.range.query.with.inline.sharding: false

然后,我们修改conf目录下的config-sharding.yaml,这个配置文件就是shardingProxy关于分库分表部分的配置。整个配置和之前我们使用ShardingJDBC时的配置大致相同,我们在最下面按照自己的数据库环境增加以下配置:

  1. schemaName: sharding_db
  2. dataSources:
  3. m1:
  4. url: jdbc:mysql://localhost:3306/userdb?serverTimezone=GMT%2B8&useSSL=false
  5. username: root
  6. password: root
  7. connectionTimeoutMilliseconds: 30000
  8. idleTimeoutMilliseconds: 60000
  9. maxLifetimeMilliseconds: 1800000
  10. maxPoolSize: 50
  11. shardingRule:
  12. tables:
  13. course:
  14. actualDataNodes: m1.course_$->{1..2}
  15. tableStrategy:
  16. inline:
  17. shardingColumn: cid
  18. algorithmExpression: course_$->{cid%2+1}
  19. keyGenerator:
  20. type: SNOWFLAKE
  21. column: cid

这一段就是按照我们之前的application01.properties文件中的规则配置的。可以看到,整个配置其实是大同小异的。
然后,还一个小问题要注意,我们进入ShardingProxy的Lib目录,里面会有些jar包因为名字太长了,导致有些文件的后缀被截断了,我们要手动把他们的文件后缀给修改过来。
image.png
然后,我们就可以启动ShardingProxy的服务了。启动脚本在bin目录下。其中,windows平台对应的脚本是start.bat,Linux平台对应的脚本是start.sh和stop.sh
启动时,我们可以直接运行start.bat脚本,这时候,ShardingProxy默认占用的是3307端口。为了不跟我们之前搭建的多个MySQL服务端口冲突,我们定制下启动端口,改为3316端口。
start.bat 3316
为什么windows平台上没有stop.bat呢?因为start.bat会独占一个命令行窗口,把命令行窗口关闭,就停止了ShardingProxy的服务。
启动完成后,可以看到几行关键的日志标识服务启动成功了。

  1. [INFO ] 10:46:53.930 [main] c.a.d.xa.XATransactionalResource - resource-1-m1: refreshed XAResource
  2. [INFO ] 10:46:54.580 [main] ShardingSphere-metadata - Loading 1 logic tables' meta data.
  3. [INFO ] 10:46:54.717 [main] ShardingSphere-metadata - Loading 8 tables' meta data.
  4. [INFO ] 10:46:56.953 [nioEventLoopGroup-2-1] i.n.handler.logging.LoggingHandler - [id: 0xc90e0eef] REGISTERED
  5. [INFO ] 10:46:56.958 [nioEventLoopGroup-2-1] i.n.handler.logging.LoggingHandler - [id: 0xc90e0eef] BIND: 0.0.0.0/0.0.0.0:3316
  6. [INFO ] 10:46:56.960 [nioEventLoopGroup-2-1] i.n.handler.logging.LoggingHandler - [id: 0xc90e0eef, L:/0:0:0:0:0:0:0:0:3316] ACTIVE

2、ShardingProxy使用

这样,我们就可以像连接一个标准MySQL服务一样连接ShardingProxy了。

  1. D:\dev-hook\mysql-8.0.20-winx64\bin>mysql.exe -P3316 -uroot -p
  2. Enter password: ****
  3. Welcome to the MySQL monitor. Commands end with ; or \g.
  4. Your MySQL connection id is 1
  5. Server version: 8.0.20-Sharding-Proxy 4.1.0
  6. Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
  7. Oracle is a registered trademark of Oracle Corporation and/or its
  8. affiliates. Other names may be trademarks of their respective
  9. owners.
  10. Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  11. mysql> show databases;
  12. +-------------+
  13. | Database |
  14. +-------------+
  15. | sharding_db |
  16. +-------------+
  17. 1 row in set (0.03 sec)
  18. mysql> use sharding_db
  19. Database changed
  20. mysql> show tables;
  21. +--------------------+
  22. | Tables_in_coursedb |
  23. +--------------------+
  24. | course |
  25. | t_dict |
  26. +--------------------+
  27. 2 rows in set (0.16 sec)
  28. mysql> select * from course;
  29. +--------------------+-------+---------+---------+
  30. | cid | cname | user_id | cstatus |
  31. +--------------------+-------+---------+---------+
  32. | 545730330389118976 | java | 1001 | 1 |
  33. | 545730330804355072 | java | 1001 | 1 |
  34. | 545730330842103808 | java | 1001 | 1 |
  35. | 545730330879852544 | java | 1001 | 1 |
  36. | 545730330917601280 | java | 1001 | 1 |
  37. +--------------------+-------+---------+---------+
  38. 5 rows in set (0.08 sec)

之前在ShardingJDBC部分完成了的其他几种分库分表策略以及读写分离策略,就请大家自行验证了。

3、ShardingProxy的服务治理

从ShardingProxy的server.yaml中看到,ShardingProxy还支持非常多的服务治理功能。在server.yaml配置文件中的orchestration部分属性就演示了如何将ShardingProxy注册到Zookeeper当中。

  1. orchestration:
  2. orchestration_ds:
  3. orchestrationType: registry_center,config_center,distributed_lock_manager
  4. instanceType: zookeeper
  5. serverLists: localhost:2181
  6. namespace: orchestration
  7. props:
  8. overwrite: false
  9. retryIntervalMilliseconds: 500
  10. timeToLiveSeconds: 60
  11. maxRetries: 3
  12. operationTimeoutMilliseconds: 500

ShardingSphere在服务治理这一块主要有两个部分:
一是数据接入以及弹性伸缩。简单理解就是把MySQL或者其他数据源的数据快速迁移进ShardingSphere的分片库中。并且能够快速的对已有的ShardingShere分片库进行扩容以及减配。这一块由ShardingSphere-scaling产品来提供支持。只是这个功能在目前的4.1.1版本中,还处于Alpha测试阶段。
另一方面,ShardingSphere支持将复杂的分库分表配置上传到统一的注册中心中集中管理。目前支持的注册中心有Zookeeper和Etcd。而ShardingSphere也提供了SPI扩展接口,可以快速接入Nacos、Apollo等注册中心。在ShardingProxy的server.yaml中我们已经看到了这一部分的配置示例。
另外,ShardingSphere针对他的这些生态功能,提供了一个ShardingSphere-UI产品来提供页面支持。ShardingSphere-UI是针对整个ShardingSphere的一个简单有用的Web管理控制台。它用于帮助用户更简单的使用ShardingSphere的相关功能。目前提供注册中心管理、动态配置管理、数据库编排管理等功能。
配套资料中也收集了ShardingSphere-UI的最新版本5.0.0-alpha版的运行包。解压后执行其中的start.bat就可以直接运行。

4、Shardingproxy的其他功能

影子库
这部分功能主要是用于进行压测的。通过给生产环境上的关键数据库表配置一个影子库,就可以将写往生产环境的数据全部转为写入影子库中,而影子库通常会配置成跟生产环境在同一个库,这样就可以在生产环境上直接进行压力测试,而不会影响生产环境的数据。
在conf/config-shadow.yaml中有配置影子库的示例。其中最核心的就是下面的shadowRule这一部分。

  1. #shadowRule:
  2. # column: shadow
  3. # shadowMappings:
  4. # 绑定shadow_dsds的影子库
  5. # ds: shadow_ds

数据加密
在conf/config-encrypt.yaml中还演示了ShardingProxy的另一个功能,数据加密。默认集成了AES对称加密和MD5加密。还可以通过SPI机制自行扩展更多的加密算法。

5、ShardingProxy的SPI扩展

上一部分提到了ShardingSphere保留了大量的SPI扩展接口,对主流程封闭、对SPI开放。这在ShardingJDBC中还体现不出太大的作用,但是在ShardingProxy中就能极大程度提高服务的灵活性了。
在ShardingProxy中,只需要将自定义的扩展功能按照SPI机制的要求打成jar包,就可以直接把jar包放入lib目录,然后就配置使用了。
例如如果想要扩展一个新的主键生成策略,只需要自己开发一个主键生成类

  1. package com.roy.shardingDemo.spiextention;
  2. import org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator;
  3. import java.time.LocalDateTime;
  4. import java.time.format.DateTimeFormatter;
  5. import java.util.Properties;
  6. import java.util.concurrent.atomic.AtomicLong;
  7. /**
  8. * @author :楼兰
  9. * @date :Created in 2020/12/17
  10. * @description:
  11. **/
  12. public final class MykeyGenerator implements ShardingKeyGenerator {
  13. private AtomicLong atom = new AtomicLong(0);
  14. private Properties properties = new Properties();
  15. public synchronized Comparable<?> generateKey() {
  16. //读取了一个自定义属性
  17. String prefix = properties.getProperty("mykey-offset", "100");
  18. LocalDateTime ldt = LocalDateTime.now();
  19. String timestampS = DateTimeFormatter.ofPattern("HHmmssSSS").format(ldt);
  20. return Long.parseLong(""+prefix+timestampS+atom.incrementAndGet());
  21. }
  22. //扩展算法的类型
  23. public String getType() {
  24. return "MYKEY";
  25. }
  26. public Properties getProperties() {
  27. return this.properties;
  28. }
  29. public void setProperties(Properties properties) {
  30. this.properties = properties;
  31. }
  32. }

然后增加一个META-INF\services\org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator文件,并在文件中写明自己的实现类。com.roy.shardingDemo.spiextention.MykeyGenerator 将扩展类和这个SPI服务文件一起打成jar包,就可以直接放到ShardingProxy的lib目录下。
image.png
接下来就可以在config-sharding.yaml中以类似下面这种配置方式引入了。

  1. shardingRule:
  2. tables:
  3. course:
  4. actualDataNodes: m1.course_$->{1..2}
  5. tableStrategy:
  6. inline:
  7. shardingColumn: cid
  8. algorithmExpression: course_$->{cid%2+1}
  9. keyGenerator:
  10. # type: SNOWFLAKE
  11. type: MYKEY # 自定义的主键生成器
  12. column: cid

然后我们可以启动ShardingProxy,试试我们自定义的主键生成器。

  1. mysql> select * from course;
  2. +--------------------+-------+---------+---------+
  3. | cid | cname | user_id | cstatus |
  4. +--------------------+-------+---------+---------+
  5. | 222 | java2 | 1002 | 1 |
  6. | 545730330389118976 | java | 1001 | 1 |
  7. | 545730330804355072 | java | 1001 | 1 |
  8. | 545730330842103808 | java | 1001 | 1 |
  9. | 545730330879852544 | java | 1001 | 1 |
  10. | 545730330917601280 | java | 1001 | 1 |
  11. +--------------------+-------+---------+---------+
  12. 6 rows in set (0.01 sec)
  13. mysql> insert into course(cname,user_id,cstatus) values ('java2',1002,'1');
  14. Query OK, 1 row affected (0.11 sec)
  15. mysql> insert into course(cname,user_id,cstatus) values ('java2',1003,'1');
  16. Query OK, 1 row affected (0.01 sec)
  17. mysql> select * from course;
  18. +--------------------+-------+---------+---------+
  19. | cid | cname | user_id | cstatus |
  20. +--------------------+-------+---------+---------+
  21. | 222 | java2 | 1002 | 1 |
  22. | 1001509178012 | java2 | 1003 | 1 |
  23. | 545730330389118976 | java | 1001 | 1 |
  24. | 545730330804355072 | java | 1001 | 1 |
  25. | 545730330842103808 | java | 1001 | 1 |
  26. | 545730330879852544 | java | 1001 | 1 |
  27. | 545730330917601280 | java | 1001 | 1 |
  28. | 1001509119631 | java2 | 1002 | 1 |
  29. +--------------------+-------+---------+---------+
  30. 8 rows in set (0.01 sec)

从结果可以看到,插入的两条记录,自动生成的CID分别为1001509178012、1001509119631。这样我们就很快的完成了一个自定义的主键生成策略。
关于ShardingSphere的SPI扩展点,在配套资料《shardingsphere_docs_cn.pdf》的开发者手册部分有更全面详细的梳理。

二、ShardingSphere总结

我们现在已经学完了ShardingSphere除了Sharding-SideCar以外的所有产品了,整个sharding + proxy的所有这些功能,本质上其实都只解决了一个问题,就是单机数据库容量的问题。在软件层面对硬件资源进行管理,从而便于对数据库的横向扩展。
但是,我们也要意识到他带来的很多问题。
例如对业务的侵入大。业务系统写的SQL将不再是纯粹的能在服务器上运行的SQL了,对大量跨维度的JOIN、聚合、子查询、排序等功能在业务上很难进行验证。这必然会弱化数据库的功能。
并且,使用ShardingSphere管理后,数据库之间变成了结合非常紧密的依赖关系,对整个集群的扩容也会带来相当大的难度。
另外,ShardingSphere这种方式实际上将原本由业务管理SQL的工作方式,转化成了由业务管理逻辑SQL,而运维管理实际SQL的混合工作模式,再加上一大堆服务的引入,整个服务运维的维护工作量以及工作难度也上升了非常多。
当然,相信随着ShardingSphere后续版本的不断升级优化,这些问题都会得到不同程度的改善。

三、与其他相关产品的对比

业界组件 原厂 功能特性 备注
DBLE 爱可生开源社区 专注于mysql的高可扩展性的分布式中间件 基于MyCAT开发出来的增强版。
Meituan Atlas 美团 读写分离、单库分表 目前已经在原厂逐步下架。
Cobar 阿里(B2B) Cobar 中间件以 Proxy 的形式位于前台应用和实际数据库之间,对前台的开放的接口是 MySQL 通信协议 开源版本中数据库只支持 MySQL,并且不支持读写分离。
MyCAT 阿里 是一个实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用MySQL 原生协议与多个 MySQL 服务器通信 MyCAT 基于阿里开源的 Cobar 产品而研发
Atlas 360 读写分离、静态分表
Kingshard 由 Go 开发高性能 MySQL Proxy 项目,在满足基本的读写分离的功能上,Kingshard 的性能是直连 MySQL 性能的80%以上。
TDDL 阿里淘宝 动态数据源、读写分离、分库分表 TDDL 分为两个版本, 一个是带中间件的版本, 一个是直接 JAVA library 的版本。
Zebra 美团点评 实现动态数据源、读写分离、分库分表、CAT监控 功能齐全且有监控,接入复杂、限制多。
MTDDL 美团点评 动态数据源、读写分离、分布式唯一主键生成器、分库分表、连接池及SQL监控
Vitess 谷歌、Youtube 集群基于ZooKeeper管理,通过RPC方式进行数据处理,总体分为,server,command line,gui监控 3部分 Youtube 大量应用
DRDS 阿里 DRDS(Distributed Relational Database Service)专注于解决单机关系型数据库扩展性问题,具备轻量(无状态)、灵活、稳定、高效等特性,是阿里巴巴集团自主研发的中间件产品。