MySQL 分布式数据库实现:无需修改代码,轻松实现分布式能力

这个项目做什么

ShardingSphere-Proxy,可以让用户像使用原生数据库一样使用 Apache ShardingSphere。

了解一项技术的开始,一般从官网开始。先来看一看官网对 ShardingSphere-Proxy 的定义是什么样的:

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

先明确一个概念,ShardingSphere-Proxy 是一个服务进程。从客户端程序连接来说,它和 MySQL 数据库并没有什么区别。

为什么要用 Proxy

在做了分库分表或其他规则的情况下,数据会分散到多个数据库实例上,在管理上难免会有一些不便;或者使用非 Java 语言的开发者,需要 ShardingSphere 所提供的能力…… 以上这些情况,正是 ShardingSphere-Proxy 力所能及之处。

1. Proxy 应用场景

日常工作中,大家使用 ShardingSphere-JDBC 进行分库分表的场景是比较多的。假设你有一张用户表,通过用户 ID 以 Hash 的方式进行了水平分库,那么此时客户端连接数据库的方式是这样:

我们举例工作中真实存在的几个场景:

  1. 测试同学想看下用户 ID 123456 的信息在数据库表里情况,需要你提供下用户在哪一张分表;
  2. 公司领导需要技术提供一份 2022 年用户的增长总量以及用户信息;
  3. 公司举行 8 周年活动,需要技术提供一份注册日期超过 8 周年的活跃老用户名单。

因为数据分库分表后,数据是散落在不同的库表中,对于上述的场景实现并不容易;如果为了实现类似临时需求,每次都需要开发代码,显得有些笨重。这个时候就需要文章主角 ShardingSphere-Proxy 登场了。

ShardingSphere-Proxy 隐藏了后端实际数据库,对于客户端来说就是在使用一个数据库,不需要关心 ShardingSphere 如何协调背后的数据库,对于使用非 Java 语言的开发者或 DBA 更友好。

比如说 t_user 在数据库层面拆分为若干真实表:t_user_0t_user_9,在客户端操作 ShardingSphere-Proxy 的过程中,只会知道有一张 t_user 逻辑表,路由至真实表的过程都在 ShardingSphere-Proxy 内部执行。

  1. 逻辑表:相同结构的水平拆分数据库(表)的逻辑名称,是 SQL 中表的逻辑标识。 例:用户数据根据主键尾数拆分为 10 张表,分别是 t_user_0t_user_9,他们的逻辑表名为 t_user
  2. 真实表:在水平拆分的数据库中真实存在的物理表。 即上个示例中的 t_user_0t_user_9

2. JDBC 和 Proxy 的区别

看了上面的描述,怎么感觉 ShardingSphere-Proxy 和 ShardingSphere-JDBC 这么像,两者有什么区别?

ShardingSphere-JDBCShardingSphere-Proxy
数据库任意基于 MySQL / PostgreSQL 协议的数据库
连接消耗数
异构语言支持 Java 等基于 JVM 语言任意
性能损耗低损耗略高
无中心化
静态入口

简单总结下两者的不同:

  1. ShardingSphere-JDBC 是一个 Jar 包,底层通过重写 JDBC 组件完成 SQL 解析、路由、改写、执行等流程;需要在项目中添加对应功能的配置文件,对应用有一定侵入性;
  2. ShardingSphere-Proxy 是一个进程服务,大部分情况下定位为辅助开发运维的效率工具。它将自己伪装为数据库,应用对接后对代码是无侵入的;对 SQL 的执行逻辑同 ShardingSphere-JDBC 一致,两者复用同一内核。

ShardingSphere-Proxy 既然对应用无侵入,而且两者复用同一内核,那为什么大家还要用 ShardingSphere-JDBC 呢?

  1. 应用通过 ShardingSphere-JDBC 是直接操作数据库,相当于只有一次网络 IO;而应用连接 ShardingSphere-Proxy 是一次网络 IO,ShardingSphere-Proxy 再操作数据库,又会发生一次网络 IO;
  2. 应用调用链路多了一层,容易形成流量瓶颈,对应用增加了潜在的风险;一般来说,应用程序会搭配 ShardingSphere-JDBC 使用。

当然,ShardingSphere-JDBC 和 ShardingSphere-Proxy 可以进行混合部署,ShardingSphere-JDBC 适用于 Java 开发的高性能的轻量级 OLTP 应用,ShardingSphere-Proxy 适用于 OLAP 应用以及对分片数据库进行管理和运维的场景。

如何开始

