ShardingSphere-Proxy
概述
ShardingSphere-Proxy 是独立部署的数据库代理服务。与 JDBC 嵌入模式不同,Proxy 对应用完全透明——应用无需修改任何代码,只需连接 Proxy 地址即可使用分库分表能力。
架构对比
JDBC 模式(嵌入应用) Proxy 模式(独立部署)
┌──────────────┐ ┌──────────────┐
│ 应用进程 │ │ 应用进程 │
│ ShardingJDBC │ ← 嵌入 JDBC 层 │ JDBC 直连 │
└──────┬───────┘ └──────┬───────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────┐
│ MySQL/DB │ │ ShardingProxy│
└──────────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ MySQL/DB │
└──────────────┘一、部署与配置
1.1 下载启动
bash
# 下载
wget https://dlcdn.apache.org/shardingsphere/5.5.0/apache-shardingsphere-5.5.0-shardingsphere-proxy-bin.tar.gz
tar -xzf apache-shardingsphere-5.5.0-shardingsphere-proxy-bin.tar.gz
cd apache-shardingsphere-5.5.0-shardingsphere-proxy-bin
# 配置
vim conf/server.yaml # 全局配置
vim conf/config-sharding.yaml # 分片规则
# 启动
bin/start.sh # 默认端口 3307
# Docker
docker run -d \
-p 3307:3307 \
-v /path/to/conf:/opt/shardingsphere-proxy/conf \
apache/shardingsphere-proxy:5.5.01.2 Server 配置
yaml
# conf/server.yaml
mode:
type: Standalone
repository:
type: File
overwrite: true
authority:
users:
- user: root@%
password: root
- user: sharding@%
password: sharding
props:
sql-show: true # 打印 SQ L日志
proxy-frontend-database-protocol-type: MySQL # 兼容 MySQL 协议
proxy-frontend-max-connections: 100
proxy-backend-query-connection-pool-size: 20
check-table-meta-data-in-period: 301.3 分片规则配置
yaml
# conf/config-sharding.yaml
databaseName: sharding_db
dataSources:
ds0:
url: jdbc:mysql://192.168.1.10:3306/order_0
username: root
password: root
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
minPoolSize: 1
ds1:
url: jdbc:mysql://192.168.1.11:3306/order_1
username: root
password: root
ds2:
url: jdbc:mysql://192.168.1.12:3306/order_2
username: root
password: root
ds3:
url: jdbc:mysql://192.168.1.13:3306/order_3
username: root
password: root
rules:
- !SHARDING
tables:
t_order:
actualDataNodes: ds${0..3}.t_order_${0..15}
databaseStrategy:
standard:
shardingColumn: user_id
shardingAlgorithmName: database_inline
tableStrategy:
standard:
shardingColumn: order_id
shardingAlgorithmName: table_inline
shardingAlgorithms:
database_inline:
type: INLINE
props:
algorithm-expression: ds${user_id % 4}
table_inline:
type: INLINE
props:
algorithm-expression: t_order_${order_id % 16}二、数据加密
2.1 加密配置
yaml
# conf/config-encrypt.yaml
databaseName: encrypt_db
rules:
- !ENCRYPT
encryptors:
aes_encryptor:
type: AES
props:
aes-key-value: "abcdef1234567890"
md5_encryptor:
type: MD5
tables:
t_user:
columns:
phone:
cipherColumn: phone_encrypt # 密文列
encryptorName: aes_encryptor
id_card:
cipherColumn: id_card_encrypt # 密文列
encryptorName: aes_encryptor
assistedQueryColumn: id_card_assisted # 辅助查询列
queryWithCipherColumn: true # 查询返回明文
t_user_log:
columns:
login_ip:
cipherColumn: login_ip_encrypt
encryptorName: md5_encryptor
likeQueryColumn: login_ip_like # 模糊查询列2.2 存量数据迁移
sql
-- 应用无感知:插入时自动加密
INSERT INTO t_user (id, name, phone, id_card) VALUES (1, '张三', '13800138000', '110101199001011234');
-- 实际存储:phone_encrypt = AES('13800138000'), id_card_encrypt = AES('110101199001011234')
-- 查询自动解密
SELECT phone FROM t_user WHERE id = 1;
-- 返回明文:13800138000
-- 存量数据加密迁移:
-- 1. 在数据库中添加密文列(phone_encrypt, id_card_encrypt)
-- 2. 执行脚本加密存量数据
UPDATE t_user SET phone_encrypt = AES_ENCRYPT(phone, 'key'),
id_card_encrypt = AES_ENCRYPT(id_card, 'key');
-- 3. 应用切换 Proxy 连接
-- 4. 验证无误后删除明文列三、读写分离
3.1 配置
yaml
# conf/config-readwrite-splitting.yaml
databaseName: order_db
dataSources:
primary_ds:
url: jdbc:mysql://192.168.1.100:3306/order
username: root
password: root
maxPoolSize: 50
replica_ds_0:
url: jdbc:mysql://192.168.1.101:3306/order
username: root
password: root
replica_ds_1:
url: jdbc:mysql://192.168.1.102:3306/order
username: root
password: root
rules:
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
staticStrategy:
writeDataSourceName: primary_ds
readDataSourceNames:
- replica_ds_0
- replica_ds_1
loadBalancerName: round_robin # 轮询负载均衡
transactionalReadQueryStrategy: PRIMARY # 事务内强制读主库
loadBalanceManagers:
round_robin:
type: ROUND_ROBIN3.2 混合模式
yaml
# 分库分表 + 读写分离 + 数据加密 同时启用
databaseName: complex_db
dataSources:
# 4 主 + 4 从
primary_ds0: ...
replica_ds0_0: ...
replica_ds0_1: ...
# ... 其他分片
rules:
- !SHARDING
# ... 分片规则
- !READWRITE_SPLITTING
# ... 读写分离规则
- !ENCRYPT
# ... 加密规则四、SQL 审计与日志
4.1 审计配置
yaml
# conf/server.yaml 中配置 SQL 审计
props:
sql-show: true # 打印路由后的 SQL
sql-simple: false # 是否简化日志
max-connections-size-per-query: 1 # 单查询最大连接数
# 审计日志输出示例:
# Logic SQL: SELECT * FROM t_order WHERE user_id = 1
# Actual SQL: ds0 ::: SELECT * FROM t_order_3 WHERE user_id = 1
# Actual SQL: ds1 ::: SELECT * FROM t_order_7 WHERE user_id = 14.2 流量治理
yaml
# conf/config-readwrite-splitting.yaml 中配置熔断
rules:
- !READWRITE_SPLITTING
dataSources:
readwrite_ds:
staticStrategy:
writeDataSourceName: primary_ds
readDataSourceNames:
- replica_ds_0
disabledDataSourceNames: # 禁用读库(出问题时手动禁用)
- replica_ds_1五、JDBC vs Proxy 选型
| 维度 | JDBC 嵌入模式 | Proxy 代理模式 |
|---|---|---|
| 侵入性 | 高:需引入 Java 依赖 + 配置 | 低:应用直连无感知 |
| 性能 | 高:进程内调用 | 中:多一次网络跳转 |
| 运维 | 高:每个应用都要配置 | 低:集中管理 |
| 语言 | 仅限 Java | 任意语言(MySQL 协议) |
| SQL 支持 | 有限制(不支持某些语法) | 有限制(同 JDBC) |
| 故障影响 | 单个应用受影响 | 所有应用受影响 |
| 扩展能力 | 分布式治理弱 | 流量治理强 |
| 适用场景 | 性能敏感、Java 技术栈 | 多语言、运维优先 |
六、总结
| 知识点 | 说明 |
|---|---|
| 部署 | 独立进程,MySQL 协议兼容 |
| 数据加密 | AES/MD5 自动加密解密,存量迁移 |
| 读写分离 | 一主多从,事务内强制读主库 |
| SQL 审计 | 逻辑 SQL → 实际 SQL 映射 |
| 流量治理 | 熔断禁用从库 |
| 混合模式 | 分片 + 读写分离 + 加密 同时启用 |
| 选型 | JDBC vs Proxy 各有优劣 |
参考链接: