Redis相关问题

一、持久化

Redis为持久化提供了两种方式:

  • RDB:在指定的时间间隔能对你的数据进行快照存储。
  • AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据。

1.1 RDB(Redis Database)的原理

Redis会定期保存数据快照至一个rbd文件中,并在启动时自动加载rdb文件,恢复之前保存的数据。可以在配置文件中配置Redis进行快照保存的时机:

save [seconds] [changes]

意为在[seconds]秒内如果发生了[changes]次数据修改,则进行一次RDB快照保存,例如

save [60] [100]

该语句会让Redis每60秒检查一次数据变更情况,如果发生了100次或以上的数据变更,则进行RDB快照保存。可以配置多条save指令,让Redis执行多级的快照保存策略。Redis默认开启RDB快照。也可以通过BGSAVE命令手动触发RDB快照保存。

RDB的优点:

  • 对性能影响最小。如前文所述,Redis在保存RDB快照时会fork出子进程进行,几乎不影响Redis处理客户端请求的效率。
  • 每次快照会生成一个完整的数据快照文件,所以可以辅以其他手段保存多个时间点的快照(例如把每天0点的快照备份至其他存储媒介中),作为非常可靠的灾难恢复手段。
  • 使用RDB文件进行数据恢复比使用AOF要快很多。

RDB的缺点:

  • 快照是定期生成的,所以在Redis crash时或多或少会丢失一部分数据。
  • 如果数据集非常大且CPU不够强(比如单核CPU),Redis在fork子进程时可能会消耗相对较长的时间,影响Redis对外提供服务的能力。

1.2 AOF(append only file)的原理

采用AOF持久方式时,Redis会把每一个写请求都记录在一个日志文件里。在Redis重启时,会把AOF文件中记录的所有写操作顺序执行一遍,确保数据恢复到最新。AOF默认是关闭的,如要开启,进行如下配置:

appendonly yes

AOF提供了三种fsync配置,always/everysec/no,通过配置项[appendfsync]指定:

  • appendfsync no:不进行fsync,将flush文件的时机交给OS决定,速度最快 appendfsync
  • always:每写入一条日志就进行一次fsync操作,数据安全性最高,但速度最慢 appendfsync
  • everysec:折中的做法,交由后台线程每秒fsync一次

随着AOF不断地记录写操作日志,因为所有的操作都会记录,所以必定会出现一些无用的日志。大量无用的日志会让AOF文件过大,也会让数据恢复的时间过长。不过Redis提供了AOF rewrite功能,可以重写AOF文件,只保留能够把数据恢复到最新状态的最小写操作集。

AOF rewrite可以通过BGREWRITEAOF命令触发,也可以配置Redis定期自动进行:

auto-aof-rewrite-percentage 100auto-aof-rewrite-min-size 64mb

上面两行配置的含义是,Redis在每次AOF rewrite时,会记录完成rewrite后的AOF日志大小,当AOF日志大小在该基础上增长了100%后,自动进行AOF rewrite。同时如果增长的大小没有达到64mb,则不会进行rewrite。

AOF的优点:

  • 最安全,在启用appendfsync always时,任何已写入的数据都不会丢失,使用在启用appendfsync everysec也至多只会丢失1秒的数据。
  • AOF文件在发生断电等问题时也不会损坏,即使出现了某条日志只写入了一半的情况,也可以使用redis-check-aof工具轻松修复。
  • AOF文件易读,可修改,在进行了某些错误的数据清除操作后,只要AOF文件没有rewrite,就可以把AOF文件备份出来,把错误的命令删除,然后恢复数据。

AOF的缺点:

  • AOF文件通常比RDB文件更大
  • 性能消耗比RDB高
  • 数据恢复速度比RDB慢

数据持久化引发的延迟

