Day132.Mysql集群、MyCat数据库中间件、读写分离、分库分表、E-R | 全局表、全局序列(分布式ID)

目录

一、Mysql 集群 主从同步

二、MyCat 数据库中间件

1、安装、配置、使用

日志的种类

架构方案

2、搭建读写分离、分库分表

1. 分库 — 垂直拆分 (拆分库中的表)

​编辑​编辑

2. 分表 — 水平拆分 (拆分表中的行)

3. E-R表 (JOIN)

4. 全局表 (本地JOIN)

3、全局序列 (分布式id)


熟悉mysql 集群架构方案,技术选型,了解mha,mmm等解决方案。

集群怎么搭的?一个master 三个slave,数据量有点大,单机大概5、6百万条,修改的不是很多,但是读的挺多,我们的架构比较简单,直接读数据库,最简单的方法就是多搞几个可读服务器。

一、阿里开发规约

小数类型使用decimal,禁止使用flloat和double

count(*) 会统计值为NULL的行,而count(列名)不会统计此列为NULL值的行

不得使用外键与级联;高并发集群下存在数据更新风暴的风险。

JOIN禁止超过三张表,多表关联查询时,保证被关联的字段需要有索引。

页面搜索严禁左模糊或全模糊,如果需要,把表导到搜索引擎中去查(倒排索引)

利用覆盖索引来进行查询操作,避免回表(不要SELECT *)

SQL性能优化至少要达到range级别

一、Mysql 集群 主从同步

master负责写操作,slave 负责读操作

  • MySQL复制三步骤:

1 master将写操作记录到二进制日志(binary log)。这些记录过程叫做二进制日志事件,binary log events;

2 slave将master的binary log events拷贝到它的中继日志(relay log)

从服务器I/O线程将主服务器的二进制日志读取过来记录到从服务器本地文件,然后SQL线程会读取relay-log日志的内容并应用到从服务器,从而使从服务器和主服务器的数据保持一致!

3 slave重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的,而且重启后从接入点开始复制。

1. 克隆虚拟机,修改ip

vim  /etc/sysconfig/network-scripts/ifcfg-ens33

基本原则:

1. 每个slave只有一个master;每个master可以有多个salve

2. 每个slave只能有一个唯一的服务器ID

主节点修改 vi /etc/my.cnf

server-id=1
log-bin=mysql-bin
binlog-ignore-db=mysql
binlog-ignore-db=infomation_schema
binlog-do-db=mytestdb
binlog_format=STATEMENT

2. 从机配置文件修改 vi /etc/my.cnf

server-id=2
relay-log=mysql-relay

3. 修改uuid,随便改一下 两个mysql 改一个就行

vi /var/lib/mysql/auto.cnf

主从机重启systemctl restart mysqld

4. 在 master 上添加Mysql用户、权限

创建用户
CREATE USER slave IDENTIFIED BY 'sgg1minggE@666';
授权
GRANT ALL PRIVILEGES ON *.* TO 'slave';
flush privileges;

添加授权用户 之后,建议在远程工具里测试一下

2、修改加密规则(可以直接复制)
ALTER USER 'slave'@'%' IDENTIFIED BY 'password' PASSWORD EXPIRE NEVER;
ALTER USER 'slave'@'%' IDENTIFIED WITH mysql_native_password BY 'password';
3、刷新权限(可以直接复制)
FLUSH PRIVILEGES;
4、重置密码
alter user 'slave'@'%' identified by '123456';

  • 集群配置 

获取主节点的记录offset

show master status;

执行完此步骤后不要再操作主服务器MYSQL,防止主服务器状态值变化

主被直间关联

修改之后,完整的三行一起在 slave 执行。

CHANGE MASTER TO MASTER_HOST='主机ip地址',
MASTER_USER='用户',MASTER_PASSWORD='密码',
MASTER_LOG_FILE='mysql-bin.具体数字',MASTER_LOG_POS=具体值;

CHANGE MASTER TO MASTER_HOST='192.168.86.87',
MASTER_USER='slave',MASTER_PASSWORD='123456',
MASTER_LOG_FILE='mysql-bin.000002',MASTER_LOG_POS=1019;

开启主从同步

start slave;

停止同步

stop slave;

查看集群状态

show slave status\G;

 

主机新建库、新建表、insert记录,从机复制

CREATE DATABASE mytestdb;

use mytestdb;
CREATE TABLE mytbl(id INT,NAME VARCHAR(16));
INSERT INTO mytbl VALUES(1, 'zhang3');
INSERT INTO mytbl VALUES(2, 'li4');

从机slave 中也有了数据

二、MyCat 数据库中间件

Mycat是数据库中间件。

可以在读写操作之间加入一个组件,把它们包容起来;通过虚拟数据库链接真实数据库

官网:Mycat1.6

1. 读写分离

2. 数据分片:垂直拆分(分库)、水平拆分(分表)、垂直+水平拆分(分库分表)
3. 多数据源整合

1、安装、配置、使用

下载最新驱动:Index of /  ; 一定要下载新版本!!

1. 克隆一个有jdk1.8、mysql8.0的虚拟机,修改端口

vim  /etc/sysconfig/network-scripts/ifcfg-ens33

1. 解压缩文件拷贝到linux下

解压:tar zxvf Mycat-server-1.6.7.6-release-20220524173810-linux.tar.gz

移动到user/local:mv mycat/ /usr/local/

2. 添加Mycat用户,用来连接物理mysql服务器。

(master) 

CREATE USER mycat IDENTIFIED BY '123456';

GRANT ALL PRIVILEGES ON *.* TO 'mycat';

FLUSH PRIVILEGES;

修改加密方式 (没权限登到mycat用户操作)

ALTER USER 'mycat'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

重置密码

alter user 'mycat'@'%' identified by '123456';

(slave) 

因为之前配置了集群,87添加用户,88mysql也会添加,只需要修改权限即可

GRANT ALL PRIVILEGES ON *.* TO 'mycat';

FLUSH PRIVILEGES;

修改加密方式 (没权限登到mycat用户操作)

ALTER USER 'mycat'@'%' IDENTIFIED WITH mysql_native_password BY '123456';

重置密码

alter user 'mycat'@'%' identified by '123456';

3. 修改myCat 配置文件 server.xml

4. 修改myCat 配置文件 schema.xml

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 这是一个虚拟数据库,客户端连得都是这个库 -->
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
        </schema>
<!--  物理库的数据源配置 mytestdb 真实的数据库-->
        <dataNode name="dn1" dataHost="host1" database="mytestdb" />
<!-- dataHost 和后端 真实 的物理mysql服务器 相关的连接配置,地址 密码等 -->
        <dataHost name="host1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>


		<!-- 数据写入的服务器 insert ,delete ,update -->
                <writeHost host="hostM1" url="jdbc:mysql://192.168.86.87:3306" user="mycat" password="123456">
                        <!-- can have multi read hosts -->
                        <readHost host="hostS1" url="jdbc:mysql://192.168.86.88:3306" user="mycat" password="123456" />
                </writeHost>
        </dataHost>
</mycat:schema>

5. 启动myCat

6. 复制一个窗口(会话),登录myCat (8066)

mysql -umycat -p -P8066 -h 192.168.86.89

7. 观察主从同步

use TESTDB;

show tables;

select * from mytbl; #查询的哪个库?{应该是主机}

修改从机的数据,再次查询!

插入测试

insert into mytbl values(111,"222");

对虚拟数据进行的所有操作,都会指向物理数据库

日志的种类

mysql 靠binlog去记录每一条对数据库操作

  • undolog 数据修改前

记录数据修改前的值,update类似的操作,方便后续出问题后可以恢复到修改前的状态

  • redolog 数据修改后

数据已经成功提交正在处理中,还没有真正写入磁盘,此时如果断电,可以通过redolog恢复

  • binlog 数据记录完

记录真正持久化后的日志,对应到idb文件。

在服务器刚刚开始运行的时候,开启了binlog,一旦有一天服务器里的数据丢失了,还可以通过binlog日志,逐条执行,就可以恢复数据了。

log和sql是有区别的

UndoLog记录的是在数据被修改之的值

RedoLog记录的是在数据被修改之的值

二者记录都发生在提交数据、存盘

BinLog记录所有木已成舟的确定性变化。

架构方案

One master and Muti salve 一主多备

一般用来做读写分离的,master 写,其他 slave 读,这种架构最大问题 I/O 压力集中 在 Master 上<多台同步影响 IO>

M-S-S

使用一台 slave 作为中继,分担 Master 的压力,slave 中继需要开启 bin-log,并配置 log-slave-updates Slave 中继可使用 Black-hole 存储引擎,不会把数据存储到磁盘,只记录二进制日志。

M-M 双主互备 (互为主从)

HA

很多人误以为这样可以做到 MySQL 负载均衡,实际没什么好处,每个服务器需要做同样的同步更新,破坏了事物的隔离性和数据的一致性。

M-M-M

监控三台机器互相作对方的 master 天生的缺陷:复制延迟,slave 上同步要慢于 master,如果大并发的情况那延迟更严重

MHA

Perl语言写的,开源的MYSQL故障切换方案;全称:Master High Availability,故障切换时间10-30s

