这次一定要教会你搭建Redis集群和MySQL主从同步(非Docker)(下)

简介: 这次一定要教会你搭建Redis集群和MySQL主从同步(非Docker)(下)

测试


测试环节通过客户端测试和Java程序测试,来模拟集群模式下Redis的存储策略。


客户端测试


开启客户端,随意连接一个master节点


/usr/local/bin/redis-cli -c -a 密码 -h IP -p 端口


image.png


我们可以看到,当我们set一个键值对的时候,Redis会自动为我们的key计算CRC16值,然后对16384取模,获取key对应的hash slot,然后通过判断该槽被那个Master所占用,帮我们重定向到那个Master节点,将键值对存入。


程序测试


在测试之前先把Redis中的数据清空,对三个Master节点分别执行flushall命令。


启动程序:


1.正常存入数据时关闭某Master节点(模拟宕机):


image.png


程序打印正在选举…


image.png


2.选举结束后继续IO


image.png


代码:

public class JedisDemo {
    public static void main(String[] args) {
         JedisPoolConfig jedisPoolConfig = new JedisPoolConfig(); 
         Set<HostAndPort> nodes = new HashSet<>();
         nodes.add(new HostAndPort("192.168.43.101",7001));
         nodes.add(new HostAndPort("192.168.43.102",7002)); 
         nodes.add(new HostAndPort("192.168.43.103",7003)); 
         nodes.add(new HostAndPort("192.168.43.101",6001)); 
         nodes.add(new HostAndPort("192.168.43.102",6002)); 
         nodes.add(new HostAndPort("192.168.43.103",6003)); 
         nodes.add(new HostAndPort("192.168.43.101",6004)); 
         nodes.add(new HostAndPort("192.168.43.102",6005)); 
         nodes.add(new HostAndPort("192.168.43.103",6006)); 
         JedisCluster jedisCluster = new JedisCluster(nodes,100,1000,100,"Object","rediscluster",jedisPoolConfig,false);
         for(int i = 0;i<2000;i++) {
             try {
            System.out.println("存入数据:"+i);
             jedisCluster.set(String.valueOf(i),String.valueOf(i));
                 try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
            e.printStackTrace();
                }
                 String res = jedisCluster.get(String.valueOf(i)); 
                 System.out.println("取出数据:"+res);
             }catch(Exception e) {
                 //出现节点宕机
                 System.out.println("正在选举...");
                 System.out.println(new Date());
                 continue;
             }
         }
         jedisCluster.close();
    }
}


注意事项


在搭建集群的过程中有可能会遇到一直等待连接,但是集群无法连接成功的状况,这是因为我们在搭建集群的时候防火墙没有开启对应的端口号导致的,我们不光要开启我们对外连接的端口号,如7001、7002、7003,还要开启对外连接端口号+10000的端口,用于集群内部相互通信,如节点端口为7001、7002、7003,那么我们还应该开启17001、17002、17003这些端口。


如果遇到搭建失败的情况,重新搭建的时候一定要到dir指向的文件夹中将快照和AOF还有node.conf文件删干净,否则无法重新搭建。


搭建完毕


至此我们已经完成了Redis集群的搭建,在私下实践的时候可以试试使用Redis客户端直接操作集群时手动关闭某个Master,会出现什么样的状况,这个是文章中没有提到的内容。


什么是MySQL主从同步


数据是一个应用至关重要的一部分。从目的出发,主从同步有那么点备份的意思,主库(Master)将自己库中的写入同时同步给自己的从库(Slave),当主库发生某些不可预知的状况,导致整个服务器无法使用时,由于从库中也有一份数据,所以数据可以做到快速恢复,不造成或者减少造成数据的损失。


当然,这只是第一个层面,如果主从库的作用仅限于此,那么我个人认为没有必要分为两个数据库,只需要定期将数据库内容作为快照发送到另一台服务器,或者每次写入时将写入内容实时发送到另一台服务器不就好了吗,这样不但可以节约资源,也可以起到容灾备份的目的。


当然主从同步的作用绝不可能仅限于此,一旦我们配置了主从结构,我们通常不会让从节点仅仅只作为备份数据库,我们应该还会相应地配置上读写分离(可以使用MyCat或者其它中间件,可以自己了解一下,关于MyCat我在下一篇博客中会说这个,篇幅可能会有点长,所以就再写一篇吧)。


在实际环境下,对于数据库的读操作数目远大于对数据库的写操作,所以我们可以让Master只提供写的功能,然后将所有的读操作都移到从库,这就是我们平时常说的读写分离,这样不但可以减轻Master的压力,还可以做容灾备份,一举两得


MySQL主从同步的原理


说完了主从同步的概念,下面来说说主从同步的原理,其实原理也非常简单,没有Redis集群那么多的概念。