Redis的数据持久化工作本身就会带来延迟,需要根据数据的安全级别和性能要求制定合理的持久化策略:

  • AOF + fsync always的设置虽然能够绝对确保数据安全,但每个操作都会触发一次fsync,会对Redis的性能有比较明显的影响
  • AOF + fsync every second是比较好的折中方案,每秒fsync一次 AOF + fsync
  • never会提供AOF持久化方案下的最优性能 使用RDB持久化通常会提供比使用AOF更高的性能,但需要注意RDB的策略配置
  • 每一次RDB快照和AOF Rewrite都需要Redis主进程进行fork操作。fork操作本身可能会产生较高的耗时,与CPU和Redis占用的内存大小有关。根据具体的情况合理配置RDB快照和AOF Rewrite时机,避免过于频繁的fork带来的延迟

Redis在fork子进程时需要将内存分页表拷贝至子进程,以占用了24GB内存的Redis实例为例,共需要拷贝24GB / 4kB * 8 = 48MB的数据。在使用单Xeon 2.27Ghz的物理机上,这一fork操作耗时216ms。

可以通过INFO命令返回的latest_fork_usec字段查看上一次fork操作的耗时(微秒)

1.3 最后

不过大多数应用场景下,建议至少开启RDB方式的数据持久化。Redis 对于数据备份是非常友好的, 因为你可以在服务器运行的时候对 RDB 文件进行复制: RDB 文件一旦被创建, 就不会进行任何修改。 当服务器要创建一个新的 RDB 文件时, 它先将文件的内容保存在一个临时文件里面, 当临时文件写入完毕时, 程序才使用 rename(2) 原子地用临时文件替换原来的 RDB 文件。

参考:https://baijiahao.baidu.com/s?id=1611955931705092609&wfr=spider&for=pc

二、Redis主从复制

作用:

  1. 数据副本:不仅在主节点(master)上存在数据,从结点(slave)上也会存在同步到的数据。
  2. 读写分离:在主节点写数据,从结点读数据,使得负载均衡。

Redis的配置文件,修改相应的配置改变主从结点关系:
https://www.cnblogs.com/metu/p/9609604.html
其中几个重要命令:
port 6379: 绑定监听的端口号
bind 127.0.0.1:指定 redis 只接收来自于该 IP 地址的请求,如果不进行设置,那么将处理所有请求
dbfilename dump.rdb:RDB文件名称,在同一主机中开启多个Redis,RDB文件名称需要区别开来,否则数据产生混乱
slaveof <masterip> <masterport>:从结点slave复制对应的主节点master
slave-read-only yes:作为从结点,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。

通过持久化功能,Redis保证了即使在服务器宕机情况下数据的丢失非常少。但是如果这台服务器出现了硬盘故障、系统崩溃等等,不仅仅是数据丢失,很可能对业务造成灾难性打击。为了避免单点故障通常的做法是将数据复制多个副本保存在不同的服务器上,这样即使有其中一台服务器出现故障,其他服务器依然可以继续提供服务。当然Redis提供了多种高可用方案包括:主从复制、哨兵模式的主从复制、以及集群。
 
在主从复制中,数据库分为两类,一类是主库(master),另一类是同步主库数据的从库(slave)。主库可以进行读写操作,当写操作导致数据变化时会自动同步到从库。而从库一般是只读的(特定情况也可以写,通过参数slave-read-only指定),并接受来自主库的数据,一个主库可拥有多个从库,而一个从库只能有一个主库。这样就使得redis的主从架构有了两种模式:一类是一主多从,二类是“链式主从复制”–主->从->主-从。
 在这里插入图片描述
 在这里插入图片描述
对于一主多从的复制架构不必多说,这里解释下链式主从复制:如上图2,主库A的数据会同步到从库B和从库C,而B又是从库D和从库E的主库,所以B的数据会同步到从库D和从库E。如果向B中写数据,数据只能同步到D和E中,所以对于这种架构数据的一致性将不能保持,也不推荐这种架构。

2.1 复制原理

redis复制过程可分为三个阶段:

  • 复制初始化阶段
  • 数据同步阶段
  • 命令传播阶段

2.1.1 复制初始化

当执行完slaveof masterip port 命令时候,从库根据指明的master节点ip和port向主库发起socket连接,主库收到socket连接之后将连接信息保存,此时连接建立;