MMM

MMM即Multi-Master Replication Manager for MySQL:mysql多主复制管理器,基于perl实现,关于mysql主主复制 配置的监控、故障转移和管理的一套可伸缩的脚本套件(在任何时候只有一个节点可以被写入

2、搭建读写分离、分库分表

1. 修改schema.xml配置文件

默认:balance="0"

(1)balance="0", 不开启读写分离机制,所有读操作都发送到当前可用的 writeHost 上。
(2)balance="1",全部的 readHost 与 stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且 M1 与 M2 互为主备),正常情况下,M2,S1,S2 都参与 select 语句的负载均衡。
(3)balance="2",所有读操作都随机的在 writeHost、readhost 上分发。
(4)balance="3",所有读请求随机的分发到 readhost 执行,writerHost 不负担读压力


修改一个数据库字段,可以看到随机读效果
 

 修改 schema.xml文件

1. 分库 — 垂直拆分 (拆分库中的表)

IO密集型 ->硬盘:Mysql(数据)、Redis(日志)、文件服务器

计算密集型->cpu:微服务、Controller(单例)

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

1. 先停止主从同步:stop slave;

2. 修改配置文件 (大换血)

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
		<!-- 这是一个虚拟数据库,客户端连得都是这个库 -->
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
			<table name="customer" dataNode="dn2" ></table>
        </schema>
			<!--  物理库的数据源配置 mytestdb 真实的数据库-->
			<dataNode name="dn1" dataHost="host1" database="orders" />
			<dataNode name="dn2" dataHost="host2" database="orders" />
		
		<!-- dataHost 和后端 真实 的物理mysql服务器 相关的连接配置,地址 密码等 -->
		<dataHost name="host1" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM1" url="jdbc:mysql://192.168.86.87:3306" user="mycat" password="123456">
                </writeHost>
        </dataHost>
        <dataHost name="host2" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="hostM2" url="jdbc:mysql://192.168.86.88:3306" user="mycat" password="123456">
                </writeHost>
        </dataHost>
</mycat:schema>

3. 重启myCat,再次查询

4. 创建数据库

#在主从机 dn1、dn2 上分别创建数据库orders

CREATE DATABASE orders;

5. 在myCat执行建表语句

#客户表  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)
);

6. 查看:master(87) 上有三张表,slave(88)上有一张表 

 myCat的BUG:建出来表是大写的,并且区分大小写;改成小写就行。

 阿里框架很多刷KPI,注册中心 Eureka;配置中心 阿波罗

2. 分表 — 水平拆分 (拆分表中的行)

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

1. 修改schema.xml;添加表分配的策略

            <table name="orders" dataNode="dn1,dn2"  rule="xxoo_role" ></table>

2. 修改rule.xml 112 行左右;修改分片的数据库节点数,添加rule配置

	<tableRule name="xxoo_role">
		<rule>
			<columns>customer_id</columns>
			<algorithm>mod-long</algorithm>
	    </rule>
    </tableRule>

3. 在 slave 中建表

CREATE TABLE orders(
    id INT AUTO_INCREMENT,
    order_type INT,
    customer_id INT,
    amount DECIMAL(10,2),
    PRIMARY KEY(id)  
); 

4. 访问Mycat灌数据实现分片

在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);


myCat以customer_id区别写入了哪台机器
 

3. E-R表 (JOIN)

虽然分好了表,但是不支持JOIN分表查询;

我们要对orders_detail也要进行分片操作。Join的原理如下图:

1. 修改schema.xml配置文件,添加配置

			<table name="orders" dataNode="dn1,dn2"  rule="xxoo_role" autoIncrement="true" fetchStoreNodeByJdbc="true">
				<childTable name="orders_detail" primaryKey="id" joinKey="order_id" parentKey="id"/>
			</table>

2. 在 slave 创建orders_detail表

CREATE TABLE orders_detail(
    id INT AUTO_INCREMENT,
    detail VARCHAR(2000),
    order_id INT,
    PRIMARY KEY(id)
);

3. 访问Mycat向orders_detail表插入数据

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);

4. 再次JOIN测试

select * from orders t1 left join orders_detail t2 on t2.id = t2.order_id;

4. 全局表 (本地JOIN)

全局表的插入、更新操作会实时在所有节点上执行,保持各个分片的数据一致性;可以跟任何一个表进行 JOIN 操作;(参考数据字典)

用来方便JOIN,myCat不支持跨库JOIN,也不建议

1. schema.xml添加配置

<table name="dict_order_type" dataNode="dn1,dn2" type="global" ></table>

2. slave 创建dict_order_type表