实际上当我们在MySQL中配置了主从之后,只要我们对Master节点进行了写操作,这个操作将会被保存到MySQL的binary-log(bin-log)日志当中,当slave连接到master的时候,master机器会为slave开启binlog dump线程。当master 的 binlog发生变化的时候,Master的dump线程会通知slave,并将相应的binlog内容发送给Slave。而Slave节点在主从同步开启的时候,会创建两个线程,一个I/O线程,一个SQL线程,这在我们后面的搭建中可以亲眼看到。


  • I/0线程:该线程链接到master机器,master机器的binlog发送到slave的时候,IO线程会将该日志内容写在本地的中继日志(Relay log)中。


  • SQL线程:该线程读取中继日志中的内容,并且根据中继日志中的内容对Slave数据库做相应的操作。


  • 可能造成的问题:在写请求相当多的情况下,可能会造成Slave数据和Master数据不一致的情况,这是因为日志传输过程中的短暂延迟、或者写命令较多,系统速度不匹配造成的。


这大致就是MySQL主从同步的原理,真正在其中起到作用的实际上就是这两个日志文件,binlog和中继日志。


image.png


手动搭建MySQL主从同步

环境准备

本次搭建主从同步的环境:CentOS 7 ,MySQL 8.0.18(使用二进制包安装)。

场景介绍

本次将会搭建MySQL的主从同步,其中一台Master,两台Slave。

Master:IP :192.168.43.201 Port:3306
Slave1:IP:192.168.43.202 Port:3306
Slave2:IP:192.168.43.203 Port:3306

开始搭建

修改配置文件


当我们安装好MySQL之后,在/etc/目录下会有一个my.cnf文件,打开文件,加入如下内容(别忘了修改之前做好备份):


x


#该配置为Master的配置
server-id=201 #Server id 每台MySQL的必须不同
log-bin=/var/lib/mysql/mysql-bin.log #代表开启binlog日志
expire_logs_days=10 #日志过期时间
max_binlog_size=200M #日志最大容量
binlog_ignore_db=mysql #忽略mysql库,表示不同步此库


y


#该配置为Slave的配置,第二台Slave也是这么配置,不过要修改一下server-id
server-id=202
expire_logs_days=10 #日志的缓存时间
max_binlog_size=200M #日志的最大大小
replicate_ignore_db=mysql #忽略同步的数据库


新增Slave用户


打开Master节点的客户端 ,mysql -u root -p 密码


创建用户 create user 'Slave'@'%' identified by '123456';

给新创建的用户赋权:grant replication slave on '*.*' to 'Slave'@'%';


查看Master节点状态


以上操作都没有问题后,我们在客户端中输入show master status查看master的binlog日志。


image.png


配置两个Slave节点


打开两个Slave节点客户端,在我们的另外两个Slave节点中输入如下命令:


change master to master_user='Slave',master_password='123456',master_host='192.168.43.201',master_log_file='mysql-bin.000005',master_log_pos=155,get_master_public_key=1;
#注意,这里的master_log_file,就是binlog的文件名,输入上图中的mysql-bin.000005,每个人的都可能不一样。
#注意,这里的master_log_pos是binlog偏移量,输入上图中的155,每个人的都可能不一样。


配置完成后,输入start slave;开启从节点,然后输入show slave status\G;查看从节点状


image.png


可以看到,在两台Slave的状态中,我们能亲眼看到IO线程和SQL线程的运行状态,这两个线程必须都是yes,才算配置搭建完成。


搭建完成


通过上述步骤,就完成了MySQL主从同步的搭建,相对Redis而言MySQL配置相当简单。下面我们可以进行测试。


先看看三个MySQL的数据库状态:SHOW DATABASES;


image.png


可以看到现在数据库都是初始默认状态,没有任何额外的库。


在Master节点中创建一个数据库,库名可以自己设置。


CREATE DATABASE testcluster;


image.png


可以看到,在Slave中也出现了Master中创建的数据库,说明我们的配置没有问题,主从搭建成功。这里就不再创建表了,大家可以自己试试,创建表再往表中插入数据,也是没有任何问题的。


注意事项


如果出现IO线程一直在Connecting状态,可以看看是不是三台机器无法相互连接,如果可以相互连接,那么有可能是Slave账号密码写错了,重新关闭Slave然后输入上面的配置命令再打开Slave即可。


如果出现SQL线程为NO状态,那么有可能是从数据库和主数据库的数据不一致造成的,或者事务回滚,如果是后者,先关闭Slave,然后先查看master的binlog和position,然后输入配置命令,再输入set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;,再重新start slave;即可,如通过是前者,那么就排查一下是不是存在哪张表没有被同步,是否存在主库存在而从库不存在的表,自己同步一下再重新配置一遍即可。


结语


