Laravel 集成使用 ShardingSphere-Proxy 读写分离

简介        

        ShardingSphere是一套开源的分布式数据库中间件解决方案组成的生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(计划中)这3款相互独立的产品组成。 他们均提供标准化的数据分片、分布式事务和数据库治理功能,可适用于如Java同构、异构语言、容器、云原生等各种多样化的应用场景。

        ShardingSphere定位为关系型数据库中间件,旨在充分合理地在分布式的场景下利用关系型数据库的计算和存储能力,而并非实现一个全新的关系型数据库。 它与NoSQL和NewSQL是并存而非互斥的关系。NoSQL和NewSQL作为新技术探索的前沿,放眼未来,拥抱变化,是非常值得推荐的。

Sharding-Proxy

        Sharding-Proxy定位为透明化的数据库代理端,提供封装了数据库二进制协议的服务端版本,用于完成对异构语言的支持。 目前先提供MySQL版本,它可以使用任何兼容MySQL协议的访问客户端(如:MySQL Command Client, MySQL Workbench等)操作数据,对DBA更加友好。

  • 向应用程序完全透明,可直接当做MySQL使用。
  • 适用于任何兼容MySQL协议的客户端。

  • 上方绿色部分是业务代码,他们统一链接Sharding-Proxy中间件,就像链接数据库一样,而具体的数据执行哪一个库,则是由Sharding-Proxy分片规则决定;
  • 中间蓝色区位就是Sharding-Proxy中间件;
  • 右侧为数据库管理工具,MySQL Cli是MySQL命令行,MySQL Workbench是管理工具,当然也支持Navicat;
  • 最下方橙色则是数据库,可以根据具体业务需求配置数据库分片、还可以配置数据库读写分离等;
  • 左侧注册中心可以统一配置分片规则、读写数据源等,而且是实时生效的;

下载

ShardingSphere-Proxy 各版本下载入口

ShardingSphere-Proxyhttps://archive.apache.org/dist/shardingsphere/https://archive.apache.org/dist/shardingsphere/

MySQL-Connector-Java MySQL各版本依赖下载入口

MySQL-Connector-Javahttps://repo1.maven.org/maven2/mysql/mysql-connector-java/https://repo1.maven.org/maven2/mysql/mysql-connector-java/

ZooKeeper 各版本下载入口

ZooKeeperhttps://zookeeper.apache.org/releases.html#downloadhttps://zookeeper.apache.org/releases.html#download


配置

        ShardingSphere-Proxy 配置

        建议下载安全稳定版本,就是不带alpha(内测)、beta(公测)关键词的包,这些多少会有一些意想不到的惊喜碧油鸡(BUG),相信我这个过来人~

         ShardingSphere-Proxy 包可以直接下载 .tar.gz 格式的,这个格式既可以Windows使用,也可以再Linux下使用,根目录下bin文件夹下,既有.bat启动文件也有.sh启动文件,不得不说开源项目有时候确实很人性化。

        ShardingSphere-Prxoy 解压配置,注意即便是Windows下也可以使用 tar -zxvf 命令解压,用命令解压好处就是保证不丢失文件,强烈推荐用命令解压,这里遇到过坑 

  • 全局配置 server.yaml。直接参考如下去掉对应配置前面的 # 号即可。
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

######################################################################################################
# 
# If you want to configure orchestration, authorization and proxy properties, please refer to this file.
# 
######################################################################################################
#
orchestration:
  orchestration_ds:
    orchestrationType: registry_center,config_center,distributed_lock_manager
    instanceType: zookeeper
    serverLists: localhost:2181
    namespace: orchestration
    props:
      overwrite: false
      retryIntervalMilliseconds: 500
      timeToLiveSeconds: 60
      maxRetries: 3
      operationTimeoutMilliseconds: 500
#
authentication:
  users:
    root:
      password: root
    sharding:
      password: sharding 
      authorizedSchemas: sharding_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: false
  allow.range.query.with.inline.sharding: false
  • 数据源+分片配置 config-sharding.yaml。直接参考如下去掉对应配置前面的 # 号即可。
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