ShardingSphere-Proxy 的启动方式有三种:二进制包、Docker、Helm,并分为单机部署和集群部署。文章以单机二进制包的方式启动。

  1. 通过 下载页面 获取 ShardingSphere-Proxy 二进制安装包;
  2. 解压缩后修改 conf/server.yaml 和以 config- 前缀开头的文件,进行分片、读写分离等规则配置;
  3. Linux 操作系统请运行 bin/start.sh,Windows 操作系统请运行 bin/start.bat 启动 ShardingSphere-Proxy。

下载后的文件目录如下:

├── LICENSE
├── NOTICE
├── README.txt
├── bin # 启动停止脚本
├── conf # 服务配置,分库分表、读写分离、数据加密等功能的配置文件
├── lib # Jar 包
└── licenses
复制代码

1. 将 MySQL 的 JDBC 驱动复制到 ext-lib 包

下载驱动 mysql-connector-java-5.1.47.jar 或者 mysql-connector-java-8.0.11.jar 放入 ext-lib 包。因为初始目录中并没有 ext-lib,需要自行创建。

2. 修改 conf/server.yaml 配置文件

server.yaml 配置中默认集群运行模式,这里提供一份单机的运行配置。

mode:
 type: Standalone # 单机模式
 repository:
   type: File
   props:
     path: /Users/xxx/software/apache-shardingsphere-5.1.0-shardingsphere-proxy/file # 元数据配置等持久化文件路径
 overwrite: false # 是否覆盖已存在的元数据
​
rules: # 认证信息
 - !AUTHORITY
   users: # 初始化用户
     - root@%:root
     - sharding@:sharding
   provider:
     type: ALL_PRIVILEGES_PERMITTED
 - !TRANSACTION
   defaultType: XA
   providerType: Atomikos
 - !SQL_PARSER
   sqlCommentParseEnabled: true
   sqlStatementCache:
     initialCapacity: 2000
     maximumSize: 65535
     concurrencyLevel: 4
   parseTreeCache:
     initialCapacity: 128
     maximumSize: 1024
     concurrencyLevel: 4
​
props: # 公用配置
 max-connections-size-per-query: 1
 kernel-executor-size: 16  # Infinite by default.
 proxy-frontend-flush-threshold: 128  # The default value is 128.
 proxy-opentracing-enabled: false
 proxy-hint-enabled: false
 sql-show: false
 check-table-metadata-enabled: false
 show-process-list-enabled: false
   # Proxy backend query fetch size. A larger value may increase the memory usage of ShardingSphere Proxy.
   # The default value is -1, which means set the minimum value for different JDBC drivers.
 proxy-backend-query-fetch-size: -1
 check-duplicate-table-enabled: false
 proxy-frontend-executor-size: 0 # Proxy frontend executor size. The default value is 0, which means let Netty decide.
   # Available options of proxy backend executor suitable: OLAP(default), OLTP. The OLTP option may reduce time cost of writing packets to client, but it may increase the latency of SQL execution
   # and block other clients if client connections are more than `proxy-frontend-executor-size`, especially executing slow SQL.
 proxy-backend-executor-suitable: OLAP
 proxy-frontend-max-connections: 0 # Less than or equal to 0 means no limitation.
 sql-federation-enabled: false
   # Available proxy backend driver type: JDBC (default), ExperimentalVertx
 proxy-backend-driver-type: JDBC
​
复制代码

需要注意,如果启动单机 ShardingSphere-Proxy,后续需要 Proxy 配置变更,建议将 mode.overwrite 设置为 true,这样 ShardingSphere-Proxy 在启动时就会重新加载元数据。

3. 启动 ShardingSphere-Proxy

执行启动命令:sh bin/start.sh。默认启动端口 3307,可以通过启动脚本命令追加参数的方式替换端口:sh bin/start.sh 3308

查看 ShardingSphere-Proxy 是否启动成功,执行查看日志命令:tail -100f logs/stdout.log。如最后一行出现下述信息,即为启动成功:

[INFO ] xxx-xx-xx xx:xx:xx.xxx [main] o.a.s.p.frontend.ShardingSphereProxy - ShardingSphere-Proxy Standalone mode started successfully
复制代码

场景实践

本章节从实战场景的前提出发,通过 ShardingSphere-Proxy 完成上述需求。

1. 初始化数据库表

