shardingsphere-proxy分库分表配置

Posted 境悟初

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了shardingsphere-proxy分库分表配置相关的知识,希望对你有一定的参考价值。

shardingsphere-proxy

shardingsphere-proxy是一个代理,兼容mysql和postgresql协议,可以接入多种语言。

1.下载

  1. 下载ss-proxy安装包:https://shardingsphere.apache.org/document/current/en/downloads/
  2. 下载mysql-jdbc-driver-lib:https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.47/mysql-connector-java-5.1.47.jar

2.安装zookeeper&mysql

proxy目前依赖ZK做调度,不过很快会有多种分布式框架可选,比如etcd,甚至自研。

3.配置proxy

使用mysql的话需要将mysql driver包放在lib下,postgresql不需要。

配置文件位于conf目录。

server.yaml

这个是必选。

governance:
  name: governance_ds # ZK上的节点名称
  registryCenter:
    type: ZooKeeper
    serverLists: localhost:2181
    props:
      retryIntervalMilliseconds: 500
      timeToLiveSeconds: 60
      maxRetries: 3
      operationTimeoutMilliseconds: 500
  overwrite: true # 如果设为false,每次重启后ZK上的配置还是之前的,不利于调试,生产环境设为false

scaling:
  blockQueueSize: 10000
  workerThread: 40

rules:
  - !AUTHORITY
    users:
      - root@%:passw23ey8dg
      # - sharding@:sharding # 密码太简单mysql会报错
    provider:
      type: NATIVE

props:
  sql-show: true

若是governance.overwrite设为false,当配置文件出了问题,得先删除ZK上的节点,否则会一直使用之前的配置

[zk: localhost:2181(CONNECTED) 11] deleteall /governance_ds

config-sharding.yaml

当然,这个名字以config-开头,后面可以随便取。

ShardingSphere-Proxy 支持多逻辑数据源,每个以 config- 前缀命名的 YAML 配置文件,即为一个逻辑数据源

schemaName: order_db # 逻辑库名

dataSources:
  ds_0:
    url: jdbc:mysql://127.0.0.1:3306/order_db_0?serverTimezone=UTC&useSSL=false
    username: root
    password: passw23ey8dg!e
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    maintenanceIntervalMilliseconds: 30000
  ds_1:
    url: jdbc:mysql://127.0.0.1:3306/order_db_1?serverTimezone=UTC&useSSL=false
    username: root
    password: passw23ey8dg!e
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
    maintenanceIntervalMilliseconds: 30000

rules:
- !SHARDING
  tables:
    t_order:
      actualDataNodes: ds_${0..1}.t_order_${0..1}
      tableStrategy:
        standard:
          shardingColumn: order_id
          shardingAlgorithmName: t_order_inline
      keyGenerateStrategy:
        column: order_id
        keyGeneratorName: snowflake
    t_order_item:
      actualDataNodes: ds_${0..1}.t_order_item_${0..1}
      tableStrategy:
        standard:
          shardingColumn: order_id
          shardingAlgorithmName: t_order_item_inline
      keyGenerateStrategy:
        column: order_item_id
        keyGeneratorName: snowflake
  bindingTables:
    - t_order,t_order_item
  defaultDatabaseStrategy:
    standard:
      shardingColumn: user_id
      shardingAlgorithmName: database_inline
  defaultTableStrategy:
    none:

  shardingAlgorithms:
    database_inline:
      type: INLINE
      props:
        algorithm-expression: ds_${user_id % 2}
    t_order_inline:
      type: INLINE
      props:
        algorithm-expression: t_order_${order_id % 2}
    t_order_item_inline:
      type: INLINE
      props:
        algorithm-expression: t_order_item_${order_id % 2}

  keyGenerators:
    snowflake:
      type: SNOWFLAKE
      props:
        worker-id: 123

需要手动在mysql中创建这几个数据库:

CREATE SCHEMA IF NOT EXISTS order_db_0;
CREATE SCHEMA IF NOT EXISTS order_db_1;

4.启动ss-proxy

bin/start.sh

他的默认端口是3307,如果要修改端口,可以在启动时指定 bin/start.sh 3308

可以看到ZK和proxy的进程

