redis搭建主从同步

x33g5p2x  于2021-10-25 转载在 Redis  
字(7.4k)|赞(0)|评价(0)|浏览(158)

1.CAP原理

1.在分布式系统中,基本所有的系统都只能实现CAP中的两个选项,P是要必定实现的。

2.C:consitent,代表一致性,A:availablity,代表可用性,P:partition tolerance 分布式容忍性。

3.在redis中,redis其实就选择了CA这两个选项,假如网络断开了,主从连接失败,主从都可以继续使用,数据有可能不一致,但是redis会尽量保持数据一致,就是网络再次连接时,从机会尽量同步更新主机的数据。

2.主从同步基础搭建

1.前提:
本人这里只是在linux上开一个虚拟机,并不是启动三台虚拟机,所以,要有要启动三个redis服务器的话,就得有三个redis的配置文件,分别配置不同的端口号还有其他的一些信息

2.修改原来redis文件名为redis6379.conf

mv redis.conf redis6379.conf

3.修改redis6379.conf文件里面的内容
1)如果开启aof,则先关闭aof

2)修改log文件名,便于区分

3)修改dump的文件名,便于区分

4.拷贝多两个配置文件

cp redis6379.conf redis6380.conf
 cp redis6379.conf redis6381.conf

5.vi redis6380.conf和redis6381.conf文件,修改它们的端口号,dump文件名再保存
redis6380文件执行

:%s/6379/6380/g

redis6381文件执行

:%s/6379/6381/g

6.同时启动三个redis服务

redis-server redis6379.conf
redis-server redis6380.conf
redis-server redis6381.conf

7.先前打开的终端连接到6379的redis,再打开两个终端,分别连接到6380和6381这两个端口号对应的redis服务器,三个终端都连接上redis服务器

redis-cli -a root123 -p 6379
redis-cli -a root123 -p 6380
redis-cli -a root123 -p 6381

8.我这里用6379的redis作为主机,其余两个作为从机
9.修改redis6380.conf和redis6381.conf文件,主要是修改连接到主机时需要的密码,我这里所有的配置文件中密码都为root123

10.在从机6380上设置6379作为其主机

slaveof 127.0.0.1 6379

11.查看连接信息

info replication

12.在主机6379set一个key,如果从机也可以get得到这个值,那么代表主从连接配置成功了,但是这种主从配置都只是暂时的,因为重启后,每一个redis服务器又全都是master身份了,要永久生效,得去修改redis的配置文件。
主机6379:

从机6380:

13.以上的slaveof 127.0.0.1 6379,可以指定主机,但是在重启服务器后会失效,如下可以在两个从机的redis配置文件配置连接到主机的地址永久生效

14.现在无论如何,每次重启6380的redis服务后,它都是一个从机,其主机是6379的redis服务器

15.redis2.6版本后,其设置了从机只能get,不能set。但是我们也可以去到redis的配置文件里将下面这个参数的值改为no,从机也可以进行set操作了

16.主从复制的流程简单来说可以分为如下几个步骤
1)从机启动,连接到主机后,会发送一个sync文件
2)主机在接收到命令后,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令
3)在后台进程执行完毕之后,主机将传送整个数据文件到各个从机,一次性完成同步
4)全量复制:从机在接收到主机发送过来的数据文件,将其保存到磁盘中并且加载到内存中
5)增量复制:主机将收集所有新的修改命令,依次传给从机,从机执行接收到的命令,完成数据同步
6)注意:从机只要是重新连接到主机,全量复制都会执行

3.接力模式

1.现在我们的两个从机在配置文件那里都设置了同一个主机,这偶尔会给主机造成一点的压力

2.这里将6381从机的master改为6380

3.可以看到6381从机依然可以同步到6379主机的数据,类似于接力一样

4.哨兵模式

1.情景
假设现在有一个主机,两个从机,从机均已连接到主机,能拿到数据,这时候,如果主机崩掉了,整个系统就蹦了,那么如何解决这种情况呢?redis提供了一种哨兵模式来解决这个问题

2.哨兵模式
简单理解就是有一个监控监控着主机,如果主机突然蹦了,没有主机了,那么其会从剩下的从机中,重新选举出一个来充当主机,避免系统崩掉的情况!

