栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

ShardingJDBC数据库中间件学习笔记

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ShardingJDBC数据库中间件学习笔记

简介

官网地址:https://shardingsphere.apache.org/index_zh.html

Apache ShardingSphere 产品定位为 Database Plus,旨在构建多模数据库上层的标准和生态。 它关注如何充分合理地利用数据库的计算和存储能力,而并非实现一个全新的数据库。ShardingSphere 站在数据库的上层视角,关注他们之间的协作多于数据库自身。

连接增量可插拔是 Apache ShardingSphere 的核心概念。

  • 连接:通过对数据库协议、SQL 方言以及数据库存储的灵活适配,快速的连接应用与多模式的异构数据库;
  • 增量:获取数据库的访问流量,并提供流量重定向(数据分片、读写分离、影子库)、流量变形(数据加密、数据脱敏)、流量鉴权(安全、审计、权限)、流量治理(熔断、限流)以及流量分析(服务质量分析、可观察性)等透明化增量功能;
  • 可插拔:项目采用微内核 + 三层可插拔模型,使内核、功能组件以及生态对接完全能够灵活的方式进行插拔式扩展,开发者能够像使用积木一样定制属于自己的独特系统。
ShardingSphere-JDBC

定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。

  • 适用于任何基于 JDBC 的 ORM 框架,如:JPA, Hibernate, Mybatis, Spring JDBC Template 或直接使用 JDBC;
  • 支持任何第三方的数据库连接池,如:DBCP, C3P0, BoneCP, HikariCP 等;
  • 支持任意实现 JDBC 规范的数据库,目前支持 MySQL,PostgreSQL,Oracle,SQLServer 以及任何可使用 JDBC 访问的数据库。
ShardingSphere-Proxy

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

  • 向应用程序完全透明,可直接当做 MySQL/PostgreSQL 使用;
  • 适用于任何兼容 MySQL/PostgreSQL 协议的的客户端。
hardingSphere-Sidecar(TODO)

定位为 Kubernetes 的云原生数据库代理,以 Sidecar 的形式代理所有对数据库的访问。 通过无中心、零侵入的方案提供与数据库交互的啮合层,即 Database Mesh,又可称数据库网格。

Database Mesh 的关注重点在于如何将分布式的数据访问应用与数据库有机串联起来,它更加关注的是交互,是将杂乱无章的应用与数据库之间的交互进行有效地梳理。 使用 Database Mesh,访问数据库的应用和数据库终将形成一个巨大的网格体系,应用和数据库只需在网格体系中对号入座即可,它们都是被啮合层所治理的对象。

ShardingSphere-JDBCShardingSphere-ProxyShardingSphere-Sidecar
数据库任意 MySQL/PostgreSQLMySQL/PostgreSQL
连接消耗数
异构语言仅 Java任意
性能损耗低损耗略高
无中心化
静态入口
hardingSphere功能清单
  • 功能列表:1.数据库分片 2.分库分表 3.读写分离 4.分片策略定制化 5.无中心化分布式主键
  • 分布式事务: 1.标准化事务接口 2.XA强一致事务 3.柔性事务 4.数据库治理
  • 分布式治理: 1.弹性伸缩 2.可视化链路追踪 3.数据加密
ShardingSphere数据分片内核剖析

ShardingSphere的3个产品的数据分片主要流程是完全一致的。核心由SQL解析=>执行器优化=>SQL路由=>SQL改写=> SQL执行=>结果归并的流程组成。

ShardingJDBC准备 Mysql完成主从复制

liunx准备mysql数据库

概述

主从复制(也称AB复制)允许将来自一个MySQL数据库服务器(主服务器)的数据复制到一个或多个MySQL数据库服务器(从服务器)。

复制是异步的从站不需要永久连接以接收来自主站的更新。

根据配置,您可以复制数据库中的所有数据库,所选数据库甚至选定的表。

主从复制优点
  • 横向扩展解决方案–在多个从站之间分配负载以提高性能。在此环境中,所有写入和更新都必须在主服务器上进行。但是,读取可以在一个或多个从设备上进行。该模型可以提高写入性能(因为主设备专用于更新),同时显着提高了越来越多的从设备的读取速度。
  • 数据安全性·因为数据被复制到从站,并且从站可以暂停复制过程,所以可以在从站上运行备份服务而不会破坏相应的主数据。
  • 分析–可以在主服务器上创建实时数据,而信息分析可以在从服务器上进行,而不会影响主服务器的性能。远程数据分发–您可以使用复制为远程站点创建数据的本地副本,而无需永久访问主服务器。
主从复制原理