######################################################################################################
# 
# Here you can configure the rules for the proxy.
# This example is configuration of sharding rule.
# 
######################################################################################################
#
#schemaName: sharding_db
#
#dataSources:
#  ds_0:
#    url: jdbc:postgresql://127.0.0.1:5432/demo_ds_0
#    username: postgres
#    password: postgres
#    connectionTimeoutMilliseconds: 30000
#    idleTimeoutMilliseconds: 60000
#    maxLifetimeMilliseconds: 1800000
#    maxPoolSize: 50
#    minPoolSize: 1
#  ds_1:
#    url: jdbc:postgresql://127.0.0.1:5432/demo_ds_1
#    username: postgres
#    password: postgres
#    connectionTimeoutMilliseconds: 30000
#    idleTimeoutMilliseconds: 60000
#    maxLifetimeMilliseconds: 1800000
#    maxPoolSize: 50
#    minPoolSize: 1
#
#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

######################################################################################################
#
# If you want to connect to MySQL, you should manually copy MySQL driver to lib directory.
#
######################################################################################################

schemaName: sharding_db
#
dataSources:
  ds_0:
    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false
    username: root
    password: 你的MySQL密码
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_1:
    url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false
    username: root
    password: 你的MySQL密码
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
#
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
  • 数据源+读写分离配置 config-master_slave.yaml。直接参考如下去掉对应配置前面的 # 号即可。
#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

######################################################################################################
#
# Here you can configure the rules for the proxy.
# This example is configuration of master-slave rule.
#
# If you want to use master-slave, please refer to this file;
# if you want to use sharding, please refer to the config-sharding.yaml.
#
######################################################################################################
#
#schemaName: master_slave_db
#
#dataSources:
#  master_ds:
#    url: jdbc:postgresql://127.0.0.1:5432/demo_ds_master?serverTimezone=UTC&useSSL=false
#    username: postgres
#    password: postgres
#    connectionTimeoutMilliseconds: 30000
#    idleTimeoutMilliseconds: 60000
#    maxLifetimeMilliseconds: 1800000
#    maxPoolSize: 50
#  slave_ds_0:
#    url: jdbc:postgresql://127.0.0.1:5432/demo_ds_slave_0?serverTimezone=UTC&useSSL=false
#    username: postgres
#    password: postgres
#    connectionTimeoutMilliseconds: 30000
#    idleTimeoutMilliseconds: 60000
#    maxLifetimeMilliseconds: 1800000
#    maxPoolSize: 50
#  slave_ds_1:
#    url: jdbc:postgresql://127.0.0.1:5432/demo_ds_slave_1?serverTimezone=UTC&useSSL=false
#    username: postgres
#    password: postgres
#    connectionTimeoutMilliseconds: 30000
#    idleTimeoutMilliseconds: 60000
#    maxLifetimeMilliseconds: 1800000
#    maxPoolSize: 50
#
#masterSlaveRule:
#  name: ms_ds
#  masterDataSourceName: master_ds
#  slaveDataSourceNames:
#    - slave_ds_0
#    - slave_ds_1

######################################################################################################
#
# If you want to connect to MySQL, you should manually copy MySQL driver to lib directory.
#
######################################################################################################

schemaName: master_slave_db
#
dataSources:
  master_ds:
    url: jdbc:mysql://127.0.0.1:3306/demo_ds_master?serverTimezone=UTC&useSSL=false
    username: root
    password: 你的MySQL密码
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 500
  slave_ds_0:
    url: jdbc:mysql://127.0.0.1:3306/demo_ds_slave_0?serverTimezone=UTC&useSSL=false
    username: root
    password: 你的MySQL密码
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 500
  slave_ds_1:
    url: jdbc:mysql://127.0.0.1:3306/demo_ds_slave_1?serverTimezone=UTC&useSSL=false
    username: root
    password: 你的MySQL密码
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 500
#
masterSlaveRule:
  name: ms_ds
  masterDataSourceName: master_ds
  slaveDataSourceNames:
    - slave_ds_0
    - slave_ds_1

        ZooKeeper 配置

        一样去官方网站下载最新稳定版本,使用命令解压

        解压后,直接进入解压后的 根目录/conf 目录下,zoo_sample.cfg 复制一份重命名为 zoo.cfg 这样可以保持一份源配置文件,后面修改错了还能还原最初默认配置(这里是个人习惯哈)

        zoof.cfg 配置文件如下 

# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial 
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between 
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just 
# example sakes.
dataDir=D:\\PHP\\zookeeper\\data
# the port at which the clients will connect
clientPort=2181
admin.serverPort=8888
# the maximum number of client connections.
# increase this if you need to handle more clients
#maxClientCnxns=60
#
# Be sure to read the maintenance section of the 
# administrator guide before turning on autopurge.
#
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance
#
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1

## Metrics Providers
#
# https://prometheus.io Metrics Exporter
#metricsProvider.className=org.apache.zookeeper.metrics.prometheus.PrometheusMetricsProvider
#metricsProvider.httpPort=7000
#metricsProvider.exportJvmInfo=true

audit.enable=true
  • tickTime: 使用的基本时间单元,以毫秒为单位默认值是2000。用来调节心跳和超时。
  • initLimit: 默认值是10,是tickTime属性值的10倍。它用于配置允许 followers 连接并同步到 leader 的最大时间。如果管理的数据量很大的话可以增加这个值。
  • syncLimit: 默认值是5,是 tickTime 属性值的5倍。它用于配置 leader 和 followers 间进行心跳检测的最大延迟时间。如果在设置的时间内 followers 无法与leader进行通信, 那么 followers 将会被丢弃。
  • dataDir: 用来存储内存数据库快照的目录。建议配置 dataLogDir 参数来指定事务日志的存储目录,方便查找也方便清除。
  • clientPort: 服务器监听客户端连接的端口,默认值是2181。
  • maxClientCnxns: 在 socket 级别限制单个客户端与单台服务器之前的并发连接数量, 可以通过 IP 地址来区分不同的客户端。它用来防止某种类型的 DoS 攻击, 包括文件描述符耗尽。默认值是60。将其设置为0将完全移除并发连接数的限制。
  • autopurge.snapRetainCount: 自动清理的时候需要保留的数据文件快照的数量和对应的事务日志文件, 默认值是 3。
  • autopurge.purgeInterval: 和参数 autopurge.snapRetainCount 配套使用, 用于配置自动清理文件的频率,默认值是1,开启自动清理功能, 为0则表示禁用自动清理功能。
  • audit.enable: 审核日志开关,设置false在启动时候:ZooKeeper audit is disabled,设置true在启动的时候:ZooKeeper audit is enabled

        MySQL jar依赖

        将对应自己系统安装的 MySQL 版本的jar下载的依赖,mysql-connector-java-x.x.x.jar 复制到对应解压配置的 SharidingSphaere-Proxy 根目录/lib文件夹下,不然会报错


启动

        ZooKeeper启动

        我们使用了 Zookeeper 注册中心,所以先启动 Zookeeper,直接进入解压后的 Zookeeper 根目录/bin,执行 zkServer.cmd(再次提醒Windows下启动.cmd,Linux下启动.sh)

