01、redis核心数据结构与原理

1、redis核心原理

1.1、redis单线程为什么性能这么快?

redis所有的数据都在内存中,所有的运算都是内存级别的运算,而且采用单线程避免了多线程的cpu切换引起的性能消耗。  

redis是单线程的,因此部分耗时命令需要谨慎使用,比如keys,这些命令的使用有可能导致redis卡顿。  

1.2、redis单线程如何处理那么多的并发客户端链接?

redis的IO多路复用:redis利用epoll来实现多路复用,将连接信息和事件放到队列中,依次放到文件事件分派器中,事件分派器分发给事件处理器。  

Nginx也是采用的IO多路复用原理解决C10K问题。  

1.3、数据流图

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nDhDMoXt-1647786851380)(images/ac06e81f-789f-41a2-bfbf-b6f2ee977921.jpg)]

2、redis常用数据结构和命令

3、redis持久化

3.1、RDB快照(snapshot)

默认情况下,redis将内存中的数据库快照保存在名字诶dump.rdb的二进制文件中。  

可以对redis进行设置,让它在“N秒内数据集至少有M个改动”时,自动保存一次数据集。  

比如:# save 60 1000  

    当60秒内有1000个键被改动时,自动保存一次数据集。

关闭RDB只需要将所有的save保存策略注释掉即可。

还可以手动执行命令生成RDB快照,进入redis客户端执行命令save或bgsave可以生成dump.rdb文件,每次命令执行都会将所有redis内存快照到一个新的rdb文件里,并覆盖原有rdb快照文件。save是同步命令,bgsave是异步命令,bgsave会从redis主进程fork(fork()是linux函数)出一个子进程专门用来生成rdb快照文件。

3.2、save和bgsave对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hzwU6KV0-1647786851381)(images/01eec37f-4c71-494c-9577-d0606a58b39c.png)]

4、AOF(append-only file)

快照功能并不是非常耐久(durable): 如果 Redis 因为某些原因而造成故障停机, 那么服务器将丢失最近写入、且仍未保存到快照中的那些数据。从 1.1 版本开始, Redis 增加了一种完全耐久的持久化方式: AOF 持久化,将修改的每一条指令记录进文件appendonly.aof中。

你可以通过修改配置文件来打开AOF 功能:

4.1、# appendonly yes

从现在开始, 每当 Redis 执行一个改变数据集的命令时(比如 SET), 这个命令就会被追加到 AOF 文件的末尾。这样的话, 当 Redis 重新启动时, 程序就可以通过重新执行 AOF 文件中的命令来达到重建数据集的目的。

你可以配置 Redis 多久才将数据 fsync 到磁盘一次。
  • appendfsync always:每次有新命令追加到 AOF 文件时就执行一次 fsync ,非常慢,也非常安全。
  • appendfsync everysec:每秒 fsync 一次,足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。
  • appendfsync no:从不 fsync ,将数据交给操作系统来处理。更快,也更不安全的选择。推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

4.2、AOP重写

AOF文件里可能有太多没用指令,所以AOF会定期根据内存的最新数据生成aof文件。

4.2.1、如下两个配置可以控制AOF自动重写频率

  • auto-aof-rewrite-min-size 64mb:aof文件至少要达到64M才会自动重写,文件太小恢复速度本来就很快,重写的意义不大。

  • auto-aof-rewrite-percentage 100:aof文件自上一次重写后文件大小增长了100%则再次触发重写。

    当然AOF还可以手动重写,进入redis客户端执行命令bgrewriteaof重写AOF。 注意,AOF重写redis会fork出一个子进程去做,不会对redis正常命令处理有太多影响。

4.2.2、RDB 和 AOF ,我应该用哪一个?

redis启动时如果既有rdb文件又有aof文件则优先选择aof文件恢复数据,因为aof一般来说数据更全一点。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hf6Gm6f0-1647786851381)(images/870eef63-13df-4b0b-901c-37c8db4f2abc.png)]