# jps -l
5745 org.apache.zookeeper.ZooKeeperMain
14068 org.apache.shardingsphere.proxy.Bootstrap
7102 org.apache.zookeeper.server.quorum.QuorumPeerMain

这时候,是可以通过mysql客户端直接连接的:

mysql -p -P 3307

5.测试分片

数据源和规则建好后,就是建表测试。

建表语句:

CREATE TABLE IF NOT EXISTS t_user (user_id INT NOT NULL AUTO_INCREMENT, user_name VARCHAR(200), user_name_plain VARCHAR(200), pwd VARCHAR(200), assisted_query_pwd VARCHAR(200), PRIMARY KEY (user_id));
CREATE TABLE IF NOT EXISTS t_order_item (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id));
CREATE TABLE IF NOT EXISTS t_order (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id));

写一段简单的JDBC代码:连接的库为逻辑库,注意端口为 3307,这是ss-proxy的默认端口,

try (Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3307/order_db", "root", "passw23ey8dg")) {

    final Statement st1 = conn.createStatement();
    String sql = "CREATE TABLE IF NOT EXISTS t_user (user_id INT NOT NULL AUTO_INCREMENT, user_name VARCHAR(200), user_name_plain VARCHAR(200), pwd VARCHAR(200), assisted_query_pwd VARCHAR(200), PRIMARY KEY (user_id));";
    st1.executeUpdate(sql);
    sql = "CREATE TABLE IF NOT EXISTS t_order_item (order_item_id BIGINT NOT NULL AUTO_INCREMENT, order_id BIGINT NOT NULL, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_item_id));";
    st1.executeUpdate(sql);
    sql = "CREATE TABLE IF NOT EXISTS t_order (order_id BIGINT NOT NULL AUTO_INCREMENT, user_id INT NOT NULL, status VARCHAR(50), PRIMARY KEY (order_id))";
    st1.executeUpdate(sql);

    st1.executeUpdate("insert into t_user(user_id,user_name) values(1,'jimo'),(2,'hehe')");
    st1.executeUpdate("insert into t_order values(1,1,'ok'),(2,1,'err'),(3,2,'ok')");

    final Statement st2 = conn.createStatement();
    final ResultSet rs = st2.executeQuery("select count(1) from t_order");
    rs.next();
    System.out.println(rs.getInt(1));
} catch (SQLException e) {
    e.printStackTrace();
}

6.验证数据

mysql> use order_db_0;

Database changed
mysql> show tables;
+----------------------+
| Tables_in_order_db_0 |
+----------------------+
| t_order_0            |
| t_order_1            |
| t_order_item_0       |
| t_order_item_1       |
| t_user               |
+----------------------+
5 rows in set (0.00 sec)

mysql> use order_db_1;

Database changed
mysql> show tables;
+----------------------+
| Tables_in_order_db_1 |
+----------------------+
| t_order_0            |
| t_order_1            |
| t_order_item_0       |
| t_order_item_1       |
+----------------------+
4 rows in set (0.00 sec)


mysql> select * from order_db_0.t_order_0;
Empty set (0.00 sec)

mysql> select * from order_db_0.t_order_1;
+----------+---------+--------+
| order_id | user_id | status |
+----------+---------+--------+
|        3 |       2 | ok     |
+----------+---------+--------+
1 row in set (0.00 sec)

mysql> select * from order_db_1.t_order_0;
+----------+---------+--------+
| order_id | user_id | status |
+----------+---------+--------+
|        2 |       1 | err    |
+----------+---------+--------+
1 row in set (0.00 sec)

mysql> select * from order_db_1.t_order_1;
+----------+---------+--------+
| order_id | user_id | status |
+----------+---------+--------+
|        1 |       1 | ok     |
+----------+---------+--------+
1 row in set (0.00 sec)

关于集群模式

每个proxy的实例是独立无状态的,通过JDBC URL上配置多个实例来做到分布式。

以上是关于shardingsphere-proxy分库分表配置的主要内容,如果未能解决你的问题,请参考以下文章

ShardingSphere-Proxy分库分表以及多租户安装使用

ShardingSphere-Proxy分库分表以及多租户安装使用

分库分表怎么配?

也许可能是史上最详尽的分库分表文章之一

为什么大公司的后台数据库都要搞分库分表?

高并发系列:存储优化之也许可能是史上最详尽的分库分表文章之一