Mycat2【java提高】4

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: Mycat2【java提高】4

3、读写分离配置扩展

通过对集群配置的修改,可以根据需求实现更多种情况的读写分离配置,总结如下

(1)读写分离(一主一从,无备)(m是主,s是从)

{
  "clusterType":"MASTER_SLAVE",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

(2)读写分离(一主一从,一备)(m是主,s是从备)

{
  "clusterType":"MASTER_SLAVE",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m","s"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

(2)读写分离(一主一从,一备)(m是主,s是从,b是备)

{
  "clusterType":"MASTER_SLAVE",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m","b"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

(4)MHA(一主一从,一备)(m是主,s是从,b是备,READ_ONLY判断主)

{
  "clusterType":"MHA",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m","b"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

(5)MGA(一主一从,一备)(m是主,s是从,b是备,READ_ONLY判断主)

{
  "clusterType":"MGA",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m","b"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

(6)GARELA_CLUSTER(一主一从,一备)(m是主,s是从,b多主)

{
  "clusterType":"GARELA_CLUSTER",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "m","b"
  ],
  "maxCon":200,
  "name":"prototype",
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "s"
  ],
  "switchType":"SWITCH"
}

第四章 垂直拆分——分库

一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同 的数据库上面,这样也就将数据或者说压力分担到不同的库上面,如下图:

系统被切分成了,用户,订单交易,支付几个模块。

5.1 如何分库

一个问题:在两台主机上的两个数据库中的表,能否关联查询?

答案:不可以关联查询

分库的原则: 有紧密关联关系的表应该在一个库里,相互没有关联关系的表可以分到不同的库里。

#客户表 rows:20万
CREATE TABLE customer(
  id INT AUTO_INCREMENT,
  NAME VARCHAR(200),
  PRIMARY KEY(id)
);
#订单表 rows:600万
CREATE TABLE orders(
  id INT AUTO_INCREMENT,
  order_type INT,
  customer_id INT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id)
);
#订单详细表 rows:600万
CREATE TABLE orders_detail(
  id INT AUTO_INCREMENT,
  detail VARCHAR(2000),
  order_id INT,
  PRIMARY KEY(id)
);
#订单状态字典表 rows:20
CREATE TABLE dict_order_type(
  id INT AUTO_INCREMENT,
  order_type VARCHAR(200),
  PRIMARY KEY(id)
);

以上四个表如何分库?客户表分在一个数据库,另外三张都需要关联查询,分在另外一个数据库。

5.2 如何分表

1、选择要拆分的表

MySQL单表存储数据条数是有瓶颈的,单表达到1000万条数据就达到了瓶颈,会影响查询效率,需要进行水平拆分(分表)进行优化。

例如:例子中的orders、orders…detail都已经达到600万行数据,需要进行分表优化。
2、 分表字段

以 orders 表为例,可以根据不同自字段进行分表

编号 分表字段 效果
1 id(主键、 或创建时间) 查询订单注重时效,历史订单被查询的次数少,如此分片会造成一个节点访问多,一个访问少,不平均。
2 customer_id(客户 id) 根据客户 id 去分,两个节点访问平均,一个客户的所 有订单都在同一个节点

5.3 实现分库分表

首先,不需要双主双从了

删掉数据源


Mycat2 一大优势就是可以在终端直接创建数据源、集群、库表,并在创建时指定分库、分表。与1.6版本比大大简化了分库分表的操作

1、添加数据库、存储数据源

/*+mycat:.createDataSource{
"name" :" dw0" , -
"url" :" jdbc:mysql://192.168.253.139:3306",
"user":"root", 
"password":"123456"
}*/ ;
/*+mycat:createDataSource{
"name" :"dr0" , 
"url" :"jdbc:mysql://192.168.253.139:3306",
"user":"root", 
"password" :"123456"
}*/ ;
/*+mycat:.createDataSource{
"name" :" dw1" , -
"url" :" jdbc:mysql://192.168.253.140:3306",
"user":"root", 
"password":"123456"
}*/ ;
/*+mycat:createDataSource{
"name" :"dr1" , 
"url" :"jdbc:mysql://192.168.253.140:3306",
"user":"root", 
"password" :"123456"
}*/ ;

手动创建

{
  "dbType":"mysql",
  "idleTimeout":60000,
  "initSqls":[],
  "initSqlsGetConnection":true,
  "instanceType":"READ_WRITE",
  "maxCon":1000,
  "maxConnectTimeout":3000,
  "maxRetryCount":5,
  "minCon":1,
  "name":"dw0",  #注意
  "password":"123456",
  "type":"JDBC",
  "url":"jdbc:mysql://192.168.253.139:3306?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",  #注意主机ip 注意不指定库
  "user":"root",
  "weight":0
}


2、添加集群配置

把新添加的数据源配置成集群

#//在mycat终端输入
/*! mycat:createCluster{"name":"c0"," masters": ["dw0"],"replicas":["dr0"]}*/; 
/*!-mycat:createCluster{"name":"c1", "masters": ["dw1"],"replicas":["dr1"]}*/ ;
#可以查看集群配置信息
cd /usr/local/mycat/conf/clusters

手动配置

  "clusterType":"MASTER_SLAVE",
  "heartbeat":{
    "heartbeatTimeout":1000,
    "maxRetry":3,
    "minSwitchTimeInterval":300,
    "slaveThreshold":0
  },
  "masters":[
    "dw0"
  ],
  "maxCon":200,
  "name":"c0", #注意
  "readBalanceType":"BALANCE_ALL",
  "replicas":[
    "dr0"
  ],
  "switchType":"SWITCH"
}


启动 Mycat并登录

./mycat console

3、创建全局表

#添加数据库db1  主机2也要创建
CREATE DATABASE db1;



vim db1.schema.json

#在建表语句中加上关键字BROADCAST(广播,即为全局表)
CREATE TABLE db1.`travelrecord` (
  `id` bigint NOT NULL AUTO_INCREMENT,
  `use_id` varchar(100) DEFAULT NULL,
  `traveldate` date DEFAULT NULL,
  `fee` decimal(10,0) DEFAULT NULL,
  `days` int DEFAULT NULL,
  `blob` longblob, 
  PRIMARY KEY(`id`) , 
  KEY `id` (`id`) 
)ENGINE=InnoDB DEFAULT CHARSET=utf8 BROADCAST;
#进入相关目录查看schema 配置


4、 创建分片表(分库分表)

#在 Mycat终端直接运行建表语句进行数据分片
CREATE TABLE db1.orders(
  id BIGINT NOT NULL AUTO_INCREMENT,
  order_type INT,
  customer_id INT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8
dbpartition BY mod_hash(customer_id) tbpartition BY mod_hash(customer_id) tbpartitions 1 dbpartitions 2;
#数据库分片规则,表分片规则,以及各分多少片
mysql> use TESTDB;
#在 mycat 里向 orders 表插入数据, INSERT 字段不能省略
INSERT INTO orders(id,order_type,customer_id,amount) VALUES (1,101,100,100100);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(2,101,100,100300);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(3,101,101,120000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(4,101,101,103000);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(5,102,101,100400);
INSERT INTO orders(id,order_type,customer_id,amount) VALUES(6,102,100,100020);
#同样可以查看生成的配置信息
#进入相关目录查看schema配置
vim db1.schema.json 


查看数据库可见,分片数据

主机1

主机2


在 Mycat终端查询依然可以看到全部数据

Mycat

5、创建ER表

与分片表关联的表如何分表,也就是ER表如何分表,如下

#在 Mycat终端直接运行建表语句进行数据分片
CREATE TABLE orders_detail(
  `id` BIGINT NOT NULL AUTO_INCREMENT,
  detail VARCHAR(2000),
  order_id INT,
  PRIMARY KEY(id)
)ENGINE=INNODB DEFAULT CHARSET=utf8
dbpartition BY mod_hash(order_id) tbpartition BY mod_hash(order_id) tbpartitions 1 dbpartitions 2 ; 
INSERT INTO orders_detail(id,detail,order_id) values(1,'detail1',1);
INSERT INTO orders_detail(id,detail,order_id) VALUES(2,'detail1',2);
INSERT INTO orders_detail(id,detail,order_id) VALUES(3,'detail1',3);
INSERT INTO orders_detail(id,detail,order_id) VALUES(4,'detail1',4);
INSERT INTO orders_detail(id,detail,order_id) VALUES(5,'detail1',5);
INSERT INTO orders_detail(id,detail,order_id) VALUES(6,'detail1',6);

mycat


主机1

不是按照想象的126划得


主机2

#上述两表具有相同的分片算法,但是分片字段不相同
#Mycat2在涉及这两个表的join分片字段等价关系的时候可以完成join的下推
#Mycat2无需指定ER表,是自动识别的,具体看分片算法的接口
#查看配置的表是否具有ER关系,使用/*+·mycat:showErGroup{}*/

#group_id表示相同的组,该组中的表具有相同的存储分布
#运行关联查询语句
Select o.*,od.detail from orders o inner join orders_detail od on o.id=od.order_id;



5.4-常用分片规则

1、分片算法简介

Mycat2支持常用的(自动)HASH型分片算法也兼容1.6的内置的(cobar)分片算法.

HASH型分片算法默认要求集群名字以c为前缀,数字为后缀, c0就是分片表第一个节点, c1就是第二个节点.该命名规则允许用户手动改变

2、Mycat2 与1.x版本区别

Mycat2-Hash型分片算法多数基于MOD_HASH(MOD对应.JAVA的%运算),实际上是取余运算。
Mycat2-Hash型分片算法对于值的处理,总是把分片值转换到列属性的数据类型再运算。

而1.x系列的分片算法统一转换到字符串类型再运算且只能根据一个分片字段计算出存储节点下标。

Mycat2-Hash型分片算法适用于等价条件查询。

而1.x系列由于含有用户经验的路由规则。1.x系列的分片规则总是先转换成字符串再运算。


3、分片规则与适用性

分片算法 描述 分库 分表 数值类型
MOD_HASH 取模哈希 数值,字符串口
UNI_HASH2 取模哈希 数值,字符串
RIGHT_SHIFT 右移哈希 数值
RANGE_HASH 两字段其一取模 数值,字符串
YYYYMM 按年月哈希 DATE,DATETIME
YYYYDD 按年日哈希 DATE,DATETIME
HASH 取模哈希 数值,字符串,如果不是,则转换成字符串
MM 按月哈希 DATE,DATETIME
DD 按日期哈希 DATE,DATETIME
MMDD 按月日哈希 DATE,DATETIME
WEEK 按周哈希 DATE,DATETIME
STR_HASH 字符串哈希 字符串
相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
Java 关系型数据库 MySQL
Mycat2【java提高】3
Mycat2【java提高】3
116 0
|
SQL 算法 Java
Mycat2【java提高】5
Mycat2【java提高】5
216 0
|
负载均衡 关系型数据库 MySQL
Mycat2【java提高】2
Mycat2【java提高】2
209 0
|
Java 中间件 关系型数据库
Mycat2【java提高】1
Mycat2【java提高】1
189 0
|
4天前
|
监控 Java
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
41 17
|
14天前
|
Java
Java—多线程实现生产消费者
本文介绍了多线程实现生产消费者模式的三个版本。Version1包含四个类:`Producer`(生产者)、`Consumer`(消费者)、`Resource`(公共资源)和`TestMain`(测试类)。通过`synchronized`和`wait/notify`机制控制线程同步,但存在多个生产者或消费者时可能出现多次生产和消费的问题。 Version2将`if`改为`while`,解决了多次生产和消费的问题,但仍可能因`notify()`随机唤醒线程而导致死锁。因此,引入了`notifyAll()`来唤醒所有等待线程,但这会带来性能问题。
Java—多线程实现生产消费者
|
16天前
|
安全 Java Kotlin
Java多线程——synchronized、volatile 保障可见性
Java多线程中,`synchronized` 和 `volatile` 关键字用于保障可见性。`synchronized` 保证原子性、可见性和有序性,通过锁机制确保线程安全;`volatile` 仅保证可见性和有序性,不保证原子性。代码示例展示了如何使用 `synchronized` 和 `volatile` 解决主线程无法感知子线程修改共享变量的问题。总结:`volatile` 确保不同线程对共享变量操作的可见性,使一个线程修改后,其他线程能立即看到最新值。
|
16天前
|
消息中间件 缓存 安全
Java多线程是什么
Java多线程简介:本文介绍了Java中常见的线程池类型,包括`newCachedThreadPool`(适用于短期异步任务)、`newFixedThreadPool`(适用于固定数量的长期任务)、`newScheduledThreadPool`(支持定时和周期性任务)以及`newSingleThreadExecutor`(保证任务顺序执行)。同时,文章还讲解了Java中的锁机制,如`synchronized`关键字、CAS操作及其实现方式,并详细描述了可重入锁`ReentrantLock`和读写锁`ReadWriteLock`的工作原理与应用场景。
|
17天前
|
安全 Java 编译器
深入理解Java中synchronized三种使用方式:助您写出线程安全的代码
`synchronized` 是 Java 中的关键字,用于实现线程同步,确保多个线程互斥访问共享资源。它通过内置的监视器锁机制,防止多个线程同时执行被 `synchronized` 修饰的方法或代码块。`synchronized` 可以修饰非静态方法、静态方法和代码块,分别锁定实例对象、类对象或指定的对象。其底层原理基于 JVM 的指令和对象的监视器,JDK 1.6 后引入了偏向锁、轻量级锁等优化措施,提高了性能。
42 3
|
17天前
|
存储 安全 Java
Java多线程编程秘籍:各种方案一网打尽,不要错过!
Java 中实现多线程的方式主要有四种:继承 Thread 类、实现 Runnable 接口、实现 Callable 接口和使用线程池。每种方式各有优缺点,适用于不同的场景。继承 Thread 类最简单,实现 Runnable 接口更灵活,Callable 接口支持返回结果,线程池则便于管理和复用线程。实际应用中可根据需求选择合适的方式。此外,还介绍了多线程相关的常见面试问题及答案,涵盖线程概念、线程安全、线程池等知识点。
100 2
下一篇
开通oss服务