5、Redis 4.0 混合持久化

重启 Redis 时,我们很少使用 RDB来恢复内存状态,因为会丢失大量数据。我们通常使用 AOF 日志重放,但是重放 AOF 日志性能相对 RDB来说要慢很多,这样在 Redis 实例很大的情况下,启动需要花费很长的时间。 Redis 4.0 为了解决这个问题,带来了一个新的持久化选项——混合持久化。通过如下配置可以开启混合持久化:\*\*# aof-use-rdb-preamble yes\*\*

如果开启了混合持久化,AOF在重写时,不再是单纯将内存数据转换为RESP命令写入AOF文件,而是将重写这一刻之前的内存做RDB快照处理,并且将RDB快照内容和增量的AOF修改内存数据的命令存在一起,都写入新的AOF文件,新的文件一开始不叫appendonly.aof,等到重写完新的AOF文件才会进行改名,原子的覆盖原有的AOF文件,完成新旧两个AOF文件的替换。于是在 Redis 重启的时候,可以先加载 RDB 的内容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重启效率大幅得到提升。

混合持久化AOF文件结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YT6beVyX-1647786851382)(images/6d6443b9-15c7-4fe3-9a42-1e9446058aa0.jpg)]

6、Redis主从架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dEd3ugCQ-1647786851382)(images/4eb5beba-c80a-44c2-a74a-01f1d38d9f6b.jpg)]

6.1、Redis 主从工作原理

如果你为master配置了一个slave,不管这个slave是否是第一次连接上Master,它都会发送一个SYNC命令(redis2.8版本之前的命令)给master请求复制数据。master收到SYNC命令后,会在后台进行数据持久化通过bgsave生成最新的rdb快照文件,持久化期间,master会继续接收客户端的请求,它会把这些可能修改数据集的请求缓存在内存中。当持久化进行完毕以后,master会把这份rdb文件数据集发送给slave,slave会把接收到的数据进行持久化生成rdb,然后再加载到内存中。然后,master再将之前缓存在内存中的命令发送给slave。

当master与slave之间的连接由于某些原因而断开时,slave能够自动重连Master,如果master收到了多个slave并发连接请求,它只会进行一次持久化,而不是一个连接一次,然后再把这一份持久化的数据发送给多个并发连接的slave。

当master和slave断开重连后,一般都会对整份数据进行复制。但从redis2.8版本开始,master和slave断开重连后支持部分复制。

6.2、数据部分复制

从2.8版本开始,slave与master能够在网络连接断开重连后只进行部分数据复制。master会在其内存中创建一个复制数据用的缓存队列,缓存最近一段时间的数据,master和它所有的slave都维护了复制的数据下标offset和master的进程id,因此,当网络连接断开后,slave会请求master继续进行未完成的复制,从所记录的数据下标开始。如果master进程id变化了,或者从节点数据下标offset太旧,已经不在master的缓存队列里了,那么将会进行一次全量数据的复制。

从2.8版本开始,redis改用可以支持部分数据复制的命令PSYNC去master同步数据主从复制(全量复制)流程图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cbu1jBkT-1647786851383)(images/a503c5f0-cca4-440e-88a8-07ae7a39ba85.jpg)]

主从复制(部分复制)流程图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-omXFz2iE-1647786851383)(images/949ed913-c9c7-4fd8-b4f7-46181f51b5cd.jpg)]

6.3、redis主从架构搭建:

6.3.1、复制redis.conf 文件三分,分别为redis-6381.conf、redis-6382.conf 、redis-6383.conf

[root@localhost redis-5.0.5]# cp redis.conf redis-6381.conf
[root@localhost redis-5.0.5]# cp redis.conf redis-6382.conf
[root@localhost redis-5.0.5]# cp redis.conf redis-6383.conf

6.3.2、修改三分配置文件的端口信息

