随着数据规模的不断膨胀,使用多节点集群的分布式方式逐渐成为趋势。在这种情况下,如何高效、自动化管理集群节点,实现不同节点的协同工作,配置一致性,状态一致性,高可用性,可观测性等,就成为一个重要的挑战。

集群管理的复杂性体现在,一方面我们需要把所有的节点,不管是底层数据库节点,还是中间件或者业务系统节点的状态都统一管理起来,并且能实时探测到最新的配置变动情况,进一步为集群的调控和调度提供依据。

另一方面,不同节点之间的统一协调,分库分表策略以及规则同步,也需要我们能够设计一套在分布式情况下,进行全局事件通知机制以及独占性操作的分布式协调锁机制。在这方面,ShardingJDBC采用了Zookeeper/Etcd来实现配置的同步,状态变更通知,以及分布式锁来控制排他操作。

ShardingJDBC分布式治理

ShardingJDBC集成了Zookeeper/Etcd,用来实现ShardingJDBC的分布式治理,下面我们先通过一个应用程序来演示一下实现原理。

安装Zookeeper

  • 通过这个地址下载Zookeeper

    https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.6.3/apache-zookeeper-3.6.3-bin.tar.gz

  • 常用操作命令

    #启动ZK服务:
    bin/zkServer.sh start
    #查看ZK服务状态:
    bin/zkServer.sh status
    #停止ZK服务:
    bin/zkServer.sh stop
    #重启ZK服务:
    bin/zkServer.sh restart
    #连接服务器
    zkCli.sh -timeout 0 -r -server ip:port
  • 单机安装

    初次使用zookeeper,需要将conf目录下的zoo_sample.cfg文件copy一份重命名为zoo.cfg

    修改dataDir目录,dataDir表示日志文件存放的路径(关于zoo.cfg的其他配置信息后面会讲)

Sharding-JDBC集成Zookeeper

本阶段演示的项目代码:sharding-jdbc-split-zookeeper,项目结构如图9-1所示。

图9-1 项目结构

添加jar包依赖

引入jar包依赖(只需要依赖下面两个包即可)

<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-governance-repository-zookeeper-curator</artifactId>
<version>5.0.0-alpha</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-governance-spring-boot-starter</artifactId>
<version>5.0.0-alpha</version>
<exclusions>
<exclusion>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-test</artifactId>
</exclusion>
</exclusions>
</dependency>

其他基础jar包(所有项目都是基于spring boot集成mybatis拷贝的)

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.72</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>

添加配置文件

增加基础的分库分表配置-application.properties

spring.shardingsphere.datasource.names=ds-0,ds-1
spring.shardingsphere.datasource.common.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.common.driver-class-name=com.mysql.jdbc.Driver spring.shardingsphere.datasource.ds-0.username=root
spring.shardingsphere.datasource.ds-0.password=123456
spring.shardingsphere.datasource.ds-0.jdbc-url=jdbc:mysql://192.168.221.128:3306/shard01?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8 spring.shardingsphere.datasource.ds-1.username=root
spring.shardingsphere.datasource.ds-1.password=123456
spring.shardingsphere.datasource.ds-1.jdbc-url=jdbc:mysql://192.168.221.128:3306/shard02?serverTimezone=UTC&useSSL=false&useUnicode=true&characterEncoding=UTF-8 spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-column=user_id
spring.shardingsphere.rules.sharding.default-database-strategy.standard.sharding-algorithm-name=database-inline spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds-$->{0..1}.t_order_$->{0..1}
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.table-strategy.standard.sharding-algorithm-name=t-order-inline spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.database-inline.props.algorithm-expression=ds-$->{user_id % 2}
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-inline.props.algorithm-expression=t_order_$->{order_id % 2}
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-item-inline.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.t-order-item-inline.props.algorithm-expression=t_order_item_$->{order_id % 2} spring.shardingsphere.rules.sharding.key-generators.snowflake.type=SNOWFLAKE
spring.shardingsphere.rules.sharding.key-generators.snowflake.props.worker-id=123

增加Zookeeper配置

# 治理名称(在zookeeper上的节点名称)
spring.shardingsphere.governance.name=sharding-jdbc-split-zookeeper
# 本地配置是否覆盖配置中心配置。如果可覆盖,每次启动都以本地配置为准.
spring.shardingsphere.governance.overwrite=true # Zookeeper/etcd
spring.shardingsphere.governance.registry-center.type=ZooKeeper
spring.shardingsphere.governance.registry-center.server-lists=192.168.221.131:2181
# 之所以加下面两个参数,是因为默认的链接超时时间是1500毫秒,由于时间较短导致启动时很容易超时,导致连接失败
# 重试次数
spring.shardingsphere.governance.registry-center.props.maxRetries=4
# 重试间隔时间
spring.shardingsphere.governance.registry-center.props.retryIntervalMilliseconds=6000

