MySQL 读写分离,分库分表 sharding-proxy5.0.0 (二)

官方文档:https://shardingsphere.apache.org/document/


目录

一、规则配置

二、引入依赖

三、启动服务

四、使用ShardingSphere-Proxy

五、问题总结

ps:
实操前置条件:需要自行实现mysql集群的搭建,以及主从数据同步
可以参考我的前一篇文章:MySQL主从同步(一)


一、规则配置

定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前提供 MySQL 和 PostgreSQL 版本,它可以使用任何兼容 MySQL/PostgreSQL 协议的访问客户端(如:MySQL Command Client, MySQL Workbench, Navicat 等)操作数据。
避免业务端直接访问数据库层还需要对业务代码进行改造,以适配sharding规则

我的工作路径:/Users/yw/workspace/shardingdock

规则配置文件:/Users/yw/workspace/shardingdock/conf

接下来要构建的数据库层级大致如下:


  • server.yaml
authentication:
  users:
    root:
      password: root
    sharding:
      password: root
      #authorizedSchemas对应的是后续config配置中的schemaName。多个用逗号分隔。
      authorizedSchemas: ebook
  • config-sharding.yaml
schemaName: ebook  # 逻辑数据库名字

dataSourceCommon: #数据源公共配置
  username: root
  password: root    
  connectionTimeoutMilliseconds: 30000  # 连接超时毫秒数
  idleTimeoutMilliseconds: 60000        # 空闲连接回收超时毫秒数
  maxLifetimeMilliseconds: 1800000      # 连接最大存活时间毫秒数
  maxPoolSize: 50                       # 最大连接数
  minPoolSize: 1
  maintenanceIntervalMilliseconds: 30000

dataSources:  #数据源别名,多个往下边追加
  ds_0_master_0:  # ds_0_master_0, ds_0_slave_0, ds_0_slave_2 三个库实现1主2从,组成逻辑库ds_0
    url: jdbc:mysql://192.168.3.12:3310/ebook0?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai                  
  ds_0_slave_0: 
    url: jdbc:mysql://192.168.3.12:3312/ebook0?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
  ds_0_slave_1: 
    url: jdbc:mysql://192.168.3.12:3313/ebook0?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
  ds_1: # 由 ds_0,ds_1组成分库
    url: jdbc:mysql://192.168.3.12:3314/ebook1?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai                  
  
rules:
  # 配置分片规则
  - !SHARDING
    tables: # 多个表就往下边追加
      test: # 逻辑表的名字
        actualDataNodes: ds_${0..1}.test_${0..2}   # 数据源名称 `ds` 使用读写分离配置的逻辑数据源名称
        tableStrategy: #分表策略
          standard:
            shardingColumn: created_at
            shardingAlgorithmName: sharding_by_time # 使用下面分片算法中的 sharding_by_time
        keyGenerateStrategy:
          column: id  # 分布式主键
          keyGeneratorName: snowflake # SNOWFLAKE 分布式主键类型
    bindingTables:
      - test

    #默认分库策略
    defaultDatabaseStrategy:
      standard:
        shardingColumn: id
        shardingAlgorithmName: database_inline
    defaultTableStrategy:
      none:

    keyGenerators: # 分布式主键配置
      snowflake:
        type: SNOWFLAKE
        props:
          worker-id: 1

    shardingAlgorithms: # 配置分片算法
      database_inline:
        type: INLINE
        props:
          algorithm-expression: ds_${id % 2}
      sharding_by_time:
        # 分片类型 
        type: auto_interval
        props: 
          # 分片开始时间 要加""不然会被解析为非字符串类型导致拿不到值
          datetime-lower: "2021-03-13 00:00:00"
          # 分片秒数 这里是一天一张表 所以秒数为86400秒  要加""不然会被解析为非字符串类型导致拿不到值
          sharding-seconds: "86400"
          # 分片结束时间 要加""不然会被解析为非字符串类型导致拿不到值
          datetime-upper: "2021-03-15 00:00:00"
          # ps:测试的时候记得核对时间,避免创建数据时写不进分片

  #配置读写分离规则
  - !REPLICA_QUERY
    dataSources:
      ds_0:
        name: ds_0 # 读写分离的逻辑数据源名称 `ds_0` 用于在数据分片中使用
        primaryDataSourceName: ds_0_master_0 # writeDataSourceName 使用真实存在的数据源名称 `ds_0_master_0`
        replicaDataSourceNames: 
          - ds_0_slave_0 # 使用真实存在的数据源名称 `ds_0_slave_0`
          - ds_0_slave_1 # 使用真实存在的数据源名称 `ds_0_slave_1`
        loadBalancerName: roundRobin
    loadBalancers:
      roundRobin:
        type: ROUND_ROBIN