当socket连接建立完成以后,从库向主库发送ping命令,以确认主库是否可用,此时的结果返回如果是PONG则代表主库可以用,否则可能出现超时或者主库此时在处理其他任务阻塞那么此时从库将断开socket连接,然后进行重试;

如果主库连接设置了密码,则从库需要设置masterauth参数,此时从库会发送auth命令,命令格式为“auth + 密码”进行密码验证,其中密码为masterauth参数配置的密码,需要注意的是如果主库设置了密码验证,从库未配置masterauth参数则报错,socket连接断开。

当身份验证完成以后,从节点发送自己的监听端口,主库保存其端口信息,此时进入下一个阶段:数据同步阶段。

2.1.2 数据同步阶段

主库和从库都确认对方信息以后,便可开始数据同步,此时从库向主库发送syn/cpsync命令,主库收到该命令后判断是进行增量复制还是全量复制,然后根据策略进行数据的同步,当主库有新的写操作时候,此时进入复制第三阶段:命令传播阶段。

在这里插入图片描述
runId:此时的主机的点的标识号,每次Redis结点重启时会改变这个标识号。根据runId可以判断该结点是否重启,若重启,主从结点间就会进行一次全量复制。

offset:偏移地址,标识该结点现在的命令到哪里了。因为从结点一般不能写入数据,故在经过一段时间同步时,其偏移地址与主节点的是有不同的。有不同就会进行增量复制(从结点经过了一次全量复制)。

在进行全量复制时,此时主节点仍在接收客户端的命令,它会先将命令放入主节点内的缓冲当中,待全量复制结束之后,就将缓存中的数据发送给从结点。
在这里插入图片描述
在这里插入图片描述

全量复制:

在redis2.6以及以前的版本,复制采用sync命令,当一个从库启动后,会向主库发送sync命令,主库收到sync命令后执行bgsave后台保存RDB快照(该过程在上一篇已经详细介绍),同时将快照保存期间接收的写命令添加到缓冲队列。当主服务器的BGSAVE命令完成时,主服务器会将这个RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。之后,主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器当前所处的数据库状态。
在这里插入图片描述

增量复制:

在Redis2.6之前,主从断开重连后,一定会进行一次快照操作然后将快照发送给从数据库,即使断开期间只有几条命令被执行,这就使得断开重连后的数据恢复过程效率很低。在Redis2.8之后,主从断开重连后会根据断开之前最新的命令偏移量进行增量复制。

1)主服务器在同步命令到从服务器的时候,会先将命令放入一个缓冲队列中并记录一个复制偏移量,同时主从服务器都会记录一个主服务器的运行ID。

2)当主从断开重连后,会判断主服务器保存的运行ID和从服务器发送过来的运行ID是否相同,相同则将从复制偏移量开始往后的所有命令一并发送给从服务器。如果不同,则进行一次复制初始化(将RDB快照和和这期间缓存起来的命令一并发送给主服务器)。

3)缓冲队列的大小默认是1MB,可以在 redis.conf 中的配置项 repl-backlog-size 进行设置,还有一个配置项 repl-backlog-ttl,表示当主从断开后,缓冲队列的缓存时间。
在这里插入图片描述
2.1.3 命令传播

在同步操作执行完毕之后,主从服务器两者的数据库状态将达到一致状态,但这种一致并不会是一成不变的,每当主服务器执行客户端发送的写命令时,主从服务器的数据库就有可能被修改,并导致主从服务器状态不再一致。

为了让主从服务器再次回到一致状态,主服务器需要将对从服务器执行命令传播操作:主服务器会将自己执行的写命令,发送给从服务器执行,当从服务器执行命令之后,主从服务器将再次回到一致状态。
在这里插入图片描述
性能讨论

全量复制时占用CPU及内存都很高,需要尽量避免全量复制。产生全量复制的原因有三种,如下图,其中也说明了规避方法。
对于第一次全量复制,可将Redis的最大内存设置小些,这样主节点较小,复制时产生的代价就比较小。同时低峰指的是在凌晨进行第一次全量复制,此时用户数目较少。
eXJhbWlk,size_16,color_FFFFFF,t_70
在这里插入图片描述