CREATE TABLE dict_order_type(
    id INT AUTO_INCREMENT,
    order_type VARCHAR(200),
    PRIMARY KEY(id)
);

3. 访问Mycat向dict_order_type表插入数据

INSERT INTO dict_order_type(id,order_type) VALUES(101,'type1');
INSERT INTO dict_order_type(id,order_type) VALUES(102,'type2');

master,slave同时添加了字段

3、全局序列 (分布式id)

分布式ID在极高的并发下才需要使用。

分布式环境下,实现分库分表的情况后,数据库自增主键已无法保证自增主键的全局唯一。为此,Mycat 提供了全局 sequence,并且提供了包含本地配置和数据库配置等多种实现方式

1. 本地文件  (没人用)

可以由myCat负责生成 全局ID,存入文件统一管理

优点:本地加载,读取速度较快
缺点:抗风险能力差,Mycat所在主机宕机后,无法读取本地文件。

2. 时间戳方式 (uuid | 雪花算法;主流;美团在用)

全局序列ID=  64 位二进制  (42(毫秒)+5(机器 ID)+5(业务编码)+12(重复累加) 换算成十进制为 18 位数的 long 类型,每毫秒可以并发 12 位二进制的累加。

优点:配置简单
缺点:无逻辑,无法排序,无法作为聚簇索引使用;18位ID过长

牺牲了有序性,极快速的生成;

3. 自主生成全局序列 (意淫出来的,没人用)

搭建一个Redis服务器专门存储ID,利用redis的单线程原子性(先进先出)来生成唯一ID

但,自主生成需要单独在工程中用java代码实现,增加了分布式项目的复杂性

4. 自主生成全局序列  (有人用)

根据数据库建立字符串索引,可使用步进实现。只能在服务器个数确定时使用。

5. 数据库的方式  (没人用)

通过存储过程创建有序id 存储过程太麻烦,略。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


学习编程是顺着互联网的发展潮流,是一件好事。新手如何学习编程?其实不难,不过在学习编程之前你得先了解你的目的是什么?这个很重要,因为目的决定你的发展方向、决定你的发展速度。
IT行业是什么工作做什么?IT行业的工作有:产品策划类、页面设计类、前端与移动、开发与测试、营销推广类、数据运营类、运营维护类、游戏相关类等,根据不同的分类下面有细分了不同的岗位。
女生学Java好就业吗?女生适合学Java编程吗?目前有不少女生学习Java开发,但要结合自身的情况,先了解自己适不适合去学习Java,不要盲目的选择不适合自己的Java培训班进行学习。只要肯下功夫钻研,多看、多想、多练
Can’t connect to local MySQL server through socket \'/var/lib/mysql/mysql.sock问题 1.进入mysql路径
oracle基本命令 一、登录操作 1.管理员登录 # 管理员登录 sqlplus / as sysdba 2.普通用户登录
一、背景 因为项目中需要通北京网络,所以需要连vpn,但是服务器有时候会断掉,所以写个shell脚本每五分钟去判断是否连接,于是就有下面的shell脚本。
BETWEEN 操作符选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。
假如你已经使用过苹果开发者中心上架app,你肯定知道在苹果开发者中心的web界面,无法直接提交ipa文件,而是需要使用第三方工具,将ipa文件上传到构建版本,开...
下面的 SQL 语句指定了两个别名,一个是 name 列的别名,一个是 country 列的别名。**提示:**如果列名称包含空格,要求使用双引号或方括号:
在使用H5混合开发的app打包后,需要将ipa文件上传到appstore进行发布,就需要去苹果开发者中心进行发布。​
+----+--------------+---------------------------+-------+---------+
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 nu...
第一步:到appuploader官网下载辅助工具和iCloud驱动,使用前面创建的AppID登录。
如需删除表中的列,请使用下面的语法(请注意,某些数据库系统不允许这种在数据库表中删除列的方式):
前不久在制作win11pe,制作了一版,1.26GB,太大了,不满意,想再裁剪下,发现这次dism mount正常,commit或discard巨慢,以前都很快...
赛门铁克各个版本概览:https://knowledge.broadcom.com/external/article?legacyId=tech163829
实测Python 3.6.6用pip 21.3.1,再高就报错了,Python 3.10.7用pip 22.3.1是可以的
Broadcom Corporation (博通公司,股票代号AVGO)是全球领先的有线和无线通信半导体公司。其产品实现向家庭、 办公室和移动环境以及在这些环境...
发现个问题,server2016上安装了c4d这些版本,低版本的正常显示窗格,但红色圈出的高版本c4d打开后不显示窗格,
TAT:https://cloud.tencent.com/document/product/1340