二、引入依赖

  • 下载mysql驱动,并让如ext-lib
# mysql5.7
wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/5.1.47/mysql-connector-java-5.1.47.jar

# mysql8.0
wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.23/mysql-connector-java-8.0.23.jar

三、启动服务

  • 获取sharding-proxy v5.0.0镜像
    目前latest最新的是sharding-proxy:5.0.0-alpha,5.x和4.x配置文件由一定改动,注意不要混用。
docker pull apache/sharding-proxy:latest
  • 启动容器
docker run -d -v /Users/yw/workspace/shardingdock/conf:/opt/sharding-proxy/conf -v /Users/yw/workspace/shardingdock/ext-lib:/opt/sharding-proxy/ext-lib -e PORT=3308 -p13308:3308 apache/sharding-proxy:4.1.1
  1. 主要是映射confext-lib两个路径,conf路径必须挂载
  2. 可以自定义端口 3308 和 13308。3308 表示 docker 容器端口, 13308 表示宿主机端口

四、使用ShardingSphere-Proxy

  • 使用laravel进行读取写入测试

修改.env配置数据库连接sharding-proxy,13308是映射的容器内部3308端口,ebook是server.yaml配置的逻辑数据库

DB_CONNECTION=mysql
DB_HOST=192.168.3.12
DB_PORT=13308
DB_DATABASE=ebook
DB_USERNAME=root
DB_PASSWORD=root

修改config/database.php,关闭mysql strict模式

connections.mysql.strict => false

添加Test模型,进行测试

  public function test()
    {
        $datetime = Carbon::now()->toDateTimeString();
        for ($i = 0; $i < 10; $i++) {
            Test::create(['name' => $i, 'created_at' => $datetime]);
        }
        $res = Test::get();
        dd($res->toArray());
    }

可以看到,查询结果,自动将多库多表的数据进行的聚合


查询结果
  • 确认数据库数据
    当前时间为2021-03-13,根据时间分片算法应该写入test_1
ds_0_master_0 节点 ,ebook0库,test_1表数据(读写分离主节点)
ds_0_slave_0 节点,ebook0库,test_1表数据(读写分离从节点)
ds_1 节点,ebook1,test_1表数据(分库节点)

五、问题总结

  • 多个库写入相同数据
错误示例:
  - !SHARDING
    tables: # 多个表就往下边追加
      test: # 逻辑表的名字
        actualDataNodes: ds_${0..1}.test_${0..2}   # 数据源名称 `ds` 使用读写分离配置的逻辑数据源名称
        # databaseStrategy: #分库策略 #分库策略写在这里会导致多个库插入相同的数据,而不是按策略分库插入,原因暂时不清楚
        #   standard:
        #     shardingColumn: id  
        #     shardingAlgorithmName: ds_inline
解决:使用默认分库策略
    defaultDatabaseStrategy:
      standard:
        shardingColumn: id
        shardingAlgorithmName: database_inline
  • 报错:invalid tag: !READ_WRITE_SPLITTING
原因:官方在线文档没更新,这种写法当场去世(下载的PDF看起来是最新的)
错误写法示例:
  # - !READ_WRITE_SPLITTING
  #   dataSources:
  #     ds_0:
  #       name: ds_0 # 读写分离的逻辑数据源名称 `ds_0` 用于在数据分片中使用
  #       writeDataSourceName: ds_0_master_0 # writeDataSourceName 使用真实存在的数据源名称 `ds_0_master_0`
  #       readDataSourceNames: # readDataSourceNames
  #         - ds_0_slave_0 # 使用真实存在的数据源名称 `ds_0_slave_0`
  #         - ds_0_slave_1 # 使用真实存在的数据源名称 `ds_0_slave_1`
  #       loadBalancerName: roundRobin
  #   loadBalancers:
  #     roundRobin:
  #       type: ROUND_ROBIN
解决:REPLICA_QUERY标签
  • 报错:Packets out of order. Expected 1 received 0. Packet size=103
原因:这里是查询带分区的表产生配置的问题
解决:修改 PDO::ATTR_EMULATE_PREPARES => true
文件所在目录:vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php

你可能感兴趣的:(MySQL 读写分离,分库分表 sharding-proxy5.0.0 (二))