前提是作为主服务器角色的数据库服务器必须开启二进制曰志

主服务器上面的任何修改都会通过自己的I/0 tread(I/O线程)保存在二进制日志 Binary log里面。

  • 从服务器上面也启动一个I/0 thread,通过配置好的用户名和密码,连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log(中继日志)里面。
  • 从服务器上面同时开启一个SQL thread定时检查Realy log(这个文件也是二进制的),如果发现有更新立即把更新的内容在本机的数据库上面执行一遍。
    每个从服务器都会收到主服务器二进制日志的全部内容的副本。
  • 从服务醋设备负责决定应该执行二进制日志中的哪些语句。
    除非另行指定,否则主从二进制日志中的所有事件都在从站上执行。如果需要。您可以将从服务器配置为仅处理一些特定数据库或表的事件。
基于Docker完成主从复制

原文链接:https://www.cnblogs.com/songwenjie/p/9371422.html

为什么基于Docker搭建?
  • 资源有限
  • 虚拟机搭建对机器配置有要求,并且安装mysql步骤繁琐
  • 一台机器上可以运行多个Docker容器
  • Docker容器之间相互独立,有独立ip,互不冲突
  • Docker使用步骤简便,启动容器在秒级别
利用Docker搭建主从服务器

首先拉取docker镜像,我们这里使用5.7版本的mysql:

docker pull mysql:5.7

然后使用此镜像启动容器,这里需要分别启动主从两个容器

Master(主):

docker run -p 3339:3306 --name mymysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

Slave(从):

docker run -p 3340:3306 --name mymysql -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7

Master对外映射的端口是3339,Slave对外映射的端口是3340。因为docker容器是相互独立的,每个容器有其独立的ip,所以不同容器使用相同的端口并不会冲突。这里我们应该尽量使用mysql默认的3306端口,否则可能会出现无法通过ip连接docker容器内mysql的问题。

使用docker ps命令查看正在运行的容器

[root@iz2vcbxtcjxxdepmmofk3hz mysql3307]# docker ps
ConTAINER ID   IMAGE                 COMMAND                  CREATED          STATUS          PORTS                               NAMES
66392fd83cf1   mysql:5.7             "docker-entrypoint.s…"   51 minutes ago   Up 20 minutes   33060/tcp, 0.0.0.0:3308->3306/tcp   mysql-slave
f5b9761e3dee   mysql:5.7             "docker-entrypoint.s…"   51 minutes ago   Up 35 minutes   33060/tcp, 0.0.0.0:3307->3306/tcp   mysql-master
配置Master(主)

通过docker exec -it 627a2368c865 /bin/bash命令进入到Master容器内部,也可以通过docker exec -it mysql-master /bin/bash命令进入。627a2368c865是容器的id,而mysql-master是容器的名称。

cd /etc/mysql切换到/etc/mysql目录下,然后vi my.cnf对my.cnf进行编辑。此时会报出bash: vi: command not found,需要我们在docker容器内部自行安装vim。使用apt-get install vim命令安装vim

会出现如下问题:

Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package vim

执行apt-get update,然后再次执行apt-get install vim即可成功安装vim。然后我们就可以使用vim编辑my.cnf,在my.cnf中添加如下配置:

[mysqld]
## 同一局域网内注意要唯一
server-id=100  
## 开启二进制日志功能,可以随便取(关键)
log-bin=mysql-bin

配置完成之后,需要重启mysql服务使配置生效。使用service mysql restart完成重启。重启mysql服务时会使得docker容器停止,我们还需要docker start mysql-master启动容器。

下一步在Master数据库创建数据同步用户,授予用户 slave REPLICATION SLAVE权限和REPLICATION CLIENT权限,用于在主从库之间同步数据。

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
配置Slave(从)

和配置Master(主)一样,在Slave配置文件my.cnf中添加如下配置:

[mysqld]
## 设置server_id,注意要唯一
server-id=101  
## 开启二进制日志功能,以备Slave作为其它Slave的Master时使用
log-bin=mysql-slave-bin   
## relay_log配置中继日志
relay_log=edu-mysql-relay-bin  

配置完成后也需要重启mysql服务和docker容器,操作和配置Master(主)一致。

链接Master(主)和Slave(从)

在Master进入mysql,执行show master status;

File和Position字段的值后面将会用到,在后面的操作完成之前,需要保证Master库不能做任何操作,否则将会引起状态变化,File和Position字段的值变化。

在Slave 中进入 mysql,执行

change master to master_host='172.17.0.3', master_user='slave', master_password='123456', master_port=3306, master_log_file='mysql-bin.000001', master_log_pos= 3298, master_connect_retry=30;

