美文网首页
MySQL 读写分离,分库分表 sharding-proxy5.

MySQL 读写分离,分库分表 sharding-proxy5.

作者: 噫那里有条咸鱼 | 来源:发表于2021-03-13 19:30 被阅读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.

          本文链接:https://www.haomeiwen.com/subject/sibxcltx.html