# Redis使用后台模式
daemonize yes
# 关闭保护模式
protected-mode no
# 注释以下内容开启远程访问
# bind 127.0.0.1
# 修改启动端口为6381
port 6381
# 修改pidfile指向路径
pidfile /var/run/redis_6379.pid

6.3.3、分别启动三个redis进程,使用创建的配置文件

[root@localhost redis-5.0.5]# src/redis-server redis-6381.conf 
2259:C 07 Aug 2020 11:00:24.459 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2259:C 07 Aug 2020 11:00:24.459 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=2259, just started
2259:C 07 Aug 2020 11:00:24.459 # Configuration loaded
[root@localhost redis-5.0.5]# src/redis-server redis-6382.conf 
2264:C 07 Aug 2020 11:00:28.704 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2264:C 07 Aug 2020 11:00:28.704 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=2264, just started
2264:C 07 Aug 2020 11:00:28.704 # Configuration loaded
[root@localhost redis-5.0.5]# src/redis-server redis-6383.conf 
2269:C 07 Aug 2020 11:00:32.177 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
2269:C 07 Aug 2020 11:00:32.177 # Redis version=5.0.5, bits=64, commit=00000000, modified=0, pid=2269, just started
2269:C 07 Aug 2020 11:00:32.177 # Configuration loaded
[root@localhost redis-5.0.5]# ps -ef |grep redis
root       2260      1  0 11:00 ?        00:00:00 src/redis-server *:6381
root       2265      1  0 11:00 ?        00:00:00 src/redis-server *:6382
root       2270      1  0 11:00 ?        00:00:00 src/redis-server *:6383
root       2289   2219  0 11:02 pts/0    00:00:00 grep --color=auto redis

6.3.4、设置主从节点

\`\`\`    在Redis中设置主从有2种方式:

在redis.conf中设置replicaof:replicaof 使用redis-cli客户端连接到redis服务,执行slaveof命令:slaveof


```Shell
# 将6382 设置成master,分别将6381、6383链接到master上
[root@localhost redis-5.0.5]# src/redis-cli -p 6381
127.0.0.1:6381> slaveof localhost 6382
OK
127.0.0.1:6381> exit
[root@localhost redis-5.0.5]# src/redis-cli -p 6383
127.0.0.1:6383> slaveof localhost 6382
OK

6.3.5、查看主从信息

登录主节点6382上,使用info replication查看主从节点信息  
[root@localhost redis-5.0.5]# src/redis-cli -p 6382
127.0.0.1:6382> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=::1,port=6381,state=online,offset=112,lag=1
slave1:ip=::1,port=6383,state=online,offset=112,lag=1
master_replid:02fc1f89594b941b4dcffc10bf89ad1d4350212e
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:112
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:112
127.0.0.1:6382> 

6.3.6、测试,主节点写,从节点读取数据

[root@localhost redis-5.0.5]# src/redis-cli -p 6382
127.0.0.1:6382> set xuebin test
OK
127.0.0.1:6382> get xuebin
"test"
127.0.0.1:6382> 
[root@localhost redis-5.0.5]# src/redis-cli -p 6381
127.0.0.1:6381> get xuebin
"test"
127.0.0.1:6381> 
[root@localhost redis-5.0.5]# src/redis-cli -p 6383
127.0.0.1:6383> get xuebin
"test"

6.4、Jedis连接代码示例

6.4.1、引入maven

<dependency>
    <groupId>redis.clientsgroupId>
    <artifactId>jedisartifactId>
    <version>2.9.0version>
dependency>

6.4.2、编写Java测试类

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

/**
 * desc:
 * author: Administrator
 * date: 2020/8/7
 */
public class JedisPoolTest {
    public static void main(String[] args) {

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);
        String host = "192.168.1.101";
        int port = 6381;
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 30000, null);

        Jedis jedis = jedisPool.getResource();
        System.out.println(jedis.set("xb2222", "xuebin"));
        System.out.println(jedis.get("xb2222"));
    }
}

// 测试结果