2.2 乐观复制策略

Redis采用乐观复制的策略,容忍在一定时间内主从数据库的内容不同,保存最终的数据会是一样的。这个策略保证了性能,在复制的时候,主数据库并不阻塞,照样处理客户端的请求。
Redis提供了配置来限制只有当数据库至少同步给指定数量的从数据库时,主数据库才可写,否则返回错误。配置是:min-slaves-to-write、min-slavesmax-lag。

参考:https://www.cnblogs.com/helbing/p/5261274.html
https://www.cnblogs.com/wdliu/p/9407179.html
https://blog.csdn.net/yanghan1222/article/details/81234220

三、Redis单线程、高并发的原因

3.1 Redis能够适用高并发环境的原因

  1. Redis是纯内存数据库,一般都是简单的存取操作,线程占用的时间很多,时间的花费主要集中在IO上,所以读取速度快。
  2. 再说一下IO,Redis使用的是非阻塞IO,IO多路复用,使用了单线程来轮询描述符,将数据库的开、关、读、写都转换成了事件,减少了线程切换时上下文的切换和竞争。
  3. Redis采用了单线程的模型,保证了每个操作的原子性,也减少了线程的上下文切换和竞争。
  4. 另外,数据结构也帮了不少忙,Redis全程使用hash结构,读取速度快,还有一些特殊的数据结构,对数据存储进行了优化,如压缩表,对短数据进行压缩存储,再如,跳表,使用有序的数据结构加快读取的速度。
  5. 还有一点,Redis采用自己实现的事件分离器,效率比较高,内部采用非阻塞的执行方式,吞吐能力比较大。

3.2 单线程能够处理多个连接请求的原理

采用多路 I/O 复用技术(Epoll)可以让单个线程高效的处理多个连接请求(尽量减少网络IO的时间消耗)

3.2.1 多路I/O复用

(1) 网络IO都是通过Socket实现,Server在某一个端口持续监听,客户端通过Socket(IP+Port)与服务器建立连接(ServerSocket.accept),成功建立连接之后,就可以使用Socket中封装的InputStream和OutputStream进行IO交互了。针对每个客户端,Server都会创建一个新线程专门用于处理

(2) 默认情况下,网络IO是阻塞模式,即服务器线程在数据到来之前处于【阻塞】状态,等到数据到达,会自动唤醒服务器线程,着手进行处理。阻塞模式下,一个线程只能处理一个流的IO事件

(3) 为了提升服务器线程处理效率,有以下三种思路:

(1)非阻塞【忙轮询】:采用死循环方式轮询每一个流,如果有IO事件就处理,这样可以使得一个线程可以处理多个流,但是效率不高,容易导致CPU空转
(2)Select代理(无差别轮询):可以观察多个流的IO事件,如果所有流都没有IO事件,则将线程进入阻塞状态,如果有一个或多个发生了IO事件,则唤醒线程去处理。但是还是得遍历所有的流,才能找出哪些流需要处理。如果流个数为N,则时间复杂度为O(N)
(3)Epoll代理:Select代理有一个缺点,线程在被唤醒后轮询所有的Stream,还是存在无效操作。 Epoll会哪个流发生了怎样的I/O事件通知处理线程,因此对这些流的操作都是有意义的,复杂度降低到了O(1)

3.2.2 Redis为什么使用单线程

因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。同时多线程处理可能涉及到锁及到线程切换而消耗CPU,所以既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

说明:此处的单线程指的是Redis执行事件处理的线程为一个单线程,与Redis执行I/O多路复用的线程分属不同线程,当然其他模块可能是多线程。执行I/O多路复用的线程将来自多个连接的命令放入队列中,然后由事件处理线程(就是此处我们讨论的单线程)逐个串行执行。这样就能在单线程下处理并发请求。