在写这篇文章之前自己也被一些计算机领域的“名词”吓到过,相信有不少同学都有一样的体会,碰上某些高大上的名词总是先被吓到,例如像“分布式”、“集群”等等等等,甚至在没接触过nginx之前,连”负载均衡“、”反向代理“这样的词都让人觉得,这么高达上的词,肯定很难吧,但其实自己了解了nginx、ribbon等之后才发现,其实也就那么回事吧,没有想象中的那么难。



所以写这篇文章的初衷是想让大家对集群化或者分布式或者其他的一些技术或者解决方案不要有一种望而却步的感觉(感觉计算机领域的词都有这么一种特点,词汇高大上,但是其实思想是比较好理解的),其实自己手动配置出一个简单的集群并没有那么难。


如果学会docker之后再来配置就更加简单了,但是更希望不要只局限于会配置,配置出来的东西只能说你会配置了,但是在这层配置底下是前人做了相当多的工作,才能使我们通过简单配置就能实现一些功能,应该要深入底层,了解配置下面的工作原理,这个才是最重要的,也是体现一个程序员水平的地方。


END



相关文章
|
9月前
|
缓存 NoSQL 关系型数据库
MySQL 与 Redis 如何保证双写一致性?
我是小假 期待与你的下一次相遇 ~
944 7
|
缓存 NoSQL 关系型数据库
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
美团面试:MySQL有1000w数据,redis只存20w的数据,如何做 缓存 设计?
|
关系型数据库 应用服务中间件 nginx
Docker一键安装中间件(RocketMq、Nginx、MySql、Minio、Jenkins、Redis)
本系列脚本提供RocketMQ、Nginx、MySQL、MinIO、Jenkins和Redis的Docker一键安装与配置方案,适用于快速部署微服务基础环境。
|
9月前
|
NoSQL 算法 Redis
【Docker】(3)学习Docker中 镜像与容器数据卷、映射关系!手把手带你安装 MySql主从同步 和 Redis三主三从集群!并且进行主从切换与扩容操作,还有分析 哈希分区 等知识点!
Union文件系统(UnionFS)是一种**分层、轻量级并且高性能的文件系统**,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem) Union 文件系统是 Docker 镜像的基础。 镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。
930 6
|
Prometheus 监控 Cloud Native
除了Prometheus,还有哪些工具可以监控Docker Swarm集群的资源使用情况?
除了Prometheus,还有哪些工具可以监控Docker Swarm集群的资源使用情况?
1017 79
|
消息中间件 监控 RocketMQ
Docker部署RocketMQ5.2.0集群
本文详细介绍了如何使用Docker和Docker Compose部署RocketMQ 5.2.0集群。通过创建配置文件、启动集群和验证容器状态,您可以快速搭建起一个RocketMQ集群环境。希望本文能够帮助您更好地理解和应用RocketMQ,提高消息中间件的部署和管理效率。
2133 91
|
NoSQL Redis Docker
Docker——阿里云服务器利用docker搭建redis集群
本文详细记录了使用Docker搭建Redis集群的过程,包括检查Docker和Docker Compose的安装、创建Redis配置文件、编写`docker-compose.yml`文件、启动Redis节点、创建Redis集群的具体步骤,以及最终的验证方法。文章还提供了在多服务器环境下搭建Redis集群的注意事项,帮助读者全面了解 Redis 集群的部署流程。
1868 68
|
缓存 NoSQL 关系型数据库
Redis和Mysql如何保证数据⼀致?
1. 先更新Mysql,再更新Redis,如果更新Redis失败,可能仍然不⼀致 2. 先删除Redis缓存数据,再更新Mysql,再次查询的时候在将数据添加到缓存中 这种⽅案能解决1 ⽅案的问题,但是在⾼并发下性能较低,⽽且仍然会出现数据不⼀致的问题,⽐如线程1删除了 Redis缓存数据,正在更新Mysql,此时另外⼀个查询再查询,那么就会把Mysql中⽼数据⼜查到 Redis中 1. 使用MQ异步同步, 保证数据的最终一致性 我们项目中会根据业务情况 , 使用不同的方案来解决Redis和Mysql的一致性问题 : 1. 对于一些一致性要求不高的场景 , 不做处理例如 : 用户行为数据 ,
|
缓存 NoSQL 关系型数据库
Redis与MySQL的数据一致性
在高并发环境下,保持 Redis 和 MySQL 的数据一致性是一个复杂但重要的问题。通过采用读写穿透、写穿透、分布式锁、双写一致性保障和延时双删策略,可以有效地减少数据不一致的风险,确保系统的稳定性和可靠性。通过合理的缓存策略和数据同步机制,可以显著提升系统的性能和用户体验。
860 22
|
消息中间件 缓存 NoSQL
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)
缓存与数据库的一致性方案,Redis与Mysql一致性方案,大厂P8的终极方案(图解+秒懂+史上最全)