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
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容