命令说明:

master_host : Master的地址,指的是容器的独立ip,可以通过docker inspect --format='{{.NetworkSettings.IPAddress}}' 容器名称|容器id 查询容器的ip

master_port: Master的端口号,指的是容器的端口号

master_user: 用于数据同步的用户

master_password: 用于同步的用户的密码

master_log_file: 指定 Slave 从哪个日志文件开始复制数据,即上文中提到的 File 字段的值

master_log_pos: 从哪个 Position 开始读,即上文中提到的 Position 字段的值

master_connect_retry: 如果连接失败,重试的时间间隔,单位是秒,默认是60秒

在Slave 中的mysql终端执行show slave status G;用于查看主从同步状态。

正常情况下,SlaveIORunning 和 SlaveSQLRunning 都是No,因为我们还没有开启主从复制过程。使用start slave开启主从复制过程,然后再次查询主从同步状态show slave status G;。

SlaveIORunning 和 SlaveSQLRunning 都是Yes,说明主从复制已经开启。此时可以测试数据同步是否成功。

读写分离 项目测试 新建项目导入依赖
       
        
            org.springframework.boot
            spring-boot-starter-web
        

        
        
            mysql
            mysql-connector-java
            runtime
        
        
            org.mybatis.spring.boot
            mybatis-spring-boot-starter
            1.3.2
        
        
            com.alibaba
            druid-spring-boot-starter
            1.1.10
        

        
        
            org.apache.shardingsphere
            sharding-jdbc-spring-boot-starter
            4.0.0-RC1
        
        
            org.apache.shardingsphere
            sharding-core-common
            4.0.0-RC1
        

        
            org.projectlombok
            lombok
            true
        
yaml配置
server:
  port: 8085

spring:
  main:
    allow-bean-definition-overriding: true
  shardingsphere:
    # 参数配置 显示SQl
    props:
      sql:
        show: true
    # 配置数据源
    datasource:
      # 给每个数据源取别名
      names: ds1,ds2
      # 给master-ds1每个数据源配置数据库连接信息
      ds1: # master
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3307/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
        username: root
        password: 123456
        maxPoolSize: 100
        minPoolSize: 5
      ds2: # slave
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3308/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=false&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
        username: root
        password: 123456
        maxPoolSize: 100
        minPoolSize: 5
    #    配置默认数据源
    sharding:
      # 默认数据源 主要用于写 注意一定要配置读写分离 如果不配做 那么就会把全部节点都当成slave
      default-data-source-name: ds1
    # 配置读写分离
    masterslave:
      name: ms # 名称 任意取
      master-data-source-name: ds1 # 主库
      slave-data-source-names: ds2 # 从库 多个逗号分割
      # 从节点负载均衡策略 默认轮询 随机 RANDOM
      load-balance-algorithm-type: round_robin

# mybatis 配置
mybatis:
  mapper-locations: classpath*:mapper
public class BirthdayAlgorithm implements PreciseShardingAlgorithm {

  // 有几个数据源 放几条数据
  List dateList = new ArrayList<>();

  {
    Calendar calendar1 = Calendar.getInstance();
    calendar1.set(2021, 1, 1, 0, 0, 0);
    Calendar calendar2 = Calendar.getInstance();
    calendar2.set(2022, 1, 1, 0, 0, 0);
    dateList.add(calendar1.getTime());
    dateList.add(calendar2.getTime());
  }

  
  @Override
  public String doSharding(Collection collection, PreciseShardingValue preciseShardingValue) {
    // 获得属性数据库的值
    Date date = preciseShardingValue.getValue();
    // 获取数据源的名称信息列表
    Iterator iterator = collection.iterator();
    String target = null;
    for (Date s : dateList) {
      target = iterator.next();
      // 如果数据晚于指定的日期直接返回
      if (date.before(s)){
        break;
      }
    }
    return target; // 最后返回的是 ds1  ds2
  }
}
spring:
  shardingsphere:
    sharding:
      tables:
        # 逻辑表名称
        master-savle:
          # 数据节点:多数据源$->{0..N} 逻辑表名$ ->{0..N} 相同表
          actual-data-nodes: ds$->{0..2}.master-savle$->{0..1}
          # 数据源分片策略
          databaseStrategy:
            standard:
              shardingColumn: birthady # 字段名
              preciseAlgorithmClassName: com.tuxc.config.BirthdayAlgorithm
          # 表分片策略
          tableStrategy:
            inline:
              shardingColumn: order_id
              algorithmlnlineexpression: master-savle$->{order_id%2}
