篇幅较长,主要分为mysql和Redis两部分。找想要的部分可见目录食用。。
目录
什么是集群?为什么要集群?
1.1 数据库主要分为两大类:关系型数据库与 NoSQL 数据库
1.2 为什么还要用 NoSQL 数据库呢?
-------------------华丽分割线--------------
一、关系型数据库MySQL
1.部署mysql
1.1安装依赖
1.2下载解压源码包
1.3源码编译安装
1.4部署mysql
测试安装效果:
集群方式
mysql的主从复制模式:
异步复制
实验1:添加slave1
1.环境配置
编辑
2.开启slave,测试:
实验2:在有数据的情况下添加slave2
1.环境配置
2.测试
实验3:延迟复制
实验4:慢查询日志
编辑
实验5:并行复制
测试:
半同步复制
1.gtid模式
2.半同步模式
组复制(高可用)
组复制的流程图:
实验
1.初始化数据库数据,防止出现问题
2.向本地解析文件中配置其他几台主机内容
3.配置sql内容
4.配置另外两台
5测试
MySQL路由
MySQL-router的部署方式
测试
MySQL高可用--MHA
1.MHA简介
2.MHA的部署
(1)搭建主两从架构
(2)安装MHA所需要的软件
编辑
(3)配置MHA管理环境
1.生成配置目录和配置文件
2.编写一个配置文件
2.检测配置
3.MHA故障切换
(1)master未出现故障手动切换
编辑
(2)master出现故障手动切换
编辑
(3)自动切换
4.添加VIP功能
二、Redis非关系型数据库
1.Redis特点
2.Redis应用场景
3.缓存的实现流程
数据更新操作流程
数据读操作流程
4.Redis的安装
4.1.rpm包方式安装
4.2.源码安装
4.3.基本操作
(1)查看配置(红色是命令,黄色是结果)
(2)写入和读取数据
(3)选择数据库 Redis中有0-15个数据库
(4)改变键名
(5)设定数据过期时间 / 持久化(设置时间版)保持
(6)删除
(7)判断key的存在
(8)清空当前库
(9)清空所有库
5.Redis主从复制
5.1.环境
5.2.配置主从同步
(1)修改master节点的配置文件
(2)配置slave节点
(3)测试
6.Redis的哨兵(高可用)
6.1.哨兵的实验过程
6.2架构缺陷
7.Redis Cluster(无中心化设计)
7.1.工作原理
7.2创建Redis Cluster的要求
7.3部署Redis Cluster
7.4集群扩容
7.5集群维护
总结
什么是集群?为什么要集群?
- 通俗一点来说,就是让若干台计算机联合起来工作 (服务),可以是并行的,也可以是做备份。
- 数据库集群的特征就是 有多台机器,这多台机器上都有数据库, 这些数据库的数据是完全一样的,即相当于一套数据的多个副本。集群就是要保证这些副本的实时或准时实(可以延时一会)的同步,即如果一台机器上的数据更改时,集群系统要保证这个更改实时或准时实的应用到所有的机器上,实现数据同步。
集群主要解决两个问题:
- 负载均衡:这个主要是解决访问量大的问题。一台机器的读写能力是有限的,当同时有大量用户访问的时候,仅一台机器可能就会因负载过大而垮掉。而使用集群后,集群系统会将访问量均衡到每台机器上,也即多台机器分担了访问量,这就达到了负载均衡的目的。
- 当机:当只有一台机器时,如果这台机器因意外当机会需要停机维护,那么此时系统就不能访问,对于一些使用量大,使用频繁的系统而言,这样是肯定不行的。如果使用集群,只有集群中有一台机器还在运行,就能让系统继续运行下去,而且对于重新启动的机器,能很快的同步在停机时间用户所做的更改。我的当前公司很喜欢用顶这个词,当一台机器垮掉时,能立马有另一台机器顶上。
1.1 数据库主要分为两大类:关系型数据库与 NoSQL 数据库
- 关系型数据库,是建立在关系模型基础上的数据库,其借助于集合代数等数学概念和方法来处理数据库 中的数据主流的 MySQL、Oracle、MS SQL Server 和 DB2 都属于这类传统数据库。
- NoSQL 数据库,全称为 Not Only SQL,意思就是适用关系型数据库的时候就使用关系型数据库,不适 用的时候也没有必要非使用关系型数据库不可,可以考虑使用更加合适的数据存储。主要分为临时性键 值存储(memcached、Redis)、永久性键值存储(ROMA、Redis)、面向文档的数据库 (MongoDB、CouchDB)、面向列的数据库(Cassandra、HBase),每种 NoSQL 都有其特有的使用 场景及优点。
1.2 为什么还要用 NoSQL 数据库呢?
主要是由于随着互联网发展,数据量越来越大,对性能要求越来越高,传统数据库存在着先天性的缺 陷,即单机(单库)性能瓶颈,并且扩展困难。这样既有单机单库瓶颈,却又扩展困难,自然无法满足 日益增长的海量数据存储及其性能要求,所以才会出现了各种不同的 NoSQL 产品,NoSQL 根本性的优势在于在云计算时代,简单、易于大规模分布式扩展,并且读写性能非常高
-------------------华丽分割线--------------
实验环境:
- vmware支持的redhat7.9虚拟机若干(做MySQL)9.4虚拟机若干台(做Redis)
- 虚拟机可联网,无其他操作的全新环境
- 虚拟机每一个都可以进行yum下载,拥有顺畅下载的本地仓库
- 关闭防火墙,selinux
一、关系型数据库MySQL
如果你安装的redhat7.9是带图形化的可以利用以下命令禁掉:
systemctl set-default multi-user.target #这条命令会永久关闭图形化
reboot #重启即可
1.部署mysql
- 在企业中90%的服务器操作系统均为Linux
- 在企业中对于Mysql的安装通常用源码编译的方式来进行(源码编译相比软件安装其可拓展性,功能性更强,对于使用者来说也更加灵活)
步骤:
- 安装依赖
- 下载解压源码包
- 源码编译安装mysql
- 使用部署
1.1安装依赖
yum install cmake gcc-c++ openssl-devel \ ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64 -y
1.2下载解压源码包
可自行去官网查找包,用xftp传输(速度快)
1.3源码编译安装
这一步时间比较漫长,稍作等待
[root@mysql-node10 mysql-5.7.44]# cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \ #指定安装路径
-DMYSQL_DATADIR=/data/mysql \ #指定数据目录
-DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock \ #指定套接字文件
-DWITH_INNOBASE_STORAGE_ENGINE=1 \ #指定启用INNODB存储引擎,默认用myisam
-DWITH_EXTRA_CHARSETS=all \ #扩展字符集
-DDEFAULT_CHARSET=utf8mb4 \ #指定默认字符集
-DDEFAULT_COLLATION=utf8mb4_unicode_ci \ #指定默认校验字符集
-DWITH_BOOST=/root/mysql-5.7.44/boost/boost_1_59_0/ #指定c++库依赖
[root@mysql-node10 mysql-5.7.44]# make -j2 #-j2 表示有几个核心就跑几个进程
[root@mysql-node10 mysql-5.7.44# make install
出现以下画面说明就成功下载中了:
这一步出现问题的小伙伴看这里:
切记要删除缓存再重新检测
1.4部署mysql
mkdir /data/mysql/
chown -R /data/mysql/
#生成启动脚本
[root@node10 ~]# cd /usr/local/mysql/support-files/
[root@node10 support-files]# cp mysql.server /etc/init.d/mysqld
#修改环境变量
[root@node10 ~]# vim ~/.bash_profile
export PATH=$PATH:/usr/local/mysql/bin
[root@node10 ~]# source ~/.bash_profile
#生成配置文件
[root@node10 my.cnf.d]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql #指定数据目录
socket=/data/mysql/mysql.sock #指定套接字
symbolic-links=0 #数据只能存放到数据目录中,禁止链接到数据目录
#数据库初始化建立mysql基本数据
[root@node10 ~]# mysqld --initialize --user=mysql
[root@node10 ~]# /etc/init.d/mysqld start
#数据库安全初始化
[root@node10 ~]# mysql_secure_installation
Enter password for user root: #输入当前密码
New password: #输入新密码
Re-enter new password: #重复密码
Press y|Y for Yes, any other key for No: no #是否启用密码插件
Change the password for root ? ((Press y|Y for Yes, any other key for No) : no
#是否要重置密码
Remove anonymous users? (Press y|Y for Yes, any other key for No) : y
Disallow root login remotely? (Press y|Y for Yes, any other key for No) : y
Remove test database and access to it? (Press y|Y for Yes, any other key for No) : y
Reload privilege tables now? (Press y|Y for Yes, any other key for No) : y
测试安装效果:
(如下图则安装完成)
集群方式
mysql的主从复制模式:
异步复制
MySQL异步复制是主从复制过程中默认的复制模式。主从复制涉及三个线程,master I/O线程、slave I/O线程、slave sql线程。因为是异步复制,所以master事务的提交,不需要经过slave的确认,即master I/O线程提交事务后,不需要等待slave I/O线程的回复确认,master并不保证binlog一定写入到了relay log中;而slave I/O把binlog写入relay log后,由slave sql线程异步执行应用到slave mysql中,slave I/O也不需要slave sql的回复确认,并不保证relay log日志完整写入到了mysql中。
实验1:添加slave1
1.环境配置
主机名称 | ip | 角色 |
mysql-node1 | 172.25.254.10 | master |
mysql-node2 | 172.25.254,20 | slave |
配置master
[root@mysql-node10 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
log-bin=mysql-bin #添加
server-id=1 #添加
[root@mysql-node10 ~]# /etc/init.d/mysqld restart
#进入数据库配置用户权限
[root@mysql-node10 ~]# mysql -plee
##生成专门用来做复制的用户,此用户是用于slave端做认证用
mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'lee';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%'; ##对这个用户进行授权
配置slave
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=2 #添加
[root@mysql-node2 ~]# /etc/init.d/mysqld restart
[root@mysql-node2 ~]# mysql -plee
定位mysql-node2
2.开启slave,测试:
定位mysql-node1
实验2:在有数据的情况下添加slave2
1.环境配置
主机名称 | ip | 角色 |
mysql-node1 | 172.25.254.10 | master |
mysql-node2 | 172.25.254,20 | slave1 |
mysql-node3 | 172.25.254.30 | slave2 |
#完成基础配置
[root@mysql-node3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=3
[root@mysql-node3 ~]# /etc/init.d/mysqld restart
跟实验1稍有不同,这里需要先从master节点备份数据(在企业中备份需要锁表以保证备份前后的数据一致)
[root@mysql-node1 ~]# mysqldump -uroot -plee lee > lee.sql
因为此时的mysql-node3中没有任何数据,所以需要拉平数据。
#利用master节点中备份出来的lee.sql在slave2中拉平数据
[root@mysql-node3 ~]# mysql -uroot -plee -e "create database lee;"
[root@mysql-node3 ~]# mysql -uroot -p lee < lee.sql
[roort@mysql-node3~]#mysql -uroot -plee -e "select * from lee.userlist;"
配置slave2的功能(同实验一)
注意:master的状态可能会发生改变,要查了之后里面立马配置slave
[root@mysql-node3 ~]# mysql -uroot -plee
mysql> CHANGE MASTER TO
MASTER_HOST='172.25.254.10',
MASTER_USER='repl',
MASTER_PASSWORD='lee',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=1251;
mysql> start slave; #开启slave功能
mysql> SHOW SLAVE STATUS\G; #查看配置是否成功
2.测试
在mysql-node1中向表lee.userlist插入数据,看两个从机是否同步
mysql> insert into lee.userlist values('五条悟','555');
实验3:延迟复制
#在slave端(随便开一台)
mysql> STOP SLAVE SQL_THREAD;
mysql> CHANGE MASTER TO MASTER_DELAY=60; #设置延迟时间
mysql> START SLAVE SQL_THREAD;
mysql> SHOW SLAVE STATUS\G;
Master_Server_Id: 1
Master_UUID: db2d8c92-4dc2-11ef-b6b0-000c299355ea
Master_Info_File: /data/mysql/master.info
SQL_Delay: 60 ##延迟效果
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more
updates
Master_Retry_Count: 86400
测试: 在master中写入数据后过了延迟时间才能被查询到
实验4:慢查询日志
当执行SQL超过long_query_time参数设定的时间阈值(默认10s)时,就被认为是慢查询,这个 SQL语句就是需要优化的
慢查询被记录在慢查询日志里 ,慢查询日志默认是不开启的 。如果需要优化SQL语句,就可以开启这个功能,它可以让你很容易地知道哪些语句是需要优化的。
未开启状态:
开启慢查询:
mysql> SET GLOBAL slow_query_log=ON;
mysql> SET long_query_time=4;
mysql> SHOW VARIABLES like "slow%";
cat /data/mysql/mysql-node1-slow.log
可以看到日志内容:
实验5:并行复制
默认情况下slave中使用的是sql单线程回放
在master中时多用户读写,如果使用sql单线程回放那么会造成主从延迟严重
开启MySQL的多线程回放可以解决上述问题
在slaves中设定
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=2
gtid_mode=ON
enforce-gtid-consistency=ON
slave-parallel-type=LOGICAL_CLOCK #基于组提交,
slave-parallel-workers=16 #开启线程数量
#master信息在表中记录,默认记录在/data/mysql//master.info
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON #日志回放恢复功能开启
[root@mysql-node2 ~]# /etc/init.d/mysql start
测试:
此时sql线程转化为协调线程,16个worker负责处理sql协调线程发送过来的处理请求
半同步复制
基于传统异步存在的缺陷,mysql在5.5版本推出半同步复制,是对传统异步复制的改进。在master事务commit前,必须确保binlog日志已经写入slave 的relay log日志中,收到slave给master的响应后,才能进行事务的commit。但是后半部分的relay log到sql线程仍然属于异步执行。
1.gtid模式
当为启用gtid时我们要考虑的问题 在master端的写入时多用户读写,在slave端的复制时单线程日志回放,所以slave端一定会延迟与 master端
这种延迟在slave端的延迟可能会不一致,当master挂掉后slave接管,一般会挑选一个和master延迟日 志最接近的充当新的master 那么为接管master的主机继续充当slave角色并会指向到新master上,作为其slave 这时候按照之前的配置我们需要知道新的master上的pos的id,但是我们无法确定新的master和slave之间差多少
当激活GITD之后
当master出现问题后,slave2和master的数据最接近,会被作为新的master slave1指向新的master,但是他不会去检测新的master的pos id,只需要继续读取自己gtid_next即可
#在master端和slave端开启gtid模式
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node1 ~]# /etc/init.d/mysqld restart
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=2
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node2 ~]# /etc/init.d/mysqld restart
[root@mysql-node3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=3
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node3 ~]# /etc/init.d/mysqld restart
#停止slave端
[root@mysql-node2 ~]# mysql -p
mysql> stop slave;
[root@mysql-node3 ~]# mysql -p
mysql> stop slave;
#开启slave端的gtid
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl',
MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1;
2.半同步模式
定位master端 配置版同步模式
[root@mysql-node1 ~]# vim /etc/my.cnf //配置文件内容
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
rpl_semi_sync_master_enabled=1
symbolic-links=0
进入mysql安装办同步插件
[root@mysql-node1 ~]# mysql -p lee
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#查看插件情况
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
-> FROM INFORMATION_SCHEMA.PLUGINS
-> WHERE PLUGIN_NAME LIKE '%semi%';
#打开半同步功能
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
#查看半同步功能状态
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
mysql> show plugins
定位mysql-node2
#配置文件内容
[root@mysql-node2 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
enforce-gtid-consistency=ON
rpl_semi_sync_master_enabled=1 #开启半同步功能
symbolic-links=0
进入mysql 进行操作
[root@mysql-node2 ~]# mysql -plee
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
mysql> STOP SLAVE IO_THREAD; #重启io线程,半同步才能生效
mysql> START SLAVE IO_THREAD; ##重启io线程,半同步才能生效
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
测试
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 2 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 0 |
| Rpl_semi_sync_master_no_tx | 0 | #未同步数据0笔
| Rpl_semi_sync_master_status | ON |
| Rpl_semi_sync_master_timefunc_failures | 0 |
| Rpl_semi_sync_master_tx_avg_wait_time | 981 |
| Rpl_semi_sync_master_tx_wait_time | 981 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 | #已同步数据1笔
+--------------------------------------------+-------+
14 rows in set (0.00 sec)
模拟故障
定位mysql-node2,mysql-node3,关闭io线程
[root@mysql-node2 ~]# mysql -plee
mysql> STOP SLAVE IO_THREAD;
[root@mysql-node3 ~]# mysql -plee
mysql> STOP SLAVE IO_THREAD;
定位master端 插入数据
mysql> insert into lee.userlist values ('user5','555');
Query OK, 1 row affected (10.00 sec) #10秒超时
mysql> SHOW STATUS LIKE 'Rpl_semi%';
+--------------------------------------------+-------+
| Variable_name | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients | 0 |
| Rpl_semi_sync_master_net_avg_wait_time | 0 |
| Rpl_semi_sync_master_net_wait_time | 0 |
| Rpl_semi_sync_master_net_waits | 2 |
| Rpl_semi_sync_master_no_times | 1 |
| Rpl_semi_sync_master_no_tx | 1 | #一笔数据为同步
| Rpl_semi_sync_master_status | OFF | #自动转为异步模式,当
slave恢复
| Rpl_semi_sync_master_timefunc_failures | 0 | #会自动恢复
| Rpl_semi_sync_master_tx_avg_wait_time | 981 |
| Rpl_semi_sync_master_tx_wait_time | 981 |
| Rpl_semi_sync_master_tx_waits | 1 |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0 |
| Rpl_semi_sync_master_wait_sessions | 0 |
| Rpl_semi_sync_master_yes_tx | 1 |
+--------------------------------------------+-------+
组复制(高可用)
基于传统异步复制和半同步复制的缺陷——数据的一致性问题无法保证,MySQL官方在5.7.17版本正式推出组复制(MySQL Group Replication,简称MGR)。
由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点(N / 2 + 1)决议并通过,才能得以提交。如上图所示,由3个节点组成一个复制组,Consensus层为一致性协议层,在事务提交过程中,发生组间通讯,由2个节点决议(certify)通过这个事务,事务才能够最终得以提交并响应。
引入组复制,主要是为了解决传统异步复制和半同步复制可能产生数据不一致的问题。组复制依靠分布式一致性协议(Paxos协议的变体),实现了分布式下数据的最终一致性,提供了真正的数据高可用方案(是否真正高可用还有待商榷)。其提供的多写方案,给我们实现多活方案带来了希望。
MGR环境下,服务器数量必须是3台以上,并且是单数,实现2/n+1的算法。
组复制的流程图:
注意:节点数量不能超过9台
实验
环境
主机名称 | ip | 角色 |
mysql-node1 | 172.25.254.10 | master |
mysql-node2 | 172.25.254,20 | slave1 |
mysql-node3 | 172.25.254.30 | slave2 |
1.初始化数据库数据,防止出现问题
#在mysql-node1中
rm -fr /data/mysql/* #删除这个目录下的内容
[root@mysql-node1 ~]# vim /etc/my.cnf #编辑配置内容
2.向本地解析文件中配置其他几台主机内容
3.配置sql内容
[root@mysql-node1 ~]# mysqld --user=mysql --initialize
[root@mysql-node1 ~]# /etc/init.d/mysqld start
[root@mysql-node1 ~]# mysql -uroot -p初始化后生成的密码 -e "alter user root@localhost identified by 'lee';"
进入mysql配置
[root@mysql-node10 ~]# mysql -plee
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'lee';
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='lee' FOR CHANNEL
'group_replication_recovery';
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
投个小懒,提高效率:
[root@mysql-node2 & 3 ~]# scp /etc/my.cnf root@172.25.254.20:/etc/my.cnf
[root@mysql-node2 & 3 ~]# scp /etc/my.cnf root@172.25.254.30:/etc/my.cnf
4.配置另外两台
#修改mysql—node2和mysl-node3中的配置
[root@mysql-node2 & 3 ~]# rm -fr/data/mysql/
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
symbolic-links=0
server-id=2 #在3上写3
disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW
plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address="172.25.254.20:33061" #在3上要写30
group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061,
172.25.254.30:33061"
group_replication_ip_whitelist="172.25.254.0/24,127.0.0.1/8"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
group_replication_enforce_update_everywhere_checks=ON
group_replication_allow_local_disjoint_gtids_join=1
[root@mysql-node1 ~]# mysqld --user=mysql --initialize
[root@mysql-node1 ~]# /etc/init.d/mysqld start
[root@mysql-node1 ~]# mysql -uroot -p初始化后生成的密码 -e "alter user
root@localhost identified by 'lee';"
#配置sql
[root@mysql-node2 & 3 ~]# mysql -plee
mysql> SET SQL_LOG_BIN=0;
mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'lee';
mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
mysql> FLUSH PRIVILEGES;
mysql> SET SQL_LOG_BIN=1;
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='lee' FOR CHANNEL
'group_replication_recovery';
mysql> START GROUP_REPLICATION;
mysql> SELECT * FROM performance_schema.replication_group_members;
5测试
#在mysql-node1中
[root@mysql-node1 ~]# mysql -p
mysql> CREATE DATABASE lee;
mysql> CREATE TABLE lee.userlist(
-> username VARCHAR(10) PRIMARY KEY NOT NULL,
-> password VARCHAR(50) NOT NULL
-> );
mysql> INSERT INTO lee.userlist VALUES ('user1','111');
mysql> SELECT * FROM lee.userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1 | 111 |
+----------+----------+
#在mysql-node2中
[root@mysql-node2 ~]# mysql -p
mysql> INSERT INTO lee.userlist values ('user2','222');
mysql> select * from lee.userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1 | 111 |
| user2 | 222 |
+----------+----------+
#mysql—node3中
[root@mysql-node3 ~]# mysql -p
mysql> INSERT INTO lee.userlist values ('user3','333');
mysql> select * from lee.userlist;
+----------+----------+
| username | password |
+----------+----------+
| user1 | 111 |
| user2 | 222 |
| user3 | 333 |
+----------+----------+
MySQL路由
mysql-router是一个对应用程序透明的InnoDB Cluster连接路由服务,提供负载均衡、应用连接故障转移和客户端路 由。 利用路由器的连接路由特性,用户可以编写应用程序来连接到路由器,并令路由器使用相应的路由策略来处理连接,使其连接到正确的MySQL数据库服务器。
MySQL-router的部署方式
主机名称 | ip | 角色 |
mysql-node1 | 172.25.254.10 | master |
mysql-node2 | 172.25.254,20 | slave1 |
mysql-node3 | 172.25.254.30 | slave2 |
mysql-node4 | 172.25.254.40 | router |
定位router端
#安装mysql-router
[root@mysql-router ~]# rpm -ivh mysql-router-community-8.4.0-1.el7.x86_64.rpm
#配置mysql-router
[root@mysql-router ~]# vim /etc/mysqlrouter/mysqlrouter.conf
[routing:ro]
bind_address = 0.0.0.0
bind_port = 7001
destinations = 172.25.254.10:3306,172.25.254.20:3306,172.25.254.30:3306 routing_strategy = round-robin
[routing:rw]
bind_address = 0.0.0.0
bind_port = 7002
destinations = 172.25.254.30:3306,172.25.254.20:3306,172.25.254.10:3306 routing_strategy = first-available
[root@mysql-router ~]# systemctl start mysqlrouter.service
测试
#建立测试用户
mysql> CREATE USER lee@'%' IDENTIFIED BY 'lee';
mysql> GRANT ALL ON lee.* TO lee@'%';
#查看调度效果
[root@mysql-node10 & 20 & 30 ~]# watch -1 lsof -i :3306
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 9879 mysql 22u IPv6 56697 0t0 TCP *:mysql (LISTEN)
[root@mysql-router ~]# mysql -ulee -plee -h 172.25.254.40 -P 7001
通过最后一行命令查看是否可以登录上指定的数据库,登录上则mysql-router成功,否则失败。查看日志排错。
MySQL高可用--MHA
1.MHA简介
什么是MHA?
- MHA(Master High Availability)是一套优秀的MySQL高可用环境下故障切换和主从复制的软件。
- MHA 的出现就是解决MySQL 单点的问题。
- MySQL故障切换过程中,MHA能做到0-30秒内自动完成故障切换操作。
- MHA能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可用。
MHA的特点是什么?
- 自动故障切换过程中,MHA从宕机的主服务器上保存二进制日志,最大程度的保证数据不丢失
- 使用半同步复制,可以大大降低数据丢失的风险,如果只有一个slave已经收到了最新的二进制日 志,MHA可以将最新的二进制日志应用于其他所有的slave服务器上,因此可以保证所有节点的数 据一致性
- 目前MHA支持一主多从架构,最少三台服务,即一主两从
MHA的工作原理?
- 目前MHA主要支持一主多从的架构,要搭建MHA,要求一个复制集群必须最少有3台数据库服务器, 一主二从,即一台充当Master,台充当备用Master,另一台充当从库。
- MHA Node 运行在每台 MySQL 服务器上
- MHAManager 会定时探测集群中的master 节点
- 当master 出现故障时,它可以自动将最新数据的slave 提升为新的master 然后将所有其他的slave 重新指向新的master,VIP自动漂移到新的master。
- 整个故障转移过程对应用程序完全透明。
2.MHA的部署
环境
主机名称 | ip | 角色 |
mysql-node1 | 172.25.254.10 | master |
mysql-node2 | 172.25.254,20 172.25.254.11 | slave1 第二个临时ip做检测用 |
mysql-node3 | 172.25.254.30 | slave2 |
mysql-MHA | 172.25.254.50 | MHA |
(1)搭建主两从架构
#在master节点中
[root@mysql-node1 ~]# /etc/init.d/mysqld stop
[root@mysql-node1 ~]# rm -fr /data/mysql/* #删除之前的数据
[root@mysql-node1 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
log_slave_updates=ON #这一行一定要写进去 因为在后面做MHA检测的时候必须要有否则报错
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node1 ~]# mysqld --user mysql --initialize #初始化
[root@mysql-node1 ~]# /etc/init.d/mysqld start
[root@mysql-node1 ~]# mysql_secure_installation
[root@mysql-node1 ~]# mysql -p
mysql> CREATE USER 'repl'@'%' IDENTIFIED BY 'lee';
mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%';
mysql> INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
做好设置之后打开数据库进入检查开关情况,如下图则成功
定位mysql-node2和mysql-node3,初始化数据库再重启数据库更新密码,加入免密认证
#在slave1和slave2
[root@mysql-node2 & 3 ~]# /etc/init.d/mysqld stop
[root@mysql-node2 & 3 ~]# rm -fr /data/mysql/*
[root@mysql-node2 & 3 ~]# vim /etc/my.cnf
[mysqld]
datadir=/data/mysql
socket=/data/mysql/mysql.sock
server-id=1
log-bin=mysql-bin
gtid_mode=ON
log_slave_updates=ON
enforce-gtid-consistency=ON
symbolic-links=0
[root@mysql-node2 & 3 ~]# mysqld --user mysql --initialize
[root@mysql-node2 & 3 ~]# /etc/init.d/mysqld start
[root@mysql-node2 & 3 ~]# mysql_secure_installation
[root@mysql-node2 & 3 ~]# mysql -p
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl',
MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1;
mysql> start slave;
mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1;
mysql> STOP SLAVE IO_THREAD;
mysql> START SLAVE IO_THREAD;
mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
输入如图所示的命令即可查看状态,必须是开启的。
(2)安装MHA所需要的软件
[root@mysql-mha ~]# unzip MHA-7.zip #解压已经导入的软件包
注意要进入解压后的软件包目录之后再继续yum
[root@mysql-mha MHA-7]# yum install *.rpm -y
利用scp传输过去给其他几台主机:
这里想要速度变快就更改/etc/.sshd/ssh_config中的USERDNS yes 为 no 记得要重启sshd服务
工具包介绍
2.Node工具包 (通常用master主机直接调用,无需人去执行)
save_binary_logs #保存和复制master的二进制日志
apply_diff_relay_logs #识别差异的中继日志事件并将其差异的事件应用于其他的slave
filter_mysqlbinlog #去除不必要的ROLLBACK事件(MHA已不再使用这个工具)
purge_relay_logs #清除中继日志(不会阻塞SQL线程)
(3)配置MHA管理环境
1.生成配置目录和配置文件
[root@mysql-mha ~]# masterha_manager --help
Usage:
masterha_manager --global_conf=/etc/masterha_default.cnf #全局配置文件,记录公共设定
--conf=/usr/local/masterha/conf/app1.cnf #不同管理配置文件,记录各自配置
See online reference
(http://code.google.com/p/mysql-master-ha/wiki/masterha_manager) for
details.
2.编写一个配置文件
解压源码包后在samples中找到配置文件的模板文件
#生成配置文件
[root@mysql-mha ~]# mkdir /etc/masterha
[root@mysql-mha MHA-7]# tar zxf mha4mysql-manager-0.58.tar.gz
[root@mysql-mha MHA-7]# cd mha4mysql-manager-0.58/samples/conf/
[root@mysql-mha conf]# cat masterha_default.cnf app1.cnf > /etc/masterha/app1.cnf
#编辑配置文件
[root@mysql-mha ~]# vim /etc/masterha/app1.cnf
[server default]
user=root #mysql管理员用户,因为需要做自动化配置
password=lee #mysql密码
ssh_user=root #ssh远程登陆用户
repl_user=repl #mysql主从复制中负责认证的用户
repl_password=lee #mysql主从复制中负责认证的用户密码
master_binlog_dir= /data/mysql #二进制日志目录
remote_workdir=/tmp #远程工作目录
#此参数使为了提供冗余检测,方式是判断mha主机网络自身的问题无法连接数据库节点,应为集群之外的主机
secondary_check_script= masterha_secondary_check -s 172.25.254.10 -s 172.25.254.11
##注意:两节点必须有一个是下面server中的 一台不是
ping_interval=3 #每隔3秒检测一次
#发生故障后调用的脚本,用来迁移vip
# master_ip_failover_script= /script/masterha/master_ip_failover
#电源管理脚本
# shutdown_script= /script/masterha/power_manager
#当发生故障后用此脚本发邮件或者告警通知
# report_script= /script/masterha/send_report
#在线切换时调用的vip迁移脚本,手动
# master_ip_online_change_script= /script/masterha/master_ip_online_change
manager_workdir=/etc/masterha #mha工作目录
manager_log=/var/etc/masterha/manager.log #mha日志
[server1]
hostname=172.25.254.10
candidate_master=1 #可能作为master的主机
check_repl_delay=0 ##默认情况下如果一个slave落后master 100M的relay logs的话
#MHA将不会选择该slave作为一个新的master
#因为对于这个slave的恢复需要花费很长时间
#通过设置check_repl_delay=0
#MHA触发切换在选择一个新的master的时候将会忽略复制延时
#这个参数对于设置了candidate_master=1的主机非常有用
#因为这个候选主在切换的过程中一定是新的master
[server2]
hostname=172.25.254.20
candidate_master=1 #可能作为master的主机
check_repl_delay=0
[server3]
hostname=172.25.254.30
no_master=1 #不会作为master的主机
2.检测配置
a.检测网络以及ssh免密
[root@mysql-mha ~]# masterha_check_ssh --conf=/etc/masterha/app1.cnf
b.检测数据主从复制情况
[root@mysql-mha ~]# masterha_check_repl --conf=/etc/masterha/app1.cnf
note:如果出现报错就去看日志的详细描述,常见错误如下:
- 防火墙没关
- selinux不是disabled状态
- /etc/masterha/app1.cnf这个配置文件内容不对
- 其他主机的/etc/my.cnf配置文件内容缺失
如果你很幸运,那么就是下面的成功画面:
3.MHA故障切换
(1)master未出现故障手动切换
#在master数据节点还在正常工作情况下
[root@mysql-mha ~]# masterha_master_switch \
--conf=/etc/masterha/app1.cnf \ # 指定配置文件
--master_state=alive \ #指定master节点状态
--new_master_host=172.25.254.20 \ #指定新master节点
--new_master_port=3306 \ #执行新master节点端口
--orig_master_is_new_slave \ #原始master会变成新的slave
--running_updates_limit=10000 #切换的超时时间
检测:
[root@mysql-mha masterha]# masterha_check_repl --conf=/etc/masterha/app1.cnf
(2)master出现故障手动切换
#模拟master故障
[root@mysql-node2 mysql]# /etc/init.d/mysqld stop
#在MHA-master中做故障切换
[root@mysql-mha masterha]# masterha_master_switch --master_state=dead --
conf=/etc/masterha/app1.cnf --dead_master_host=192.168.56.12 --
dead_master_port=3306 --new_master_host=192.168.56.11 --new_master_port=3306 --
ignore_last_failover
--ignore_last_failover 表示忽略在/etc/masterha/目录中在切换过程中生成的锁文件
masterha_master_switch --master_state=dead --conf=/etc/masterha/app1.cnf --
dead_master_host=172.25.254.20 --dead_master_port=3306 --
new_master_host=172.25.254.10 --new_master_port=3306 --ignore_last_failover
--dead_master_ip=<dead_master_ip> is not set. Using 172.25.254.20.
恢复故障mysql节点
[root@mysql-node20 tmp]# /etc/init.d/mysqld start Starting MySQL. SUCCESS! [root@mysql-node20 tmp]# mysql -p
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl', MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1;
(3)自动切换
[root@mysql-mha masterha]# rm -fr app1.failover.complete #删掉切换锁文件
#监控程序通过指定配置文件监控master状态,当master出问题后自动切换并退出避免重复做故障切换
[root@mysql-mha masterha]# masterha_manager --conf=/etc/masterha/app1.cnf
[root@mysql-mha masterha]# cat /etc/masterha/manager.log
#恢复故障节点
[root@mysql-node20 mysql]# /etc/init.d/mysqld start
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl',
MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1
#清除所锁文件
[root@mysql-mha masterha]# rm -rf app1.failover.complete manager.log
4.添加VIP功能
上传脚本(已写好的)
[root@mysql-mha ~]# ls
master_ip_failover master_ip_online_change MHA-7 MHA-7.zip
[root@mysql-mha ~]# cp master_ip_failover master_ip_online_change /usr/local/bin/
[root@mysql-mha ~]# chmod +x /usr/local/bin/master_ip_*
#修改脚本在脚本中只需要修改下vip即可
[root@mysql-mha ~]# vim /usr/local/bin/master_ip_failover
my $vip = '172.25.254.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";
[root@mysql-mha ~]# vim /usr/local/bin/master_ip_online_change
my $vip = '172.25.254.100/24';
my $ssh_start_vip = "/sbin/ip addr add $vip dev eth0";
my $ssh_stop_vip = "/sbin/ip addr del $vip dev eth0";
my $exit_code = 0;
[root@mysql-mha masterha]# masterha_manager --conf=/etc/masterha/app1.cnf #启动监控程序
[root@mysql-node10 tmp]# ip a a 172.25.254.100/24 dev eth0 #在master节点添加VIP
模拟故障:
[root@mysql-node10 ~]# /etc/init.d/mysqld stop #关闭主节点服务
[root@mysql-mha masterha]# cat manager.log
恢复故障主机:
[root@mysql-node20 mysql]# /etc/init.d/mysqld start
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl', MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1
[root@mysql-mha masterha]# rm -rf app1.failover.complete manager.log
手动切换后查看vip变化
[root@mysql-mha masterha]# masterha_master_switch --conf=/etc/masterha/app1.cnf --master_state=alive --new_master_host=172.25.254.10 --new_master_port=3306 -- orig_master_is_new_slave --running_updates_limit=10000
[root@mysql-node10 ~]# ip a #查看ip变化
二、Redis非关系型数据库
1.Redis特点
- 速度快: 10W QPS,基于内存,C语言实现
- 单线程
- 持久化
- 支持多种数据结构
- 支持多种编程语言
- 功能丰富: 支持Lua脚本,发布订阅,事务,pipeline等功能
- 简单: 代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单(单线程之所以超级快,是因为:纯内存、非阻塞、避免切换和竞态消耗)
- 主从复制
- 支持高可用和分布式
2.Redis应用场景
3.缓存的实现流程
数据更新操作流程
数据读操作流程
4.Redis的安装
官方下载地址:http://download.redis.io/releases/
任意选择以下方式安装(仅使用1种方式即可)
4.1.rpm包方式安装
[root@redis-node1 ~]# dnf install redis -y
4.2.源码安装
[root@redis-node1 ~]# tar zxf redis-7.4.0.tar.gz
[root@redis-node1 ~]# ls
redis-7.4.0 redis-7.4.0.tar.gz
#安装编译工具
[root@redis-node1 redis-7.4.0]# dnf install make gcc initscripts-10.11.6-1.el9.x86_64 -y
#执行编译命令
[root@redis-node1 redis-7.4.0]# make
[root@redis-node1 redis-7.4.0]# make install
#启动Redis
[root@redis-node1 redis-7.4.0]# cd utils/
[root@redis-node1 utils]# ./install_server.sh
配置Redis
[root@redis-node1 utils]# vim /etc/redis/6379.conf
bind * -::*
[root@redis-node1 utils]# /etc/init.d/redis_6379 restart
Stopping ...
Redis stopped
Starting Redis server...
[root@redis-node1 utils]# netstat -antlpe | grep redis
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN 0
67267 38417/redis-server
tcp6 0 0 :::6379
#查看信息
[root@redis-node1 utils]# redis-cli
127.0.0.1:6379> info
如果提示如下图所示:
vim /etc/redis/redis.conf #进入Redis的主配置文件
如下图则表示成功进入了Redis,即可开始使用
4.3.基本操作
(1)查看配置(红色是命令,黄色是结果)
(2)写入和读取数据
(3)选择数据库 Redis中有0-15个数据库
(4)改变键名
(5)设定数据过期时间 / 持久化(设置时间版)保持
127.0.0.1:6379> PERSIST name 持久化保持
(6)删除
(7)判断key的存在
(8)清空当前库
127.0.0.1:6379> flushdb
(9)清空所有库
127.0.0.1:6379[1]> FLUSHALL
5.Redis主从复制
5.1.环境
需要安装同样的数据库主机三台
主机名称 | ip | 角色 |
redis-node1 | 172.25.254.10 | master |
redis-node2 | 172.25.254,20 | slave |
redis-node3 | 172.25.254.30 | slave |
5.2.配置主从同步
- slave节点发送同步亲求到master节点
- slave节点通过master节点的认证开始进行同步
- master节点会开启bgsave进程发送内存rbd到slave节点,在此过程中是异步操作,也就是说 master节点仍然可以进行写入动作
- slave节点收到rdb后首先清空自己的所有数据
- slave节点加载rdb并进行数据恢复 在master和slave同步过程中master还会开启新的bgsave进程把没有同步的数据进行缓存 然后通过自有的replactionfeedslave函数把未通过内存快照发动到slave的数据一条一条写入到 slave中
(1)修改master节点的配置文件
[root@redis-node1 & node2 & node3 ~]# vim /etc/redis/6379.conf
修改配置文件之后需要重启服务
[root@redis-node1 &node2 & node3 ~]# /etc/init.d/redis_6379 restart
(2)配置slave节点
[root@redis-node2 & 3 ~]# vim /etc/redis/6379.conf
[root@redis-node2 & 3 ~]# /etc/init.d/redis_6379 restart
(3)测试
#在mastser节点
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> set name yara
OK
#在slave节点查看
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> get name
"yara"
6.Redis的哨兵(高可用)
每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活” 着,如果发现对方在指定配置时间(此项可配置)内未得到回应,则暂时认为对方已离线,也就是所谓的” 主观认为宕机” (主观:是每个成员都具有的独自的而且可能相同也可能不同的意识),英文名称: Subjective Down,简称SDOWN
有主观宕机,对应的有客观宕机。当“哨兵群”中的多数Sentinel进程在对Master主服务器做出SDOWN 的 判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判 断,这种方式就是“客观宕机”(客观:是不依赖于某种意识而已经实际存在的一切事物),英文名称是: Objectively Down, 简称 ODOWN
6.1.哨兵的实验过程
在所有阶段中关闭 protected-mode no
#编辑配置文件
[root@redis-node1 ~]# cd redis-7.4.0/
[root@redis-node1 redis-7.4.0]# cp sentinel.conf /etc/redis/
[root@redis-node1 redis-7.4.0]# vim /etc/redis/sentinel.conf
protected-mode no #关闭保护模式
port 26379 #监听端口
daemonize no #进入不打如后台
pidfile /var/run/redis-sentinel.pid #sentinel进程pid文件
loglevel notice #日志级别
sentinel monitor mymaster 172.25.254.100 6379 2 #创建sentinel监控监控master主机,2表示必须得到2票
sentinel down-after-milliseconds mymaster 10000 #master中断时长,10秒连不上视为master下线
sentinel parallel-syncs mymaster 1 #发生故障转移后,同时开始同步新
master数据的slave数量
sentinel failover-timeout mymaster 180000 #整个故障切换的超时时间为3分钟
####复制配置文件到其他阶段
[root@redis-node1 redis-7.4.0]# scp /etc/redis/sentinel.conf
root@172.25.254.201:/etc/redis/
root@172.25.254.201's password:
sentinel.conf
100% 14KB 9.7MB/s 00:00
[root@redis-node1 redis-7.4.0]# scp /etc/redis/sentinel.conf
root@172.25.254.200:/etc/redis/
root@172.25.254.200's password:
sentinel.conf
启动服务
[root@redis-node1 redis-7.4.0]# redis-sentinel /etc/redis/sentinel.conf
39319:X 05 Aug 2024 20:53:16.807 # WARNING Memory overcommit must be enabled!
Without it, a background save or replication may fail under low memory condition.
Being disabled, it can also cause failures without low memory condition, see
https://github.com/jemalloc/jemalloc/issues/1328. To fix this issue add
'vm.overcommit_memory = 1' to /etc/sysctl.conf and then reboot or run the command
'sysctl vm.overcommit_memory=1' for this to take effect.
39319:X 05 Aug 2024 20:53:16.807 * oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
39319:X 05 Aug 2024 20:53:16.807 * Redis version=7.4.0, bits=64, commit=00000000,
modified=0, pid=39319, just started
39319:X 05 Aug 2024 20:53:16.807 * Configuration loaded
39319:X 05 Aug 2024 20:53:16.808 * Increased maximum number of open files to
10032 (it was originally set to 1024).
39319:X 05 Aug 2024 20:53:16.808 * monotonic clock: POSIX clock_gettime
_._
_.-``__ ''-._
_.-`` `. `_. ''-._ Redis Community Edition
.-`` .-```. ```\/ _.,_ ''-._ 7.4.0 (00000000/0) 64 bit
( ' , .-` | `, ) Running in sentinel mode
|`-._`-...-` __...-.``-._|'` _.-'| Port: 26379
| `-._ `._ / _.-' | PID: 39319
`-._ `-._ `-./ _.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' | https://redis.io
`-._ `-._`-.__.-'_.-' _.-'
|`-._`-._ `-.__.-' _.-'_.-'|
| `-._`-._ _.-'_.-' |
`-._ `-._`-.__.-'_.-' _.-'
`-._ `-.__.-' _.-'
`-._ _.-'
`-.__.-'
39319:X 05 Aug 2024 20:53:16.810 * Sentinel new configuration saved on disk
39319:X 05 Aug 2024 20:53:16.810 * Sentinel ID is
e568add863fd7c132e03f7a6ce2c5ef367d3bdae
39319:X 05 Aug 2024 20:53:16.810 # +monitor master mymaster 172.25.254.100 6379
quorum 2
39319:X 05 Aug 2024 20:53:16.811 * +slave slave 172.25.254.201:6379
172.25.254.201 6379 @ mymaster 172.25.254.100 6379
39319:X 05 Aug 2024 20:53:16.812 * Sentinel new configuration saved on disk
39319:X 05 Aug 2024 20:53:16.812 * +slave slave 172.25.254.200:6379
172.25.254.200 6379 @ mymaster 172.25.254.100 6379
39319:X 05 Aug 2024 20:53:16.813 * Sentinel new configuration saved on disk
39319:X 05 Aug 2024 20:53:41.769 * +sentinel sentinel
4fe1dcbe25a801e75d6edfc5b0a8517bfa7992c3 172.25.254.200 26379 @ mymaster
172.25.254.100 6379
39319:X 05 Aug 2024 20:53:41.771 * Sentinel new configuration saved on disk
39319:X 05 Aug 2024 20:53:57.227 * +sentinel sentinel
83f928aafe317a5f9081eea8fc5c383ff31c55ef 172.25.254.201 26379 @ mymaster
172.25.254.100 6379
39319:X 05 Aug 2024 20:53:57.229 * Sentinel new configuration saved on disk
测试
在开一个master节点终端
[root@redis-node1 ~]# redis-cli
127.0.0.1:6379> SHUTDOWN
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> info replications
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=172.25.254.201,port=6379,state=online,offset=211455,lag=1
slave1:ip=172.25.254.100,port=6379,state=online,offset=211455,lag=1
master_failover_state:no-failover
master_replid:d42fd72f3dfae94c84ca722ad1653417495ef4fd
master_replid2:290c3407108cc6120086981b7149a6fa377594c4
master_repl_offset:211598
second_repl_offset:185931
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:150986
repl_backlog_histlen:60613
6.2架构缺陷
在生产环境中如果master和slave中的网络出现故障,由于哨兵的存在会把master提出去 当网络恢复后,master发现环境发生改变,master就会把自己的身份转换成slave master变成slave后会把网络故障那段时间写入自己中的数据清掉,这样数据就丢失了。
如何解决这一问题呢?
master在被写入数据时会持续连接slave,mater确保有2个slave可以写入我才允许写入 如果slave数量少于2个便拒绝写入
#在matster中设定
[root@redis-node2 ~]# redis-cli
127.0.0.1:6379> CONFIG GET min-slaves-to-write
1) "min-slaves-to-write"
2) "0" 127.0.0.1:6379> CONFIG set min-slaves-to-write 2
OK
127.0.0.1:6379> CONFIG GET min-slaves-to-write
1) "min-slaves-to-write"
2) "2"
#如果要永久保存写到配置文件中/etc/redis/6379.conf
7.Redis Cluster(无中心化设计)
7.1.工作原理
在哨兵sentinel机制中,可以解决redis高可用问题,即当master故障后可以自动将slave提升为master, 从而可以保证redis服务的正常使用,但是无法解决redis单机写入的瓶颈问题,即单机redis写入性能受限于单机的内存大小、并发数量、网卡速率等因素。
redis 3.0版本之后推出了无中心架构的redis cluster机制,在无中心的redis集群当中,其每个节点保存当前节点数据和整个集群状态,每个节点都和其他所有节点连接
Redis cluster的架构虽然解决了并发的问题,但是又引入了一个新的问题,每个Redis master的高可用 如何解决?
那就是对每个master 节点都实现主从复制,从而实现 redis 高可用性
7.2创建Redis Cluster的要求
7.3部署Redis Cluster
在所有主机中
[root@redis-masterx ~]# vim /etc/redis/redis.conf
masterauth "123456" #集群主从认证
requirepass "123456" #redis登陆密码 redis-cli 命令连接redis后要
用“auth 密码”进行认证
cluster-enabled yes #开启cluster集群功能
cluster-config-file nodes-6379.conf #指定集群配置文件
cluster-node-timeout 15000 #节点加入集群的超时时间单位是ms
[root@redis-master1 ~]# systemctl restart redis.service
[root@redis-master1 ~]# redis-cli
127.0.0.1:6379> auth 123456
OK
127.0.0.1:6379> info
# Cluster
cluster_enabled:1
注意观察命令行前面主机称号
#配置文件位置 [root@redis-master1 ~]# ll /var/lib/redis/nodes-6379.conf
[root@redis-master1 ~]# redis-cli --cluster create -a 123456 \
> 172.25.254.10:6379 172.25.254.20:6379 172.25.254.30:6379 \
> 172.25.254.110:6379 172.25.254.120:6379 172.25.254.130:6379 \
> --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460 #哈希槽分配
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 172.25.254.120:6379 to 172.25.254.10:6379 #主从分配情况
Adding replica 172.25.254.130:6379 to 172.25.254.20:6379
Adding replica 172.25.254.110:6379 to 172.25.254.30:6379
M: 5ab2e93f4f0783983676f7bd118efaacfb202bd1 172.25.254.10:6379
slots:[0-5460] (5461 slots) master
M: ba504e78f14df5944280f9035543277a0cf5976b 172.25.254.20:6379
slots:[5461-10922] (5462 slots) master
M: 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7 172.25.254.30:6379
slots:[10923-16383] (5461 slots) master
S: c20c9b5465b2e64868161c0e285d55bc81358ba4 172.25.254.110:6379
replicates 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7
S: d458f34fa900d83212c021dc1e65396e490b5495 172.25.254.120:6379
replicates 5ab2e93f4f0783983676f7bd118efaacfb202bd1
S: 83d7a82fe896cf9f4d8212cb533058659bba16ce 172.25.254.130:6379
replicates ba504e78f14df5944280f9035543277a0cf5976b
Can I set the above configuration? (type 'yes' to accept): yes
>>> Performing Cluster Check (using node 172.25.254.10:6379)
M: 5ab2e93f4f0783983676f7bd118efaacfb202bd1 172.25.254.10:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: c20c9b5465b2e64868161c0e285d55bc81358ba4 172.25.254.110:6379
slots: (0 slots) slave
replicates 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7
M: ba504e78f14df5944280f9035543277a0cf5976b 172.25.254.20:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 83d7a82fe896cf9f4d8212cb533058659bba16ce 172.25.254.130:6379
slots: (0 slots) slave
replicates ba504e78f14df5944280f9035543277a0cf5976b
M: 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7 172.25.254.30:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: d458f34fa900d83212c021dc1e65396e490b5495 172.25.254.120:6379
slots: (0 slots) slave
replicates 5ab2e93f4f0783983676f7bd118efaacfb202bd1
[OK] All nodes agree about slots configuration.
>>> Check for open slots... #检查打开的哈希槽位
>>> Check slots coverage... #检查槽位覆盖范围
[OK] All 16384 slots covered. #所有槽位分配完成
检查Redis集群状态
[root@redis-master1 ~]# redis-cli -a 123456 --cluster info 172.25.254.10:6379
#查看集群状态
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
172.25.254.10:6379 (5ab2e93f...) -> 0 keys | 5461 slots | 1 slaves.
172.25.254.20:6379 (ba504e78...) -> 0 keys | 5462 slots | 1 slaves.
172.25.254.30:6379 (1fcaeb1d...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
[root@redis-master1 ~]# redis-cli -a 123456 cluster info
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:821
cluster_stats_messages_pong_sent:801
cluster_stats_messages_sent:1622
cluster_stats_messages_ping_received:796
cluster_stats_messages_pong_received:821
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:1622
[root@redis-master1 ~]# redis-cli -a 123456 --cluster check 172.25.254.10:6379
#检测集群
Warning: Using a password with '-a' or '-u' option on the command line interface
may not be safe.
172.25.254.10:6379 (5ab2e93f...) -> 0 keys | 5461 slots | 1 slaves.
172.25.254.20:6379 (ba504e78...) -> 0 keys | 5462 slots | 1 slaves.
172.25.254.30:6379 (1fcaeb1d...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 172.25.254.10:6379)
M: 5ab2e93f4f0783983676f7bd118efaacfb202bd1 172.25.254.10:6379
slots:[0-5460] (5461 slots) master
1 additional replica(s)
S: c20c9b5465b2e64868161c0e285d55bc81358ba4 172.25.254.110:6379
slots: (0 slots) slave
replicates 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7
M: ba504e78f14df5944280f9035543277a0cf5976b 172.25.254.20:6379
slots:[5461-10922] (5462 slots) master
1 additional replica(s)
S: 83d7a82fe896cf9f4d8212cb533058659bba16ce 172.25.254.130:6379
slots: (0 slots) slave
replicates ba504e78f14df5944280f9035543277a0cf5976b
M: 1fcaeb1dd936b46f4ea1efe4330c54195e66acf7 172.25.254.30:6379
slots:[10923-16383] (5461 slots) master
1 additional replica(s)
S: d458f34fa900d83212c021dc1e65396e490b5495 172.25.254.120:6379
slots: (0 slots) slave
replicates 5ab2e93f4f0783983676f7bd118efaacfb202bd1
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
写入数据
[root@redis-master1 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set key1 value1 #被分配到20的hash槽位上
(error) MOVED 9189 172.25.254.20:6379
[root@redis-master2 ~]# redis-cli -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> set key1 value1
OK
7.4集群扩容
#添加master [root@redis-master1 ~]# redis-cli -a 123456 --cluster add-node 172.25.254.40:6379 172.25.254.10:6379
[root@redis-master1 ~]# redis-cli -a 123456 --cluster info 172.25.254.10:6379
#分配槽位
[root@redis-master1 ~]# redis-cli -a 123456 --cluster reshard 172.25.254.10:6379
#添加salve
[root@redis-master1 ~]# redis-cli -a 123456 --cluster add-node 172.25.254.140:6379 172.25.254.10:6379 --cluster-slave --cluster-master-id 009571cb206a89afa6658b60b2d403136056ac09
7.5集群维护
添加节点的时候是先添加node节点到集群,然后分配槽位,删除节点的操作与添加节点的操作正好相 反,是先将被删除的Redis node上的槽位迁移到集群中的其他Redis node节点上,然后再将其删除,如 果一个Redis node节点上的槽位没有被完全迁移,删除该node的时候会提示有数据且无法删除。
#移除要下线主机的哈希槽位
[root@redis-master2 ~]# redis-cli -a 123456 --cluster reshard 172.25.254.20:6379
#删除master
[root@redis-master2 ~]# redis-cli -a 123456 --cluster del-node
172.25.254.120:6379 d458f34fa900d83212c021dc1e65396e490b5495
[root@redis-master2 ~]# redis-cli -a 123456 --cluster del-node
172.25.254.10:6379 5ab2e93f4f0783983676f7bd118efaacfb202bd1
总结
至此我们的数据库集群技术就到这里