启动后就会在启动命令跑脚本的时候最下方看到 ZooKeeper audit is enabled

 有些时候因启动结束多次过,并且在 data 下已经生成了 version-2 文件,会有时候无 ZooKeeper audit is enabled。没有也是正常的,放心继续操作就好。参考如下生成这个

         ShardingSphere-Proxy 启动

        启动咱们的中间件大管家 ShardingSphere-Proxy,进入上述中解压后的 ShardingShpere-Proxy 根目录/bin下,直接执行 start.bat(再次提醒Windows下启动.bat,Linux下启动.sh)

        正常启动之后,就可以进入 ShardingSphere-Proxy 中间件数据库了,直接命令行进入,这里要注意  ShardingSphere-Proxy 中间件默认端口是 3307,所以命令行进入数据库需要设置端口为 3307 才可以,如下

        通过命令行进入数据库之后,发现和本地直接安装的 MySQL3306端口进入的服务版本有所差别,这就是 ShardingSphere-Proxy 中间件数据库连接,是正常对的哦。可能有些人不想用 3307 端口,也是可以实现的,在启动  start.bat 3308 或  start.bat 3309 等,在启动脚本后面加上自己想用的端口号就可以了。

        使用数据库管理工具连接,如 Navicat  但是使用高版本的时候遇到了问题,就是在使用测试连接时提示成功的,实际连接就时无法连接,如下

         出现这个提示的时候,不是你的 ShardingSphere-Proxy 有问题,而是 Navicat 版本不兼容问题,可以试试 Navicat 11 ,就可以正常连接了。如下


测试

        上面已经安装、配置、启动完成,我们开始开始尝试使用,进入 ShardingSphere-Proxy 中间件数据库,你就会发现配置文件里面的

config-master_slave.yaml 配置文件中的
schemaName: master_slave_db

config-sharding.yaml 配置文件中的
schemaName: sharding_db

        数据库已经创建完成了,如下

 分库分表测试

        首先需要根据 config-sharding.yaml 配置文件中的

url: jdbc:mysql://127.0.0.1:3306/local_db_01?serverTimezone=UTC&useSSL=false
在3306端口下创建名为 local_db_01 数据库

url: jdbc:mysql://127.0.0.1:3306/local_db_02?serverTimezone=UTC&useSSL=false
在3306端口下创建名为 local_db_02 数据库

说明:local_db_01 和 local_db_02 是做分库分表的数据库,所以在配置文件 config-sharding.yaml 配置了什么名字就创建对应数据库名字就好

#分库
CREATE SCHEMA `local_db_01` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

#分库
CREATE SCHEMA `local_db_02` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

        创建好之后,在回到 ShardingShpere-Proxy 中间件数据库,直接在 sharding_db 数据库中创建名为 t_order 的数据表。如下

DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT '主键ID',
  `number` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL UNIQUE COMMENT '订单号',
  `user_id` bigint unsigned DEFAULT NULL COMMENT '用户ID',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
  `status` tinyint unsigned DEFAULT NULL COMMENT '状态:1未付款,2已付款,3已发货,4确认中',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

        执行之后,不仅在 sharding_db 中有 t_order 表,在你的 3306 端口下创建的 local_db_01 和 local_db_02 也有对应 t_order_0 和 t_order_1 两张表。如下

         测试一条数据试试看,直接在 sharding_db 中执行一条 insert sql ,参考如下

INSERT INTO `t_order` (`id`, `number`, `user_id`, `remark`, `status`) VALUES (1, '202111221002284415297e3af8c', 3125,'system_api_ios_store_hot_pid13', 2);

        执行后它除了在 sharding_db 中生成数据之外,还会自动在你的 local_db_01 或 local_db_02 中的 t_order_0 或 t_order_1 中也插入一条数据,这就实现了分库分表

读写分离测试

        首先需要根据 config-master_slave.yaml 配置文件中的

url: jdbc:mysql://127.0.0.1:3306/demo_ds_master?serverTimezone=UTC&useSSL=false
在3306端口下创建名为 demo_ds_master 数据库(主)

url: jdbc:mysql://127.0.0.1:3306/demo_ds_slave_0?serverTimezone=UTC&useSSL=false
在3306端口下创建名为 demo_ds_slave_0 数据库(从)

url: jdbc:mysql://127.0.0.1:3306/demo_ds_slave_1?serverTimezone=UTC&useSSL=false
在3306端口下创建名为 demo_ds_slave_1 数据库(从)