# CREATE DATABASE
CREATE DATABASE user_sharding_0;
​
CREATE DATABASE user_sharding_1;
​
# CREATE TABLE
use user_sharding_0;
​
CREATE TABLE `t_user_0` (
  `id` bigint (20) NOT NULL,
  `user_id` bigint (20) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = latin1;
​
CREATE TABLE `t_user_1` (
  `id` bigint (20) NOT NULL,
  `user_id` bigint (20) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = latin1;
​
​
use user_sharding_1;
​
CREATE TABLE `t_user_0` (
  `id` bigint (20) NOT NULL,
  `user_id` bigint (20) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = latin1;
​
​
CREATE TABLE `t_user_1` (
  `id` bigint (20) NOT NULL,
  `user_id` bigint (20) NOT NULL,
  `create_date` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)) ENGINE = InnoDB DEFAULT CHARSET = latin1;
复制代码

2. 初始化 Proxy 分片配置

schemaName: sharding_db
​
dataSources:
  ds_0:
    url: jdbc:mysql://127.0.0.1:3306/user_sharding_0?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_1:
    url: jdbc:mysql://127.0.0.1:3306/user_sharding_1?serverTimezone=UTC&useSSL=false
    username: root
    password: root
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
​
rules:
- !SHARDING
  tables:
    t_user:
      actualDataNodes: ds_${0..1}.t_user_${0..1}
      tableStrategy:
        standard:
          shardingColumn: user_id
          shardingAlgorithmName: t_user_inline
      keyGenerateStrategy:
        column: user_id
        keyGeneratorName: snowflake
  bindingTables:
    - t_user
  defaultDatabaseStrategy:
    standard:
      shardingColumn: user_id
      shardingAlgorithmName: database_inline
  defaultTableStrategy:
    none:
​
  shardingAlgorithms:
    database_inline:
      type: INLINE
      props:
        algorithm-expression: ds_${user_id % 2}
    t_user_inline:
      type: INLINE
      props:
        algorithm-expression: t_user_${user_id % 2}
​
  keyGenerators:
    snowflake:
      type: SNOWFLAKE
复制代码

3. 分片测试

使用 MySQL 终端命令连接 ShardingSphere-Proxy 服务端。如果 Docker 部署的数据库,需要加上 -h 本机 ip。因为容器内访问 127.0.0.1 不通。

# 将 {xx} 替换为实际参数
mysql -h {ip} -u {username} -p{password} -P 3307
# 示例命令
mysql -h 127.0.0.1 -u root -proot -P 3307
复制代码

ShardingSphere-Proxy 支持 Navicat MySQL、DataGrip、WorkBench、TablePlus 等数据库管理工具连接。

连接成功后,查询代理数据库,与配置文件中一致。

mysql> show databases;
+-------------+
| schema_name |
+-------------+
| sharding_db |
+-------------+
1 row in set (0.02 sec)
复制代码

执行新增 t_user 语句,插入 6 条用户数据,创建时间 2021 年 3 条,2022 年 3 条。

mysql> use sharding_db;
mysql> INSERT INTO t_user (id, user_id, create_date) values(1, 1, '2021-01-01 00:00:00'), (2, 2, '2021-01-01 00:00:00'), (3, 3, '2021-01-01 00:00:00'), (4, 4, '2022-01-01 00:00:00'), (5, 5, '2022-02-01 00:00:00'), (6, 6, '2022-03-01 00:00:00');
Query OK, 6 rows affected (0.16 sec)
​
mysql> select * from t_user;
+----+---------+---------------------+
| id | user_id | create_date         |
+----+---------+---------------------+
|  2 |       2 | 2021-01-01 00:00:00 |
|  4 |       4 | 2022-01-01 00:00:00 |
|  6 |       6 | 2022-03-01 00:00:00 |
|  1 |       1 | 2021-01-01 00:00:00 |
|  3 |       3 | 2021-01-01 00:00:00 |
|  5 |       5 | 2022-02-01 00:00:00 |
+----+---------+---------------------+
复制代码

此时数据分别散落在 user_sharding_0user_sharding_1 库。

回到最初的问题,如何定位数据信息。因为 ShardingSphere-Proxy 已经将表进行了逻辑聚合,所以直接查询就好。

mysql> select * from t_user where user_id = 1;
+----+---------+---------------------+
| id | user_id | create_date         |
+----+---------+---------------------+
|  1 |       1 | 2021-01-01 00:00:00 |
+----+---------+---------------------+
1 row in set (0.01 sec)
复制代码

第二个问题,查询 2022 年用户增长数量以及用户情况。

mysql> select count(*) from t_user where create_date > '2022-00-00 00:00:00';
+----------+
| count(*) |
+----------+
|        3 |
+----------+
1 row in set (0.10 sec)

mysql> select * from t_user where create_date > '2022-00-00 00:00:00';
+----+---------+---------------------+
| id | user_id | create_date         |
+----+---------+---------------------+
|  4 |       4 | 2022-01-01 00:00:00 |
|  6 |       6 | 2022-01-01 00:00:00 |
|  5 |       5 | 2022-01-01 00:00:00 |
+----+---------+---------------------+
3 rows in set (0.02 sec)
复制代码

第三个问题同上。

最后总结

文章通过图文并茂的方式帮助大家过了一遍 ShardingSphere-Proxy 的基本概念,引申出了分库分表后产生的实际运维场景,并演示了如何通过 ShardingSphere-Proxy 解决相关问题。

相信大家看完对 ShardingSphere-Proxy 有了更深入的认识。首先要明白 ShardingSphere-Proxy 的定位是协助开发运维的产品,掌握 ShardingSphere-JDBC 和 ShardingSphere-Proxy 有哪些区别,以及理解两者的优缺点和实现方式是怎么样的。在这个基础上去阅读两者的源码,也就更容易理解了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/10518.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot学习2

一、spring boot自动装配原理 pom.xml spring-boot-dependencies 核心依赖在父工程中 在写或者引入一些spring boot依赖的时候&#xff0c;不需要指定版本&#xff0c;因为有这些版本仓库启动器 <dependency><groupId>org.springframework.boot</groupId>&…

会画画的海龟,Python Turtle库详解(27)

小朋友们好&#xff0c;大朋友们好&#xff01; 我是猫妹&#xff0c;一名爱上Python编程的小学生。 欢迎和猫妹一起&#xff0c;趣味学Python。 今日主题 介绍下Python的turtle库&#xff0c;这是一个可以画画的库&#xff0c;非常适合小孩子在屏幕上画画。 先学习基础知…

第08章_面向对象编程(高级)

第08章_面向对象编程(高级) 讲师&#xff1a;尚硅谷-宋红康&#xff08;江湖人称&#xff1a;康师傅&#xff09; 官网&#xff1a;http://www.atguigu.com 本章专题与脉络 1. 关键字&#xff1a;static 回顾类中的实例变量&#xff08;即非static的成员变量&#xff09; c…

虚拟化技术:实现资源高效利用和灵活管理的利器

虚拟化技术是一种通过软件或硬件手段&#xff0c;将物理资源抽象化&#xff0c;从而创建虚拟资源的技术。这种技术可以应用于计算、存储、网络等领域&#xff0c;通过将物理资源划分为多个虚拟资源&#xff0c;使得多个应用程序或用户可以共享同一组物理资源&#xff0c;从而提…

Linux 进程管理之四大名捕

一、四大名捕 四大名捕&#xff0c;最初出现于温瑞安创作的武侠小说&#xff0c;是朝廷中正义力量诸葛小花的四大徒弟&#xff0c;四人各怀绝技&#xff0c;分别是轻功暗器高手 “无情”、内功卓越的高手“铁手”、腿功惊人的“追命” 和剑法一流的“冷血”。 本文四大名捕由…

关于电商商品数据API接口列表,你想知道的(详情页、Sku信息、商品描述、评论问答列表)

目录 一、商品数据API接口列表 二、商品详情数据API调用代码item_get 三、获取sku详细信息item_sku 四、获得淘宝商品评论item_review 五、数据说明文档 进入 一、商品数据API接口列表 二、商品详情数据API调用代码item_get <?php// 请求示例 url 默认请求参数已经URL…

集合-LinkedList

LinkedList LinkedList的概述 LinkedList的底层使用双向链表实现。 链表是一种线性数据结构&#xff0c;其中每个元素都是一个单独的对象&#xff0c;包含一个指向列表中下一个节点的引用。 它可以用于实现各种抽象数据类型&#xff0c;例如列表、堆栈、队列等。 LinkedLis…

Carla仿真二:Carla多视图切换代码详解

文章目录前言一、Carla多视图切换效果二、Camera安装坐标系1、Carla.Location2、Carla.Rotation三、接口及代码详解1、接口介绍2、生成上帝视图代码3、生成Camera视图代码四、完整代码前言 1、Carla提供了大量的Python API接口&#xff0c;用户可以通过查找文档实现各类功能&a…

无限制翻译软件-中英互译字数无限

翻译软件是我们工作及学习中必不可少的工具&#xff0c;然而许多翻译软件在使用时常常会出现字数限制的问题,这使得用户在处理长文本和大量文本时变得十分麻烦。如果你也遇到了类似的问题&#xff0c;那么哪个翻译软件不限制字数将为您带来全新的翻译体验。 以下是我们的哪个翻…

Vite打包后直接使用浏览器打开,显示空白问题

vite打包后&#xff0c;直接用浏览器打开显示空白 1.需求&#xff1a; 安卓webview等浏览器直接打开文件显示 2.原因 &#xff08;1&#xff09;资源路径错误&#xff1a; vite.config.js 配置 base: “./” &#xff08;在webpack中则配置publicPath: "./"即可…

ATTCK v12版本战术实战研究——提权(一)

一、概述 前几期文章中&#xff0c;我们中介绍ATT&CK 14项战术中提权战术&#xff08;一&#xff09;&#xff0c;包括提权前6项子技术。那么从前文中介绍的相关提权技术来开展测试&#xff0c;进行更深一步的分析。本文主要内容是介绍攻击者在运用提权技术时&#xff0c;…

算法 贪心2 || 122.买卖股票的最佳时机II 55. 跳跃游戏 45.跳跃游戏II

122.买卖股票的最佳时机II 如果想到其实最终利润是可以分解的&#xff0c;那么本题就很容易了&#xff01; 如何分解呢&#xff1f; 假如第0天买入&#xff0c;第3天卖出&#xff0c;那么利润为&#xff1a;prices[3] - prices[0]。 相当于(prices[3] - prices[2]) (prices[2…

【华为OD机试】1043 - 从单向链表中删除指定值的节点

文章目录一、题目&#x1f538;题目描述&#x1f538;输入输出&#x1f538;样例1&#x1f538;样例2二、代码参考作者&#xff1a;KJ.JK&#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &am…

8D和A3报告

8D和3A报告&#xff0c;他们都不仅仅是记录问题的一种文书&#xff0c;而是解决问题的工具。 A3发展于TPS &#xff08;Toyota Production system&#xff09;&#xff0c;可以用来解决问题&#xff0c;沟通&#xff0c;记录&#xff0c;是一种流程&#xff0c;当人们在使用A3…

自定义类型详解

目录 一 结构体 1.1 结构的基础知识 1.2 结构的声明 1.3 特殊的声明 1.4 结构的自引用 1.5 结构体变量的的定义和初始化 1.6 结构体内存对齐 1.7 修改默认对齐数 1.8 结构体传参 二 位段 2.1 什么是位段 2.2 位段的内存分配 2.3 位段的跨平台问题 三 枚举 3.1 枚…

JAVA本地监听与远程端口扫描的设计与开发

随着Internet的不断发展&#xff0c;信息技术已成为社会进步的巨大推动力。不管是存储于服务器里还是流通于Internet上的信息都已成为一个关系事业成败的关键&#xff0c;这就使保证信息的安全变得格外重要。本地监听与远程端口扫描程序就是在基于Internet的端口扫描的基础上&a…

VMware Horizon 8 2303 - 虚拟桌面基础架构 (VDI) 和应用软件

请访问原文链接&#xff1a;https://sysin.org/blog/vmware-horizon-8/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org Version2303DocumentationRelease NotesRelease Date2023-03-30 虚拟桌面基础架构 (VDI) 和应用软件 VMw…

使用Ubuntu22.04搭建k8s环境和一些k8s基础知识

minikube搭建 基本环境 我使用virtualBox构建的ubuntu&#xff0c;选择4核4G内存minikube是一个K8S集群模拟器&#xff0c;可以快速构建一个单节点的集群&#xff0c;用于在本地测试和开发首先使用官方脚本安装docker curl -fsSL https://test.docker.com -o test-docker.sh…

Vue——模板引用

目录 访问模板引用​ v-for 中的模板引用​ 函数模板引用​ 组件上的 ref​ 虽然 Vue 的声明性渲染模型为你抽象了大部分对 DOM 的直接操作&#xff0c;但在某些情况下&#xff0c;我们仍然需要直接访问底层 DOM 元素。要实现这一点&#xff0c;我们可以使用特殊的 ref att…

【FPGA】多功能ALU

目录 实验要求 源代码 顶层模块 数据输入模块 ALU运算模块 结果处理模块 扫描数码管模块 扫描数码管顶层 分频器 数码管显示 仿真代码 结构层图 管脚配置 实验板卡&#xff1a;xc7a100tlc sg324-2L&#xff0c;共20个开关 实验要求 通过高低位控制&#xff0c;实现32位数…