环境准备
这次的分享偏使用, 不探索 ShardingSphere 的代码过程 ( 实际是我还没编译通过… )
主要准备是 MySQL 主从环境, 我这里直接在 windows 上安装 mysql 5.7, 并拷贝了一份当做从库, 链接如下: https://blog.csdn.net/a345203172/article/details/106911270
更加方便的方式是启动 docker 来做一主多从的环境.
读写分离
在 ShardingSphere-5.0.0-alpha 中我是使用这样一段代码来实现读写分离:
@Bean(name = "dataSource")
public DataSource getDataSource() throws SQLException {
// 创建主从库数据源连接池
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("master", DataSourceUtil.createDataSource(url_master));
dataSourceMap.put("slave", DataSourceUtil.createDataSource(url_slave));
// 创建主从配置信息类
ReplicaQueryDataSourceRuleConfiguration dataSourceConfig = new ReplicaQueryDataSourceRuleConfiguration(
"master_slave_datasource", "master",
Arrays.asList("slave"), null);
// 创建规则配置类
ReplicaQueryRuleConfiguration ruleConfig = new ReplicaQueryRuleConfiguration(
Collections.singleton(dataSourceConfig), Collections.emptyMap());
// 工厂获得数据源
return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(ruleConfig), new Properties());
}
这里的核心是 ReplicaQueryRuleConfiguration 类, 可以配置主从的查询规则 (一主N从), 也可以配置从库的负载均衡策略 (我这里的代码是传入空集合, 使用默认的轮训策略).
然而在 5.0.0-beta 版中, 这块的内容是有所变化, 改后的代码如下:
@Bean(name = "dataSource")
public DataSource getDataSource() throws SQLException {
// 创建主从库数据源连接池
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("master", DataSourceUtil.createDataSource(url_master));
dataSourceMap.put("slave", DataSourceUtil.createDataSource(url_slave));
// 创建主从配置信息类
ReadwriteSplittingDataSourceRuleConfiguration dataSourceConfig = new ReadwriteSplittingDataSourceRuleConfiguration(
"master_slave_datasource", "", "master",
Arrays.asList("slave"), null);
// 创建规则配置类
ReadwriteSplittingRuleConfiguration ruleConfig = new ReadwriteSplittingRuleConfiguration(
Collections.singleton(dataSourceConfig), Collections.emptyMap());
// 工厂获得数据源
return ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(ruleConfig), new Properties());
}
ReplicaQueryRuleConfiguration 类被 ReadwriteSplittingRuleConfiguration 取代, ReplicaQueryDataSourceRuleConfiguration类被 ReadwriteSplittingDataSourceRuleConfiguration 取代. 看上去优化点就像把名字写的更加通俗易懂了些.
唯一一个不同点是在主从数据源配置类 ReadwriteSplittingDataSourceRuleConfiguration 中新加入了一个参数 autoAwareDataSourceName, 暂不清楚什么作用, 依照官方例子传入空字符串即可.
分库分表
准备好两个库, 做分库演示.
根据官方文档的示例, 使用两个字段 user_id 与 order_id 分别来控制 分库与分表 的分片算法依据, 具体代码如下:
@Bean(name = "dataSource")
public DataSource getDataSource() throws SQLException {
// 创建主从库数据源连接池
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("ds0", DataSourceUtil.createDataSource(url_ds0));
dataSourceMap.put("ds1", DataSourceUtil.createDataSource(url_ds1));
// 配置 t_order 表规则
ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("t_order", "ds${0..1}.t_order${0..1}");
// 配置分库策略
orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("user_id", "dbShardingAlgorithm"));
// 配置分表策略
orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("order_id", "tableShardingAlgorithm"));
// 配置分片规则
ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
shardingRuleConfig.getTables().add(orderTableRuleConfig);
// 配置分库算法
Properties dbShardingAlgorithmrProps = new Properties();
dbShardingAlgorithmrProps.setProperty("algorithm-expression", "ds${user_id % 2}");
shardingRuleConfig.getShardingAlgorithms().put("dbShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", dbShardingAlgorithmrProps));
// 配置分表算法
Properties tableShardingAlgorithmrProps = new Properties();
tableShardingAlgorithmrProps.setProperty("algorithm-expression", "t_order${order_id % 2}");
shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", tableShardingAlgorithmrProps));
// 创建 ShardingSphereDataSource
DataSource dataSource = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(shardingRuleConfig), new Properties());
return dataSource;
}
最终创建所使用的仍然是 ShardingSphereDataSourceFactory 工厂的 createDataSource() 方法, 而数据分片与读写分离相同的入参也提醒我们, 分片规则类 ShardingRuleConfiguration
与 读写分离规则类 ReadwriteSplittingRuleConfiguration
是源自同一个接口 RuleConfiguration
, 他们在 ShardingSphere 下都属于规则衍生类.
分库的效果是: db0 与 db1 下的 t_order1 都新增一行数据
分表的效果是: db1下的 t_order_0 与 t_order_1 新增一行数据.
加密
加密这块有两种处理方式, 一种是会在原字段上直接存储密文, 另一种是需要创建一个密文字段, ShardingSphere 会帮你同时存两者.
我这里的演示是选择第二种, 准备数据库表时, 需要准备明文与密文字段:
代码实现上, 我们同样看到与加密相关的规则类是 EncryptRuleConfiguration, 根据它所需的参数, 一层层配齐即可:
@Bean(name = "dataSource")
public DataSource getDataSource() throws SQLException {
Map<String, DataSource> dataSourceMap = new HashMap<>();
dataSourceMap.put("encryption", DataSourceUtil.createDataSource(url_encryption));
// 逻辑列名称
String logicColumn = "pwd";
// 密文列名称
String cipherColumn = "pwd_cipher";
// 原文列名称
String plainColumn = "pwd";
// 加密算法名称
String encryptorName = "aes_encryptor";
// 加密列规则配置
EncryptColumnRuleConfiguration encryptColumnRuleConfiguration = new EncryptColumnRuleConfiguration(logicColumn, cipherColumn, "", plainColumn, encryptorName);
// 加密表规则配置
EncryptTableRuleConfiguration encryptTableRuleConfiguration = new EncryptTableRuleConfiguration("t_user", Collections.singleton(encryptColumnRuleConfiguration));
// 加密算法配置
Properties properties = new Properties();
properties.setProperty("aes-key-value", "123456ac");
ShardingSphereAlgorithmConfiguration shardingSphereAlgorithmConfiguration = new ShardingSphereAlgorithmConfiguration("AES", properties);
Map<String, ShardingSphereAlgorithmConfiguration> shardingSphereAlgorithmConfigurationMap = Collections.singletonMap("aes_encryptor", shardingSphereAlgorithmConfiguration);
// 配置规则
EncryptRuleConfiguration encryptRuleConfiguration = new EncryptRuleConfiguration(Collections.singleton(encryptTableRuleConfiguration), shardingSphereAlgorithmConfigurationMap);
// 创建 ShardingSphereDataSource
DataSource dataSource = ShardingSphereDataSourceFactory.createDataSource(dataSourceMap, Collections.singleton(encryptRuleConfiguration), new Properties());
return dataSource;
}
那么在存储时可以看到, ShardingSphere 帮助存储了密文:
而在读取时, 根据我们所配置的逻辑列, 仍然可以得到明文信息:
小结
这次是对 ShardingSphere-JDBC 的三个主要功能模块进行实际使用, 且也只是使用的 Java API 方式. 但这样的使用应该是更直观的能感觉到 ShardingSphere-JDBC 的设计, 它将规则进行了统一的抽象, 由工厂类负责装载返回数据源.
我对探究这个工厂类的实现是挺有兴趣的, 之后可以进行源码分析.