第四种: ShardingSphere -符合分片策略((了解)
  • 对应接口:HintShardingStrategy。通过Hint而非SQL解析的方式分片的策略。
  • 对于分片字段非SQL决定,而是由其他外置条件决定的场景,克使用SQL hint灵活的注入分片字段。例如:按照用户登录的时间,主键等进行分库,而数据库中并无此字段。SQL hint支持通过Java API和SQL注解两种方式使用。让后分库分表更加灵活。
第五种:ShardingSphere - hint分片策略(了解)
  • 对应ComplexShardingStrategy。符合分片策略提供对SQL语句中的-,in和between and的分片操作支持。
  • ComplexShardingStrategy支持多分片键,由于多分片键之间的关系复杂,因此并未进行过多的封装,而是直接将分片键组合以及分片操作符透传至分片算法,完全由开发者自己实现,提供最大的灵活度。
分布式主键配置

问题:如果主键是自增长的情况下,存放在不同数据库里的数据,很容易出现主键相同的情况

ShardingSphere提供灵活的配置分布式主键生成策略方式。在分片规则配置模块克配置每个表的主键生成策略。默认使用雪花算法。(snowflake)生成64bit的长整型数据。支持两种方式配置

  • SNOWFLAKE
  • UUID
spring:
  shardingsphere:
    sharding:
      tables:
        # 逻辑表名称
        master-savle:
          key-generator:
            #主键的列明 数据库类型 必须用 bigint类型
            column: id
            type: SHOWFLAKE # 注意要用大写

注意点:

  1. 数据库主键类型不要自增长,否则会插入不进去
  2. 使用SHOWFLAKE ,数据库列类型必须是bigint
  3. 配置主键策略使用大写
分布式事务管理

本地事务

在不开启任何分布式事务管理器的前提下,让每个数据节点各自管理自己的事务,它们之间没有协阅以及通信的能力,也并不互相知晓其他数据节点事务的成功与否。本地事务在性能方面无任何损耗,但在强一致性以及最终一致性方面则力不从心。

两阶段提交

XA协议最早的分布式事务模型是由X/Open国际联盟提出的X/Open Distributed Transaction Processing (DTP)模型,简称XA协议。
基于XA协议实现的分布式事务对业务侵入很小。它最大的优势就是对使用方通明,用户可以像使用本地事务一样使用基于XA协议的分布式事务。XA协议能够严格保障事务ACID特性。
严格保障事务ACID特性是一把双刃剑,事务执行在过程中需要将所需资源全部锁定,它更加适用于执行时间确定的短事务。对于长事务来说,整个事务进行期间对数据的独占,将导致对热点数据依赖的业务系统并发性能衰退明显。因此,在高并发的性能至上场景中,基于XA协议的分布式事务并不是最侄选择。

柔性事务

如果将实现了ACID的事务要素的事务称为刚性事务的话,那么基于base事务要素的事务则称为桑柔性事务。base是基本可用、柔性状态和最终―数性这三个要素的缩写。

  • 基本可用(Basically Available)保证分布式事务参与方不一定同时在线。
  • 柔性状态(Soft state)则允许系统状态更新有一定的延时,这个延时对客户来说不一定能够察觉。
  • 而最终一致性(Eventually consistent)通常是通过消息传递的方式保证系统的最终一致性。

在ACID事务中对隔离性的要求很高,在事务执行过程中,必须将所有的资源锁定。柔性事务的理念则是通过业务逻辑将互斥锁操作从资源层面上移至业务层面。通过放宽对强一致性要求,来换取系统吞吐量的提升。
基于ACID的强一致性事务和基于base的最终一致性事务都不是银弹,只有在最适合的场景中才能发挥它们的最大长处,可通过下表详细对比它们之间的区别,以帮助开发者进行技术选型,

使用SpringBoot starter 引入 Maven 依赖

    org.apache.shardingsphere
    shardingsphere-transaction-xa-core
    ${shardingsphere.version}




    org.apache.shardingsphere
    shardingsphere-transaction-base-seata-at
    ${shardingsphere.version}

配置事务管理器
@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
    
    @Bean
    public PlatformTransactionManager txManager(final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
    
    @Bean
    public JdbcTemplate jdbcTemplate(final DataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}
使用分布式事务
@Transactional
@ShardingSphereTransactionType(TransactionType.XA)  // 支持TransactionType.LOCAL, TransactionType.XA, TransactionType.base
public void insert() {
    jdbcTemplate.execute("INSERT INTO t_order (user_id, status) VALUES (?, ?)", (PreparedStatementCallback) ps -> {
        ps.setObject(1, i);
        ps.setObject(2, "init");
        ps.executeUpdate();
    });
}


转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号