启动项目进行测试

启动过程中看到如下日志,表示配置zookeeper成功,启动的时候会先把本地配置保存到zookeeper中,后续我们可以在zookeeper中修改相关配置,然后同步通知给到相关的应用节点。

2021-07-29 21:31:25.007  INFO 112916 --- [           main] org.apache.zookeeper.ZooKeeper           : Client environment:java.io.tmpdir=C:\Users\mayn\AppData\Local\Temp\
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:java.compiler=<NA>
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.name=Windows 10
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.arch=amd64
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.version=10.0
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:user.name=mayn
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:user.home=C:\Users\mayn
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:user.dir=E:\教研-课件\vip课程\第五轮\03 高并发组件\09 ShardingSphere基于Zookeeper实现分布式治理\sharding-jdbc-readwrite-zookeeper
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.memory.free=482MB
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.memory.max=7264MB
2021-07-29 21:31:25.007 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Client environment:os.memory.total=501MB
2021-07-29 21:31:25.009 INFO 112916 --- [ main] org.apache.zookeeper.ZooKeeper : Initiating client connection, connectString=192.168.221.131:2181 sessionTimeout=60000 watcher=org.apache.curator.ConnectionState@68e2d03e
2021-07-29 21:31:25.012 INFO 112916 --- [ main] org.apache.zookeeper.common.X509Util : Setting -D jdk.tls.rejectClientInitiatedRenegotiation=true to disable client-initiated TLS renegotiation
2021-07-29 21:31:25.020 INFO 112916 --- [ main] org.apache.zookeeper.ClientCnxnSocket : jute.maxbuffer value is 1048575 Bytes
2021-07-29 21:31:25.023 INFO 112916 --- [ main] org.apache.zookeeper.ClientCnxn : zookeeper.request.timeout value is 0. feature enabled=false
2021-07-29 21:31:25.030 INFO 112916 --- [ main] o.a.c.f.imps.CuratorFrameworkImpl : Default schema

接着访问如下接口进行测试。

@RestController
@RequestMapping("/t-order")
public class TOrderController { @Autowired
ITOrderService orderService; @GetMapping
public void init() throws SQLException {
orderService.initEnvironment();
orderService.processSuccess();
}
}

配置中心的数据结构说明

注册中心的数据结构如下

namespace: 就是spring.shardingsphere.governance.name

namespace
├──users # 权限配置
├──props # 属性配置
├──schemas # Schema 配置
├ ├──${schema_1} # Schema 名称1
├ ├ ├──datasource # 数据源配置
├ ├ ├──rule # 规则配置
├ ├ ├──table # 表结构配置
├ ├──${schema_2} # Schema 名称2
├ ├ ├──datasource # 数据源配置
├ ├ ├──rule # 规则配置
├ ├ ├──table # 表结构配置

rules全局配置规则

可包括访问 ShardingSphere-Proxy 用户名和密码的权限配置

- !AUTHORITYusers:  - root@%:root  - sharding@127.0.0.1:shardingprovider:  type: NATIVE

props属性配置

ShardingSphere相关属性配置

executor-size: 20sql-show: true

/schemas/${schemeName}/dataSources

多个数据库连接池的集合,不同数据库连接池属性自适配(例如:DBCP,C3P0,Druid, HikariCP)。

ds_0:   dataSourceClassName: com.zaxxer.hikari.HikariDataSource  props:    url: jdbc:mysql://127.0.0.1:3306/demo_ds_0?serverTimezone=UTC&useSSL=false    password: null    maxPoolSize: 50    connectionTimeoutMilliseconds: 30000    idleTimeoutMilliseconds: 60000    minPoolSize: 1    username: root    maxLifetimeMilliseconds: 1800000ds_1:   dataSourceClassName: com.zaxxer.hikari.HikariDataSource  props:    url: jdbc:mysql://127.0.0.1:3306/demo_ds_1?serverTimezone=UTC&useSSL=false    password: null    maxPoolSize: 50    connectionTimeoutMilliseconds: 30000    idleTimeoutMilliseconds: 60000    minPoolSize: 1    username: root    maxLifetimeMilliseconds: 1800000

/schemas/${schemeName}/rule

规则配置,可包括数据分片、读写分离等配置规则