OK
xuebin

6.5、下redis管道

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

import java.util.List;

/**
 * desc:
 * author: Administrator
 * date: 2020/8/7
 */
public class JedisPoolTest {
    public static void main(String[] args) {
        // 1、JedisPool示例
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);
        String host = "192.168.1.101";
        int port = 6381;
        JedisPool jedisPool = new JedisPool(jedisPoolConfig, host, port, 30000, null);

        Jedis jedis = jedisPool.getResource();
        System.out.println(jedis.set("xb2222", "xuebin"));
        System.out.println(jedis.get("xb2222"));

        // 2、管道示例
        Pipeline pipeline = jedis.pipelined();
        for (int i = 0; i < 10; i++){
            pipeline.incr("xb:pl");
            pipeline.set("xb:"+i, "xb:value"+i);
        }

        List<Object> result = pipeline.syncAndReturnAll();
        System.out.println(result);
    }
}

Connected to the target VM, address: '127.0.0.1:64020', transport: 'socket'
OK
xuebin
[11, OK, 12, OK, 13, OK, 14, OK, 15, OK, 16, OK, 17, OK, 18, OK, 19, OK, 20, OK]
Disconnected from the target VM, address: '127.0.0.1:64020', transport: 'socket'

6.6、调用lua脚本

// 3、调用lua脚本
// lua脚本模拟一个商品减库存的原子操作
// lua脚本命令执行方式:redis‐cli ‐‐eval /tmp/test.lua , 10
// jedis.set("product_count_10016", "15"); //初始化商品10016的库存
String script = " local count = redis.call('get', KEYS[1]) " +
    " local a = tonumber(count) " +
    " local b = tonumber(ARGV[1]) " +
    " if a >= b then " +
    " redis.call('set', KEYS[1], count‐b) " +
    " return 1 " +
    " end " +
    " return 0 ";
Object obj = jedis.eval(script, Collections.singletonList("product_count_10016"), Collections.singletonList("10"));
System.out.println("lua result: "+obj);

7、Redis哨兵高可用架构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sXngtsVi-1647786851384)(images/f399ea19-3aea-47fb-87d1-086dd6ec2708.jpg)]

sentinel哨兵是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点发生变化,哨兵会第一时间感知到,并且将新的redis主节点通知给client端(这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息)。

7.1、redis哨兵架构搭建步骤

7.1.1、复制三分sentinel配置文件,并修改相关内容

[root@localhost redis-5.0.5]# cp sentinel.conf sentinel-26381.conf 
[root@localhost redis-5.0.5]# cp sentinel.conf sentinel-26382.conf 
[root@localhost redis-5.0.5]# cp sentinel.conf sentinel-26383.conf 

# 修改配置文件中如下内容
port 26381
daemonize yes
pidfile "/var/run/redis‐sentinel‐26379.pid" 
logfile "26379.log"
# sentinel monitor     
# quorum是一个数字,指明当有多少个sentinel认为一个master失效时(值一般为:sentinel总数/2 + 1),master才算真正失效
sentinel monitor mymaster 192.168.1.101 6381 2

注意:西东多个sentinel时,sentinel的myid不能相同,否则sentinel不能发现对方,查看信息时只有一个sentinel,没法实现高可用。可以手动修改sentinel的值或者删除,系统自动分配

#sentinel myid af97b2ad93954c296bb20318133476adbc3a58a4

7.1.2、启动sentinel

[root@localhost redis-5.0.5]# src/redis-sentinel sentinel-26381.conf;
[root@localhost redis-5.0.5]# src/redis-sentinel sentinel-26382.conf;
[root@localhost redis-5.0.5]# src/redis-sentinel sentinel-26383.conf;
[root@localhost redis-5.0.5]# ps -ef |grep sentinel
root       2872      1  0 22:23 ?        00:00:00 src/redis-sentinel *:26381 [sentinel]
root       2877      1  0 22:23 ?        00:00:00 src/redis-sentinel *:26382 [sentinel]
root       2882      1  0 22:23 ?        00:00:00 src/redis-sentinel *:26383 [sentinel]
root       2887   2219  0 22:23 pts/0    00:00:00 grep --color=auto sentinel