参考https://blog.csdn.net/u011663149/article/details/85307615
https://www.cnblogs.com/darknebula/p/10072658.html
https://blog.csdn.net/liupeng_qwert/article/details/77263187
https://blog.csdn.net/u011663149/article/details/85307615

四、Redis事务

4.1 Redis事务过程

Redis提供的事务是将多个命令打包,然后一次性、按照先进先出的顺序(FIFO)有序的执行。在执行过程中不会被打断(在事务执行过程,其他客户端提交的命令请求不会插入到事务执行命令序列中),当事务队列中的所以命令都被执行(无论成功还是失败)完毕之后,事务才会结束。

MULTI       //开始事务
SET   ...   //命令1入队
GET   ...   //命令1入队
SADD  ...   //命令1入队
......
EXEC        //执行事务(一次执行1.2.3...)

如上所述,Redis的事务以特殊命令MULTI开始,之后跟着用户传入的多个命令,最后以EXEC未结束。由于这种简单的事务在EXEC命令被调用之前不会执行任何实际操作,所以用户将没有办法根据根据读到的数据来做决定。这句话初次读有点难懂,下面我们通过实例来解释一下这句话的含义。

4.2 Redis事务的使用形式

我们拿MySQL(InnoDB)和Redis在同样的需求场景下的不同实现形式来分析

场景:
假设我们有三条记录,分别为A、B、C;
在MySQL中ABC代表同一行记录的三个字段,初始值分别为a、b、c;
在Redis中ABC代表三个不同Key键,初始值分别为a、b、c; 我们实现这样一个功能:

  1. 将A的值变成a2
  2. 当B=b的情况下,将C变成c2;如果这条这行不成功,则1、2两条都不执行

MySQL中的伪代码实现

Connection conn = ... //获取数据库连接
conn.setAutoCommit(false); //开启事务
try{
    SET A = a2;                //将A的值变成a2
    var b_value = SELECT (B);  //读B的值(修改频繁的高并发场景下,这个读是很有必要的)
    if(b_value == b){
        boolean result = (SET C = c2 WHERE B=b);  //将C变成c2
    }
    
    if(result){
        conn.commit(); //提交事务
    }else{
        conn.rollback();//事务回滚
    }
    
}catch (Exception e) {
  conn.rollback();//事务回滚
}finally{
   conn.close();//关闭链接
}

首先我们来看一个Redis错误的示范,看看Redis的事务有何不同

ValueOperations vo = redisTemplate.opsForValue();
        vo.set("A", "a");//初始化数据
        vo.set("B", "b");
        vo.set("C", "c");
        redisTemplate.setEnableTransactionSupport(true);

        redisTemplate.multi();     //开始事务
        vo.set("A", "a2");         //将A的值变成a2
        String b_value = String.valueOf(vo.get("B"));    //获取B的值
        logger.info("事务读到b_value:" + b_value);
        if ("b".equals(b_value)) {
            vo.set("C", "c2");
        }else
        logger.info("事务结果:" + JSON.toJSONString(redisTemplate.exec()));

程序结果

事务读到b_value:null
事务结果:[true,"b"]