rules:- !SHARDING  defaultDatabaseStrategy:    standard:      shardingAlgorithmName: database-inline      shardingColumn: user_id  keyGenerators:    snowflake:      props:        worker-id: '123'      type: SNOWFLAKE  shardingAlgorithms:    t-order-inline:      props:        algorithm-expression: t_order_$->{order_id % 2}      type: INLINE    database-inline:      props:        algorithm-expression: ds-$->{user_id % 2}      type: INLINE    t-order-item-inline:      props:        algorithm-expression: t_order_item_$->{order_id % 2}      type: INLINE  tables:    t_order:      actualDataNodes: ds-$->{0..1}.t_order_$->{0..1}      keyGenerateStrategy:        column: order_id        keyGeneratorName: snowflake      logicTable: t_order      tableStrategy:        standard:          shardingAlgorithmName: t-order-inline          shardingColumn: order_id

/schemas/${schemeName}/table

表结构配置,暂时不支持动态修改

configuredSchemaMetaData:  tables:    t_order:      columns:        order_id:          caseSensitive: false          dataType: 0          generated: true          name: order_id          primaryKey: true        user_id:          caseSensitive: false          dataType: 0          generated: false          name: user_id          primaryKey: false        address_id:          caseSensitive: false          dataType: 0          generated: false          name: address_id          primaryKey: false        status:          caseSensitive: false          dataType: 0          generated: false          name: status          primaryKey: falseunconfiguredSchemaMetaDataMap:  ds-0:  - t_order_complex  - t_order_interval  - t_order_item_complex

动态生效

除了table相关的配置无法动态更改之外,其他配置在zookeeper上修改之后,在不重启应用节点时,都会同步到相关服务节点。

比如,我们修改图9-2所示的红色部分的位置,把t_order_$->{0..1}修改成t_order_$->{0..4},这样就会生成4个分片,并且取模规则也做相应更改。

然后点击保存后,在不重启应用节点时,重新发起接口测试请求,就可以看到修改成功后的结果。

http://localhost:8080/swagger-ui.html


图9-2 zookeeper配置中心

注册中心节点

在zookeeper服务器上,还存在以下节点信息。

namespace   ├──states   ├    ├──proxynodes   ├    ├     ├──${your_instance_ip_a}@${your_instance_pid_x}@${UUID}   ├    ├     ├──${your_instance_ip_b}@${your_instance_pid_y}@${UUID}   ├    ├     ├──....   ├    ├──datanodes   ├    ├     ├──${schema_1}   ├    ├     ├      ├──${ds_0}   ├    ├     ├      ├──${ds_1}   ├    ├     ├──${schema_2}   ├    ├     ├      ├──${ds_0}   ├    ├     ├      ├──${ds_1}   ├    ├     ├──....

这个是注册中心节点,用来保存shardingsphere-proxy中间件的服务器实例信息、以及实例运行情况。

运行实例标识由运行服务器的 IP 地址和 PID 构成。

运行实例标识均为临时节点,当实例上线时注册,下线时自动清理。 注册中心监控这些节点的变化来治理运行中实例对数据库的访问等。

由于注册中心会在后续的内容中讲,所以这里暂时不展开。

分布式治理总结

引入zookeeper这样一个角色,可以协助ShardingJDBC完成以下功能

  • 配置集中化:越来越多的运行时实例,使得散落的配置难于管理,配置不同步导致的问题十分严重。将配置集中于配置中心,可以更加有效进行管理。
  • 配置动态化:配置修改后的分发,是配置中心可以提供的另一个重要能力。它可支持数据源和规则的动态切换。
  • 存放运行时的动态/临时状态数据,比如可用的 ShardingSphere 的实例,需要禁用或熔断的数据源等。
  • 提供熔断数据库访问程序对数据库的访问和禁用从库的访问的编排治理能力。治理模块仍然有大量未完成的功能(比如流控等)。

到目前为止,ShardingSphere中Sharding-JDBC部分的内容就到这里结束了,另外一个组件Sharding-Proxy就没有展开了,因为它相当于实现了数据库层面的代理,也就是说,不需要开发者在应用程序中配置数据库分库分表的规则,而是直接把Sharding-Proxy当作数据库源连接,Sharding-Proxy相当于Mysql数据库的代理,当请求发送到Sharding-Proxy之后,在Sharding-Proxy上会配置相关的分片规则,然后根据分片规则进行相关处理。

关注[跟着Mic学架构]公众号,获取更多精品原创