7.1.3、链接sentinel,查看相关信息

[root@localhost redis-5.0.5]# src/redis-cli -p 26381
127.0.0.1:26381> info sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.1.101:6381,slaves=2,sentinels=3

7.2、哨兵的Jedis连接代码

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

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

/**
 * desc: redis哨兵模式 Java链接测试
 * author: Administrator
 * date: 2020/8/8
 */
public class JedisSentinelTest {
    public static void main(String[] args) {

        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(20);
        jedisPoolConfig.setMaxIdle(10);
        jedisPoolConfig.setMinIdle(5);

        String masterName = "mymaster";
        Set<String> sentinels = new HashSet<>();

        sentinels.add(new HostAndPort("192.168.1.101", 26381).toString());
        sentinels.add(new HostAndPort("192.168.1.101", 26382).toString());
        sentinels.add(new HostAndPort("192.168.1.101", 26383).toString());

        JedisSentinelPool jedisSentinelPool = new JedisSentinelPool(masterName, sentinels, jedisPoolConfig, 3000, null);

        Jedis jedis = null;
        try {
            jedis = jedisSentinelPool.getResource();

            System.out.println(jedis.set("sentinel:xuebin", "xuebin"));
            System.out.println(jedis.get("sentinel:xuebin"));
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (jedis != null){
                jedis.close();
            }
        }
    }
}

八月 08, 2020 11:17:26 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Trying to find master from available Sentinels...
八月 08, 2020 11:17:26 下午 redis.clients.jedis.JedisSentinelPool initSentinels
信息: Redis master running at 192.168.1.101:6381, starting Sentinel listeners...
八月 08, 2020 11:17:26 下午 redis.clients.jedis.JedisSentinelPool initPool
信息: Created JedisPool to master at 192.168.1.101:6381
OK
xuebin

7.3、哨兵的Spring Boot整合Redis连接

7.3.1、引入maven依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-pool2</artifactId>
</dependency>

7.3.2、YML 文件配置redis

server:
  port: 8001
spring:
  application:
    name: redis-start
  redis:
    database: 0
    timeout: 3000
    lettuce:
      pool:
        max-idle: 50
        max-active: 100
        max-wait: 1000
    sentinel: #哨兵模式
      master: mymaster #主服务器所在集群名称
      nodes: 192.168.1.101:26381,192.168.1.101:26382,192.168.1.101:26383

7.3.3、Spring Boot启动类,启动后操作redsi

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.redis.core.StringRedisTemplate;

import javax.annotation.PostConstruct;

/**
 * desc:
 * author: Administrator
 * date: 2020/8/8
 */
@SpringBootApplication
public class RedisTempterApplication {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public static void main(String[] args) {
        SpringApplication.run(RedisTempterApplication.class, args);

    }

    /**
     * 测试节点挂了哨兵重新选举新的master节点,客户端是否能动态感知到
     * 新的master选举出来后,哨兵会把消息发布出去,客户端实际上是实现了一个消息监听机制,
     * 当哨兵把新master的消息发布出去,客户端会立马感知到新master的信息,从而动态切换访问的maste rip
     */
    @PostConstruct
    public void testSentinel() {
        int i = 1;
        while (true){
            try {
                stringRedisTemplate.opsForValue().set("testSentinel:"+i, i+"");
                System.out.println("设置key:"+ "testSentinel:" + i);
                i++;
                Thread.sleep(2000);
            }catch (Exception e){
                System.err.println("错误: "+e.getMessage());
            }
        }
    }
}

7.3.4、测试结果

