1. 程式人生 > 實用技巧 >ShardingSphere入門實戰(2)-Sharding-Proxy使用

ShardingSphere入門實戰(2)-Sharding-Proxy使用

Sharding-Proxy定位為透明化的資料庫代理端,提供封裝了資料庫二進位制協議的服務端版本,用於完成對異構語言的支援。 目前先提供MySQL/PostgreSQL版本,它可以使用任何相容MySQL/PostgreSQL協議的訪問客戶端。本文主要介紹Sharding-Proxy的基本使用,文中使用到的軟體版本:sharding-proxy 4.1.1、MySQL 5.7.26、Java 1.8.0_191。

1、Sharding-Proxy和Sharding-JDBC的區別

2、Sharding-Proxy安裝

2.1、下載並解壓

https://shardingsphere.apache.org/document/current/cn/downloads/

tar zxvfapache-shardingsphere-4.1.1-sharding-proxy-bin.tar.gz

2.2、修改配置檔案

conf/server.yaml

authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding 
      authorizedSchemas: sharding_db,master_slave_db

props:
  max.connections.size.per.query: 1
  acceptor.size: 16  # The default value is available processors count * 2.
  executor.size: 16  # Infinite by default.
  proxy.frontend.flush.threshold: 128  # The default value is 128.
    # LOCAL: Proxy will run with LOCAL transaction.
    # XA: Proxy will run with XA transaction.
    # BASE: Proxy will run with B.A.S.E transaction.
  proxy.transaction.type: LOCAL
  proxy.opentracing.enabled: false
  proxy.hint.enabled: false
  query.with.cipher.column: true
  sql.show: true
  allow.range.query.with.inline.sharding: false

conf/config-sharding.yaml

schemaName: sharding_db

dataSources:
  ds0:
    url: jdbc:mysql://10.49.196.10:3306/itest
    username: admin
    password: Root_123!
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
  ds1:
    url: jdbc:mysql://10.49.196.20:3306/itest
    username: admin
    password: Root_123!
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50

shardingRule:
  tables:
    t_user: #邏輯表名,在一個庫裡分表:ds0.t_user_0,ds0.t_user_1
      actualDataNodes: ds0.t_user_$->{0..1}
      tableStrategy: #表分片策略
        inline: #行表示式分片策略
          shardingColumn: user_id #分片的欄位
          algorithmExpression: t_user_$->{user_id % 2} #分片的演算法
    t_dept: #分庫,兩個庫裡建系統的表:ds0.t_dept,ds1.t_dept
      actualDataNodes: ds$->{0..1}.t_dept
      databaseStrategy: #資料庫分片策略
        inline: #行表示式分片策略
          shardingColumn: dept_id #分片的欄位
          algorithmExpression: ds$->{dept_id % 2} #分片的演算法

conf/config-master_slave.yaml

schemaName: master_slave_db

dataSources:
  master:
    url: jdbc:mysql://10.49.196.10:3306/itest
    username: admin
    password: Root_123!
  slave0:
    url: jdbc:mysql://10.49.196.20:3306/itest
    username: admin
    password: Root_123!

masterSlaveRule:
  name: ds_ms
  masterDataSourceName: master
  slaveDataSourceNames: 
    - slave0

3、使用JDBC訪問Sharding-Proxy

package com.inspur.demo.shardingsphere;

import com.inspur.demo.shardingsphere.util.JdbcUtil;
import org.apache.shardingsphere.api.hint.HintManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class ShardingProxyCase {
    private static Logger logger = LoggerFactory.getLogger(ShardingProxyCase.class);


    /**
     * 資料分片
     * t_user在同一個庫裡分表(t_user_0,t_user_1)
     * t_dept分庫
     */
    @Test
    public void fragmentation() {
        Connection con = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://10.49.196.10:3307/sharding_db", "sharding", "sharding");
            con.setAutoCommit(false);
            Statement st = con.createStatement();

            //插入ds0.t_user_0表
            st.executeUpdate("insert into t_user(user_id,user_name,age) values(110,'趙雲2', 30)");
            //插入ds0.t_user_1表
            st.executeUpdate("insert into t_user(user_id,user_name,age) values(111,'張飛2', 31)");

            //插入ds0.t_dept表
            st.executeUpdate("insert into t_dept(dept_id,dept_name) values(110,'dept10-2')");
            //插入ds1.t_dept表
            st.executeUpdate("insert into t_dept(dept_id,dept_name) values(111,'dept11-2')");

            ResultSet rs = st.executeQuery("select user_id,user_name from t_user where user_id in(110,111)");
            while (rs.next()) {
                logger.info("user_id={},user_name={}", rs.getString("user_id"), rs.getString("user_name"));
            }

            rs = st.executeQuery("select dept_id,dept_name from t_dept where dept_id in(110,111)");
            while (rs.next()) {
                logger.info("dept_id={},dept_name={}", rs.getString("dept_id"), rs.getString("dept_name"));
            }

            con.commit();
        } catch (Exception e) {
            JdbcUtil.rollback(con);
            e.printStackTrace();
        } finally {
            JdbcUtil.close(con);
        }
    }


    /**
     * 讀寫分離,主庫寫,從庫讀
     * 同一執行緒且同一資料庫連線內,如有寫入操作,以後的讀操作均從主庫讀取,用於保證資料一致性
     */
    @Test
    public void readWrite() {
        Connection con = null;
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            con = DriverManager.getConnection("jdbc:mysql://10.49.196.10:3307/master_slave_db", "sharding", "sharding");
            Statement st = con.createStatement();

            //從slave0讀資料
            ResultSet rs = st.executeQuery("select * from t_student");
            while (rs.next()) {
                System.out.println(rs.getString("id") + "|" + rs.getString("name"));
            }

            //寫入master
            st.executeUpdate("insert into t_student(id,name) values(600,'測試')");

            //這邊應該從master讀資料,但是還是從slave0讀取資料,可能是ShardingProxy的bug
            rs = st.executeQuery("select * from t_student");
            while (rs.next()) {
                System.out.println(rs.getString(1) + "|" + rs.getString(2));
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.close(con);
        }
    }

}

資料分配和讀寫分離訪問了不同schema;在讀寫分離的例子中第二次查詢應從master讀資料,但是還是從slave0讀取資料,不知是我配置錯了還是ShardingProxy的bug,知道的同學告訴下哈。