我们可以看到第9行代码的返回结果是null,所以第12行根本就没机会执行。
我们从14行的打印结果返现有两个返回值:[true,”b”],true是第8行vo.set(“A”, “a2”)的返回值,”b”是第9行(vo.get(“B”)的返回值,也就是说redis这些命令,只有才EXEC执行的时候才会真正的执行。这就是之前文章提到的“由于这种简单的事务在EXEC命令被调用之前不会执行任何实际操作,所以用户将没有办法根据根据读到的数据来做决定。”,所以在EXEC执行前我们的普通的读写操作都不会执行的,在这个过程中我们不能像传统数据库那样读DB的值来做逻辑处理。

而且还有很重要的一点,Redis是不支持已被执行命令的回滚。

那么在Redis中,面对这种场景我们应该如何处理呢?怎么解决读判断,以及判断回滚呢?

4.3 Redis回滚

那就要引入另一个关键字watch,我们先看怎么使用,再分析是怎么实现的

try {
            redisTemplate.watch("B");//监视 Key-B
            String b_value = String.valueOf(vo.get("B"));    //获取B的值
            logger.error("事务读到b_value:" + b_value);
            if ("b".equals(b_value)) {
                redisTemplate.multi();     //开始事务
                vo.set("A", "a2");         //将A的值变成a2
                vo.set("C", "c2");         //将C的值变成c2
                logger.error("事务结果:" + JSON.toJSONString(redisTemplate.exec()));
            } else {
                redisTemplate.unwatch();
                logger.error("解除watch...");
            }
        } catch (Exception e) {
            redisTemplate.discard();//取消事务,放弃执行事务块内的所有命令
            logger.error("取消事务,放弃执行事务块内的所有命令");
        }

我们看一下如果在事务从“watch ~ 事务开启 ~命令入队 ~ EXEC”期间,B键的值没有被其他客户端改变的情况下的打印结果:

事务读到b_value:b
事务结果:[true,true]

从打印结果,我们可以看到事务中7,8行的命令都被准确执行。

我们再Debug运行一次,这次我们把断点打在第8行,运行到第8行时我们在终端修改变B键的值:

127.0.0.1:6379> SET B b1
OK

这个时候我们让程序继续从第8行继续运行,打印结果为:

事务读到b_value:b
事务结果:[]

可以看到事务中7,8行的命令都没有执行(redis使用watch正在监视“B”,由于B对象被终端修改,则事务终止),符合我们的预期。

4.4 Redis事务分步实现

我们上面提到,Redis事务的过程分为三个阶段:

  1. 事务开始
  2. 命令入队
  3. 事务执行

事务开始

Redis事务的开始是通过执行MULTI 命令来实现,它的作用是将执行该命令的客户端从非事务状态切换至事务状态, 这一切换是通过在客户端状态的 flags 属性中打开 REDIS_MULTI 标识来完成的。

命令入队

当一个客户端出于事务状态时, 如果客户端发送的命令是 EXEC(执行所有事务块内的命令) 、DISCARD(取消事务,放弃执行事务块内的所有命令。) 、 WATCH(监视任意数量的key ,提一下,在事务中执行这个命令会报错:ERR WATCH inside MULTI is not allowed) 、 MULTI(标记一个事务块的开始) 四个命令以外的其他命令,那么服务器并不立即执行这个命令,而是将这个命令放入一个事务队列里面, 然后向客户端返回 QUEUED 回复。

事务执行

当一个处于事务状态的客户端向服务器发送 EXEC 命令时, 这个 EXEC 命令将立即被服务器执行: 服务器会遍历这个客户端的事务队列,执行队列中保存的所有命令,最后将执行命令所得的结果全部返回给客户端。
(这里需要说明的一点是,Redis在处理网络请求的是单线程的,所以队列中的命令在执行期间是不会被其他客户端命令插进来的。这一点对理解Redis事务很关键)

WATCH

WATCH 用于事务开启之前对任意数量的Key进行监视,如果这个被监视的key被改动(这里提一下,这个改动,不管是删除、添加、修改,或者A -> B -> A改回原值,都会被认为发生了改动),那么相应事务就被取消,否则事务正常执行。所以我们可以认为 WATCH 是一个乐观锁。
如果想让key取消被监控,可以用 UNWATCH 命令(这里又要提一下,UNWATCH 如果在事务中执行,也是会被放到队列里的)。

如上文所说,WATCH对于添加操作也是敏感的,也就说我们可以对一个不存在的Key进行WATCH。假如cli_1客户端对一个不存在的Key进行WATCH,此时cli_2客户端增加了这个键,那么cli_1客户端的事务依然不会执行,这个很有意思

参考https://blog.csdn.net/wq3002/article/details/86250820

五、Redis面试问题汇总

https://blog.csdn.net/qq_34337272/article/details/80012284

六、Redis持久化问题定位与优化

https://www.cnblogs.com/yangmingxianshen/p/8407972.html

七、主、从结点的故障转移Sentinel

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
配置三个Sentinel结点,下图只显示了端口号为7000的sesentinel。因为一个Sentinel集合可以监控多个主节点,故需要通过给主节点命名来区分Sentinel监控的各个主节点。
在这里插入图片描述
客户端控制sentinel:
在这里插入图片描述
在这里插入图片描述
三个定时任务来实现Sentinel结点与主节点、从结点之间的信息交换。
在这里插入图片描述
主节点下线时需要主观下线和客观下线两个流程。主观下线是指独立的sentinel结点在与主节点进行定时交互时发现结点“失败”了,此时因为主节点下线时需要做大量的故障转移工作,所以还需要更为稳妥的“客观下线”,客观下线是指所有的sentinel结点对主节点“失败”产生统一认识,即有超过quorum个结点认为主节点已经“失败”了。此时,才会发生真正的主节点下线。而从结点下线因为不需要故障转移,所以只要经过主观下线就可以了。
Tips:quorum数量设置的标准一般按照Sentinel的个数为(n/2+1),且Sentinel结点个数一般设置为奇数(Sentinel数量较多)。
在这里插入图片描述
因为只需要一个Sentinel结点完成故障转移,则需要在Sentinel结点中选举出一个结点,选举流程如下所示。使用了Ruft算法思想。
在这里插入图片描述
在这里插入图片描述
选举出进行故障转移的Sentinel结点后,便可以对各个结点进行故障转移的操作。
在这里插入图片描述
那么如何选择哪个slave结点应该成为主节点呢?
在这里插入图片描述

八、Redis集群

集群可改善的问题:

  • 并发量:QPS
  • 数据量:“大数据”
  • 网络流量:单机流量有网卡限制

分布式数据分布有两种分布方式:哈希分布和顺序分布,对比如下。
在这里插入图片描述
Redi Cluster采用哈希分布方式组织数据,且在扩容时使用一致性哈希算法。
https://www.cnblogs.com/study-everyday/p/8629100.html
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

集群的配置
在这里插入图片描述
在这里插入图片描述
下图的最后一个配置表示是否需要所有集群内的所有结点都能提供服务,要是集群内有一个结点坏掉了,集群就不对外提供服务了。所以此配置一般为No。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
原生命令安装简要说明:首先开启各个Redis结点及设置相关配置(注意将每个结点设置为集群模式),此时如果向结点中进行set操作会报错,只有在集群全部配置结束之后(meet、分配槽、复制等)才会允许读写操作。此时在单个节点中也看不到集群中其他结点的状态。第二步就是进行结点之间的握手(meet),只需要将某个结点向其他各结点均做一次meet操作就可以实现两两结点的互相感知,建立连接。然后在各结点上分配槽位。分配槽位时在按照主节点master的数量划分,因为有的结点作为了从结点。接着便是设置主从结点,假设有六个Redis结点,便可以两两结合,分配三组主从结点。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
大学生在线租房平台管理系统按照操作主体分为管理员和用户。管理员的功能包括报修管理、报修评价管理、字典管理、房东管理、房屋管理、房屋收藏管理、房屋留言管理、房屋租赁管理、租房论坛管理、公告信息管理、留言板管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 大学生在线租房平台管理系统可以提高大学生在线租房平台信息管理问题的解决效率,优化大学生在线租房平台信息处理流程,保证大学生在线租房平台信息数据的安全,它是一个非常可靠,非常安全的应用程序。 管理员权限操作的功能包括管理公告,管理大学生在线租房平台信息,包括房屋管理,培训管理,报修管理,薪资管理等,可以管理公告。 房屋管理界面,管理员在房屋管理界面中可以对界面中显示,可以对房屋信息的房屋状态进行查看,可以添加新的房屋信息等。报修管理界面,管理员在报修管理界面中查看报修种类信息,报修描述信息,新增报修信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
基于hal库的OLED显示屏驱动C语言实现源码.zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip基于hal库的OLED显示屏驱动C语言实现源码.zip
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值