ShardingJdbc基于Zookeeper实现分布式治理的更多相关文章

  1. 基于ZooKeeper的分布式Session实现(转)

    1.   认识ZooKeeper ZooKeeper—— “动物园管理员”.动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始丛林里,心惊胆颤的被 ...

  2. 基于ZooKeeper的分布式Session实现

    1.   认识ZooKeeper ZooKeeper—— “动物园管理员”.动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始丛林里,心惊胆颤的被 ...

  3. 基于 Zookeeper 的分布式锁实现

    1. 背景 最近在学习 Zookeeper,在刚开始接触 Zookeeper 的时候,完全不知道 Zookeeper 有什么用.且很多资料都是将 Zookeeper 描述成一个“类 Unix/Linu ...

  4. 【连载】redis库存操作,分布式锁的四种实现方式[一]--基于zookeeper实现分布式锁

    一.背景 在电商系统中,库存的概念一定是有的,例如配一些商品的库存,做商品秒杀活动等,而由于库存操作频繁且要求原子性操作,所以绝大多数电商系统都用Redis来实现库存的加减,最近公司项目做架构升级,以 ...

  5. Java Web学习总结(20)——基于ZooKeeper的分布式session实现

    1.   认识ZooKeeper ZooKeeper-- "动物园管理员".动物园里当然有好多的动物,游客可以根据动物园提供的向导图到不同的场馆观赏各种类型的动物,而不是像走在原始 ...

  6. 基于zookeeper实现分布式配置中心(二)

    上一篇(基于zookeeper实现分布式配置中心(一))讲述了zookeeper相关概念和工作原理.接下来根据zookeeper的特性,简单实现一个分布式配置中心. 配置中心的优势 1.各环境配置集中 ...

  7. 分布式锁(3) ----- 基于zookeeper的分布式锁

    分布式锁系列文章 分布式锁(1) ----- 介绍和基于数据库的分布式锁 分布式锁(2) ----- 基于redis的分布式锁 分布式锁(3) ----- 基于zookeeper的分布式锁 代码:ht ...

  8. 基于Zookeeper的分布式锁(干干干货)

    原文地址: https://juejin.im/post/5df883d96fb9a0163514d97f 介绍 为什么使用锁 锁的出现是为了解决资源争用问题,在单进程环境下的资源争夺可以使用 JDK ...

  9. 基于ZooKeeper的分布式锁和队列

    在分布式系统中,往往需要一些分布式同步原语来做一些协同工作,上一篇文章介绍了Zookeeper的基本原理,本文介绍下基于Zookeeper的Lock和Queue的实现,主要代码都来自Zookeeper ...

随机推荐

  1. 内核软中断之tasklet机制

    1. 软中断IRQ简介 软中断(SoftIRQ)是内核提供的一种基于中断的延时机制, Linux内核定义的软中断有以下几种: enum { HI_SOFTIRQ=0, /*高优先级的tasklet*/ ...

  2. Identity角色管理三(编辑角色)

    因只有角色名能修改故继续使用创建角色的视图模型 using System.ComponentModel; using System.ComponentModel.DataAnnotations; na ...

  3. Vue CSS模拟菜单点击变色

    <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8&quo ...

  4. wrap()包裹被选元素的内容

    <!doctype html><html><head><meta charset="utf-8"><title>修改代码 ...

  5. freeswitch 编译安装后的配置

    --------------------FreeSWITCH configuration------------Locations: prefix: /usr/local/freeswitchexec ...

  6. C# 动态构建表达式树(一)—— 构建 Where 的 Lambda 表达式

    C# 动态构建表达式树(一)-- 构建 Where 的 Lambda 表达式 前言 记得之前同事在做筛选功能的时候提出过一个问题:如果用户传入的条件数量不确定,条件的内容也不确定(大于.小于和等于), ...

  7. 5.21学习总结——android开发实现用户头像的上传

    最近在做个人头像的上传,具体是能调用摄像头和从相册进行选择.本篇文章参考的我的同学的博客,大家有兴趣可以去原作者那里去看看: Hi(.・∀・)ノ (cnblogs.com) 1.使用glide进行图片 ...

  8. symfony生成路由

    控制器里生成地址 $this->generateUrl('course_manage_show_test', array('id' => 1)) twig前端文件生成地址: {{ path ...

  9. Orchard Core 简介

    Orchard Core 是基于ASP.NET Core 对Orchard CMS的 二次开发. Orchard Core由两部分组成: Orchard Core Framework: 一个基于ASP ...

  10. 配置 放上传文件的目录 apache(httpd)

    1. 确认服务器 开放8088端口 https://www.apachefriends.org/download.html 下载XAMPP for Windows,安装 2. 修改apache主配置文 ...