2020-08-09 00:04:50.128  INFO 17660 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2020-08-09 00:04:50.145  INFO 17660 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8ms. Found 0 Redis repository interfaces.
2020-08-09 00:04:50.351  INFO 17660 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8001 (http)
2020-08-09 00:04:50.356  INFO 17660 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-08-09 00:04:50.356  INFO 17660 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-08-09 00:04:50.405  INFO 17660 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-08-09 00:04:50.405  INFO 17660 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 741 ms
设置key:testSentinel:1
设置key:testSentinel:2
设置key:testSentinel:3
设置key:testSentinel:4
设置key:testSentinel:5
设置key:testSentinel:6
设置key:testSentinel:7
设置key:testSentinel:8

7.3.6、测试主节点被kill,系统是否自动选主

# 直接kill掉master节点

2020-08-09 00:04:49.628  INFO 17660 --- [           main] com.redis.start.RedisTempterApplication  : Starting RedisTempterApplication on PC-201910131736 with PID 17660 (E:\workspace\java\SpringBootAll\redis-start\target\classes started by Administrator in E:\workspace\java\SpringBootAll)
2020-08-09 00:04:49.630  INFO 17660 --- [           main] com.redis.start.RedisTempterApplication  : No active profile set, falling back to default profiles: default
2020-08-09 00:04:50.127  INFO 17660 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Multiple Spring Data modules found, entering strict repository configuration mode!
2020-08-09 00:04:50.128  INFO 17660 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data Redis repositories in DEFAULT mode.
2020-08-09 00:04:50.145  INFO 17660 --- [           main] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8ms. Found 0 Redis repository interfaces.
2020-08-09 00:04:50.351  INFO 17660 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8001 (http)
2020-08-09 00:04:50.356  INFO 17660 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2020-08-09 00:04:50.356  INFO 17660 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet engine: [Apache Tomcat/9.0.37]
2020-08-09 00:04:50.405  INFO 17660 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2020-08-09 00:04:50.405  INFO 17660 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 741 ms
设置key:testSentinel:1
设置key:testSentinel:2
。。。。。。。。。。。。
设置key:testSentinel:16
设置key:testSentinel:17
2020-08-09 00:05:23.980  INFO 17660 --- [xecutorLoop-1-1] i.l.core.protocol.ConnectionWatchdog     : Reconnecting, last destination was /192.168.1.101:6383
2020-08-09 00:05:24.989  WARN 17660 --- [ioEventLoop-4-4] i.l.core.protocol.ConnectionWatchdog     : Cannot reconnect to [192.168.1.101:6383]: Connection refused: no further information: /192.168.1.101:6383
错误: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)
# 主节点被kill掉,链接失败报错
错误: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)
错误: Redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException: Command timed out after 3 second(s)
2020-08-09 00:06:11.680  INFO 17660 --- [xecutorLoop-1-3] i.l.core.protocol.ConnectionWatchdog     : Reconnecting, last destination was 192.168.1.101:6383

# 重新选取主节点完成,链接192.168.1.101:6382 成功
2020-08-09 00:06:11.689  INFO 17660 --- [ioEventLoop-4-2] i.l.core.protocol.ReconnectionHandler    : Reconnected to 192.168.1.101:6382

# 重新选取主节点完成,继续存储key值
设置key:testSentinel:18
设置key:testSentinel:19
设置key:testSentinel:20
。。。。。。。。。。。。。
设置key:testSentinel:43
设置key:testSentinel:44

7.3.7、重启主节点

重启主节点,sentinel会将原来主节点加都原有主从结构中,并将其设置为从节点。同事修改配置文件从新的主节点同步数据,该节点只读等信息。

配置信息会加导配置文件末尾。  

redis-6383.conf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WWUToBgZ-1647786851384)(images/20b254c3-4c7d-4e61-8030-36820ced4807.png)]

sentinel-26383.conf

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZBuA2np-1647786851384)(images/9f014e04-ab93-4636-9570-cd2f29e1f4e2.png)]

你可能感兴趣的:(AI:Redis,redis,分布式,中间件)