说明:demo_ds_master 主数据库,demo_ds_slave_0 和 demo_ds_slave_1 为从数据库,所以在配置文件 config-master_slave.yaml 配置了什么名字就创建对应数据库名字就好

#主库
CREATE SCHEMA `demo_ds_master` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

#从库
CREATE SCHEMA `demo_ds_slave_0` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

#从库
CREATE SCHEMA `demo_ds_slave_1` DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

         创建好之后,再回到 ShardingSphere-Proxy 根目录/conf 下 server.yaml 配置文件中

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

        将 authorizedSchemas: 改成  config-master_slave.yaml 配置文件中对应的 schemaName: master_slave_db 名称即可。然后重启 ZooKeeper 和 ShardingSphere-Proxy 脚本。

        再次进入到 ShardingSphere-Proxy 中间件数据库,创建 t_order 表具体可以参考上述的分库分表测试中的sql建表示例。

DROP TABLE IF EXISTS `t_order`;
CREATE TABLE `t_order` (
  `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT COMMENT '主键ID',
  `number` varchar(128) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL UNIQUE COMMENT '订单号',
  `user_id` bigint unsigned DEFAULT NULL COMMENT '用户ID',
  `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '备注',
  `status` tinyint unsigned DEFAULT NULL COMMENT '状态:1未付款,2已付款,3已发货,4确认中',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

        直接查看 ShardingSphere-Proxy 中间件下的 master_slave_db 数据库有 t_order 表 

mysql> show databases;
+-----------------+
| Database        |
+-----------------+
| master_slave_db |
| sharding_db     |
+-----------------+
2 rows in set (0.01 sec)

mysql> use master_slave_db;
Database changed
mysql> show tables;
+--------------------------+
| Tables_in_demo_ds_master |
+--------------------------+
| t_order                  |                 |
+--------------------------+
30 rows in set (0.01 sec)

mysql>

        然后在 3306 端口数据库下检查,发现对应的 t_order 也被创建成功了。

Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

PS C:\Users\user> mysql -uroot -p
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 274
Server version: 8.0.27 MySQL Community Server - GPL

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> use demo_ds_master;
Database changed
mysql> show tables;
+--------------------------+
| Tables_in_demo_ds_master |
+--------------------------+
| t_order                  |
+--------------------------+
29 rows in set (0.01 sec)

mysql>

        为了快速测试,我们还是直接执行 INSERT 方便快速测试

#从库
INSERT INTO `demo_ds_slave_0`.`t_order`(`id`, `number`, `user_id`, `remark`, `status`) VALUES (3, '202111221002284415297o5e3lm', 3173,'system_api_ios_store_hot_pid53', 4);

#从库
INSERT INTO `demo_ds_slave_1`.`t_order`(`id`, `number`, `user_id`, `remark`, `status`) VALUES (5, '202111221002284415297s2wt8l', 5503,'system_api_ios_store_hot_pid21', 1);

        查询测试,可以看到在不指定数据库查询,会在 demo_ds_slave_0 和 demo_ds_slave_1 之间交替查询且没有查询主库,实现读写分离。

mysql> select * from t_order;
+----+-----------------------------+---------+--------------------------------+--------+
| id | number                      | user_id | remark                         | status |
+----+-----------------------------+---------+--------------------------------+--------+
|  2 | 202111221002284415297s2wt8l |    5503 | system_api_ios_store_hot_pid21 |      1 |
+----+-----------------------------+---------+--------------------------------+--------+
1 rows in set (0.03 sec)

mysql> select * from t_order;
+----+-----------------------------+---------+--------------------------------+--------+
| id | number                      | user_id | remark                         | status |
+----+-----------------------------+---------+--------------------------------+--------+
|  1 | 202111221002284415297o5e3lm |    3173 | system_api_ios_store_hot_pid53 |      4 |
+----+-----------------------------+---------+--------------------------------+--------+
1 rows in set (0.01 sec)
mysql> 

PHP集成

        直接调整对应的数据库连接类或者数据库配置文件即可,以下 sample 作参考

<?php

/**
 * @desc mysqli单例模式连接sharding-proxy中间件
 * @author coachmans
 * @datatime 2021-11-19
 */

class MySQLDB
{
    static $instance;
    static $connect;
    protected $result;

    /**
     * protected关键字阻止此类在外部进行实例化
     */
    protected function __construct($host, $user, $password, $name, $port)
    {
        self::$connect = @new \mysqli($host, $user, $password, $name, $port);
        if (self::$connect->connect_errno) {
            die(iconv('gbk', 'utf8mb4', self::$connect->connect_error) . '(' . self::$connect->connect_errno . ')');
        }
    }

    /**
     * protected关键字阻止此类在外部进行克隆
     */
    protected function __clone(){}

    /**
     * 当对象被销毁时关闭连接
     */
    function __destruct()
    {
        self::$connect->close();
    }

    /**
     * 获取实例
     */
    public static function getInstance($host, $user, $password, $name, $port){
        self::$instance = self::$instance ?: new self($host, $user, $password, $name, $port);
        return self::$instance;
    }
}


/**
 * @desc PDO单例模式连接sharding-proxy中间件
 * @author coachmans
 * @datatime 2021-11-19
 */

class PDODB
{
    protected static $_instance = null;
    protected $dbName = '';
    protected $dsn;
    protected $dbh;

    /**
     * protected关键字阻止此类在外部进行实例化
     */
    protected function __construct($dbHost, $dbPort, $dbUser, $dbPasswd, $dbName, $dbCharset)
    {
        try {
            $this->dsn = 'mysql:host=' . $dbHost . ';port=' . $dbPort . ';dbname=' . $dbName;
            $this->dbh = new PDO($this->dsn, $dbUser, $dbPasswd);
            $this->dbh->exec('SET character_set_connection=' . $dbCharset . ', character_set_results=' . $dbCharset . ', character_set_client=binary');
        } catch (PDOException $e) {
            $this->outputError($e->getMessage());
        }
    }

    /**
     * 防止克隆
     */
    protected function __clone(){}

    /**
     * Singleton instance
     */
    public static function getInstance($dbConfig)
    {
        if (self::$_instance === null) {
            self::$_instance = new self($dbConfig['host'], $dbConfig['port'], $dbConfig['username'], $dbConfig['password'], $dbConfig['database'], $dbConfig['charset']);
        }
        return self::$_instance;
    }
}

        直接在对应业务的位置引用调用就好了。或者修改自己的项目的数据库配置,改成部署启动的 ShardingSphere-Proxy 中间件连接即可。


Laravel框架集成

        修改对应的 env 配置文件,把数据库连接修改成 ShardingSphere-Proxy 中间件连接。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3307
DB_DATABASE=master_slave_db
DB_USERNAME=root
DB_PASSWORD=root #默认密码是root

        修改 config/database.php 需要支持预处理,不然会出现连接超时或者内存溢出等问题

	'options'  => [
		...,
	    PDO::ATTR_EMULATE_PREPARES => true,// 模拟预处理语句
	]

#清除缓存重新访问
php artisan cache:clear

        欢迎小伙伴留言讨论


踩坑

  • 如在启动 ShardingSphere-Proxy 的时候出现 XX 类缺失,请务必使用命令重新解压
  • 启动 ZooKeeper 遇到 ZooKeeper audit is disabled 时,在 zoo.cfg 添加 audit.enable=true 保存并重启
  • 使用 Navicat 连接 ShardingSphere-Proxy 出现 1046 - No database selected,请使用低版本 Navicat 例如 11
  • 遇到端口被占用时,请直接修改 zoo.cfg 配置中的 admin.serverPort=8888
  • 遇到 KeeperErrorCode = OperationTimeout 请启动 ZooKeeper 后在启动 ShardingSphere-Proxy
  • 其他异常请尝试删除 ZooKeeper 配置的启动生成的 version-2 文件

        欢迎小伙伴留言讨论

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值