3.如何配置哨兵模式?
1)它的配置主要在sentinel.conf这个文件里

vi sentinel.conf

2)修改这行配置,最后的那个数改为1,1代表有多少个哨兵来监控6379主机

sentinel monitor mymaster 127.0.0.1 6379 1

3)添加这行配置,要监控的主机的连接密码

sentinel auth-pass mymaster root123

3)启动哨兵模式

redis-sentinel sentinel.conf

4)这时候,我们在6379端执行shutdown命令后,再查看是否重新选举了主机,这个要等一会时间
,如下可以看到,6381被选举成为了主机,注意,这个时候,如果6379重启服务后,它也是一个从机了,这个配置是永久生效的

6381成为了主机

5.jedis操作哨兵模式

1.准备工作
1)所有的redis实例都要配置一个参数,就是masterauth,还有从机指定主机为6379(在redis.conf中配置)

6379的配置文件

6380的配置文件

6381的配置文件

2)所有redis实例都需要绑定地址,地址为虚拟机ip地址

6379的配置文件

6380的配置文件

6381的配置文件

3)哨兵监控的master也要改成ip地址

2.启动三个redis服务器,并且启动哨兵模式

redis-server redis6379.conf
redis-server redis6380.conf
redis-server redis6381.conf
redis-sentinel sentinel.conf

3.打开三个终端,测试通过redis-cli命令测试是否能连接到redis服务器

redis-cli -p 6379 -a root123 -h 192.168.244.132

redis-cli -p 6380 -a root123 -h 192.168.244.132

redis-cli -p 6381 -a root123 -h 192.168.244.132

4.查看主机的相关信息,可以看到有两个从机

5.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>distribute-lock</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <!--json依赖-->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.12.3</version>
        </dependency>
        <!--jedis依赖-->
        <dependency>
               <groupId>redis.clients</groupId>
               <artifactId>jedis</artifactId>
               <version>3.2.0</version>
               <type>jar</type>
               <scope>compile</scope>
        </dependency>
        <!--bloom依赖-->
        <dependency>
               <groupId>com.redislabs</groupId>
               <artifactId>jrebloom</artifactId>
               <version>1.2.0</version>
        </dependency>
    </dependencies>

</project>

6.sentinelTest

package com.yl;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;

import java.util.HashSet;
import java.util.Set;

public class SentinelTest {
    public static void main(String[] args) {
        //连接池信息
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(10);
        config.setMaxWaitMillis(1000);
        //主机名
        String masterName = "mymaster";
        //哨兵模式的配置
        Set<String> set = new HashSet<>();
        set.add("192.168.244.132:26379");
        JedisSentinelPool sentinelPool = new JedisSentinelPool(masterName,set,config,"root123");
        Jedis jedis = null;
        while (true) {
            try {
                //获取jedis实例
                jedis = sentinelPool.getResource();
                System.out.println(jedis.get("k1"));
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (jedis != null) {
                    jedis.close();
                }
                try {
                    Thread.sleep(6000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

7.未作任何操作之前,都可以从redis服务器获取数据

8.那么现在,我们在6379主机执行shutdown

9.可以看到控制台报错了

10,但是过一段时间,又可以获取到数据了

11.在linux上也可以看到,6380被选举为了主机

6.springboot操作哨兵模式

1.pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.6</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yl</groupId>
    <artifactId>sentinel</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>sentinel</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2.application.properties

# redis的配置
# 密码
spring.redis.password=root123
#超时时间
spring.redis.timeout=6000
# 要监控的主机名
spring.redis.sentinel.master=mymaster
# 哨兵的端口
spring.redis.sentinel.nodes=192.168.244.132:26379

3.test

package com.yl.sentinel;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;

@SpringBootTest
class SentinelApplicationTests {

    @Autowired
    StringRedisTemplate redisTemplate;

    @Test
    void contextLoads() {
        while (true) {
            try {
                String k1 = redisTemplate.opsForValue().get("k1");
                System.out.println(k1);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

}

4.未操作之前的结果

5.在主机6379执行shutdown后,发现报错了,并且过了一会,又正常了

报错

过一段时间,又正常了

linux上发现6381成为了主机

相关文章

微信公众号

最新文章

更多