M63.第二十周作业

1、总结tomcat优化方法

1. Linux内核参数调优

1.1 打开的文件数量的限制

查看系统允许当前用户进程打开的文件数量的限制:ulimit -n 默认值为1024 。即是Linux操作系统对一个进程打开的文件句柄数量的限制

ulimit参数含义

参数     含义

-H        设置硬资源限制,一旦设置不能增加.

-S         设置软资源限制,设置后可以增加,但不能超过硬资源设置

-a          显示当前所有limit信息

-c         最大的core文件大小,以blocks为单位

-d         进程最大的数据段大小,以blocks为单位

-f          进程可以创造文件的最大值,以kbytes为单位

-l          最大可加锁内存大小,以kbytes为单位

-m        最大内存大小,以kbytes为单位

-n         Linux操作系统对一个进程可以打开最大文件描述符的数量.

-p         管道缓冲区大小,以kbytes为单位

-s         线程栈大小,以kbytes为单位

-t         最大CPU占用时间,以秒为单位

-u        用户最大可用的进程数

-v        进程最大可用的虚拟机内存,以kbytes为单位.


对于想支持更高数量的TCP并发连接的通讯处理程序,就必须修改Linux对当前用户的进程同时打开的文件数量的软限制(soft limit)和硬限制(hardlimit)。其中软限制是指Linux在当前系统能够承受的范围内进一步限制用户同时打开的文件数;硬限制则是根据系统硬件资源状况(主要是系统内存)计算出来的系统最多可同时打开的文件数量。通常软限制小于或等于硬限制。

配置文件:/etc/security/limits.conf

echo '* soft nofile 655350' >>/etc/security/limits.conf

echo '* hard nofile 655350' >>/etc/security/limits.conf

echo '* soft nproc  655350' >>/etc/security/limits.conf

echo '* hard nproc  650000' >>/etc/security/limits.conf

hard和soft两个值都代表什么意思呢?

soft是一个警告值,而hard则是一个真正意义的阀值,超过就会报错

配置完成后重新登录参数生效


临时生效方法(重启失效):

ulimit -Hn 65535

ulimit -Sn 65535


如果只是配置tomcat用户打开文件数:

echo 'tomcat soft nofile 655350' >>/etc/security/limits.conf

echo 'tomcat hard nofile 655350' >>/etc/security/limits.conf

echo 'tomcat soft nproc  655350' >>/etc/security/limits.conf

echo 'tomcat hard nproc  650000' >>/etc/security/limits.conf

1.2 Linux网络内核对TCP连接的有关限制

配置文件:/etc/sysctl.conf

echo "net.ipv4.tcp_tw_reuse = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_tw_recycle = 1" >> /etc/sysctl.conf

echo "net.ipv4.tcp_fin_timeout = 30" >> /etc/sysctl.conf

echo "net.ipv4.ip_local_port_range = 10000 65000" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_syn_backlog = 8192" >> /etc/sysctl.conf

echo "net.ipv4.tcp_max_tw_buckets = 10000" >> /etc/sysctl.conf

echo "net.core.somaxconn=8192" >> /etc/sysctl.conf

sysctl -p

即时生效,不用重启或注销登录


2. JVM优化

2.1 内存空间优化

配置文件:/usr/local/tomcat/bin/catalina.sh

JAVA_OPTS="-server -Xms4g -Xmx4g -Xss512k -Xmn1g \

-XX:CMSInitiatingOccupancyFraction=65 -XX:+AggressiveOpts \

-XX:+UseBiasedLocking -XX:+DisableExplicitGC \

-XX:MaxTenuringThreshold=10 -XX:NewRatio=2 -XX:PermSize=128m \

-XX:MaxPermSize=512m -XX:CMSFullGCsBeforeCompaction=5 \

-XX:+ExplicitGCInvokesConcurrent -XX:+UseConcMarkSweepGC \

-XX:+UseParNewGC -XX:+CMSParallelRemarkEnabled \

-XX:+UseCMSCompactAtFullCollection -XX:LargePageSizeInBytes=128m \

-XX:+UseFastAccessorMethods"

参数                                含义

-server                            服务器模式

-Xms                               堆内存初始化大小

-Xmx                                堆内存空间上限

-XX:NewSize=                 新生代空间初始化大小

-XX:MaxNewSize=          新生代空间最大值

3. Tomcat 调优

配置文件:/usr/local/tomcat/conf/server.xml

3.1 maxThreads 修改

<!--

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="150" minSpareThreads="4"/>

  -->

修改为:

<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"

maxThreads="1500"  minSpareThreads="50" maxIdleTime="60000"

prestartminSpareThreads = "true"  maxQueueSize = "100"/>

3.2 maxConnections acceptCount修改

<Connector

port="8080"

protocol="HTTP/1.1"

connectionTimeout="20000"

redirectPort="8443"

/>

修改为:

<Connector executor ="tomcatThreadPool" port="8009"

protocol="org.apache.coyote.http11.Http11Nio2Protocol" 

connectionTimeout="20000" maxConnections="10000"  redirectPort="8443"

acceptCount="1500"/>

参数                                         含义

connectionTimeout                 连接超时时长,单位ms

maxThreads                            最大线程数,默认200

minSpareThreads                    最小空闲线程数

maxSpareThreads                   最大空闲线程数

acceptCount                             当启动线程满了之后,等待队列的最大长度,默认100

URIEncoding URI                     地址编码格式,建议使用 UTF-8

enableLookups                         是否启用客户端主机名的DNS反向解析,缺省禁用,建议禁用,就使用客户端IP就行

compression                             是否启用传输压缩机制,建议 “on”,CPU和流量的平衡

compressionMinSize                 启用压缩传输的数据流最小值,单位是字节

compressableMimeType            定义启用压缩功能的MIME类型text/html, text/xml, text/css,text/javascript



2、java程序出现oom如何解决?什么场景下会出现oom?

oom

Out of memory(OOM)是一种操作系统或者程序已经无法再申请到内存的状态。经常是因为所有可用的内存,包括磁盘交换空间都已经被分配了。当JVM因为没有足够的内存来为对象分配空间、并且垃圾回收器也已经没有空间可回收时,就会抛出 java.lang.Out Of Memory Error 错误

1 Java heap space

当堆内存(Heap Space)没有足够空间存放新创建的对象时,就会抛出 java.lang.Out Of Memory Error:Java heap space 错误(根据实际生产经验,可以对程序日志中的 Out Of Memory Error 配置关键字告警,一经发现,立即处理)。

原因分析

Javaheap space 错误产生的常见原因可以分为以下几类:

(1)请求创建一个超大对象,通常是一个大数组。

(2)超出预期的访问量/数据量,通常是上游系统请求流量飙升,常见于各类促销/秒杀活动,可以结合业务流量指标排查是否有尖状峰值。

(3)过度使用终结器(Finalizer),该对象没有立即被 GC。

(4)内存泄漏(Memory Leak),大量对象引用没有释放,JVM 无法对其自动回收,常见于使用了 File 等资源没有回收。

解决方案

针对大部分情况,通常只需要通过 -Xmx 参数调高 JVM 堆内存空间即可。如果仍然没有解决,可以参考以下情况做进一步处理:

(1)如果是超大对象,可以检查其合理性,比如是否一次性查询了数据库全部结果,而没有做结果数限制。

(2)如果是业务峰值压力,可以考虑添加机器资源,或者做限流降级。

(3)如果是内存泄漏,需要找到持有的对象,修改代码设计,比如关闭没有释放的连接。

2 GC overhead limit exceeded

当 Java 进程花费 98% 以上的时间执行 GC,但只恢复了不到 2% 的内存,且该动作连续重复了 5 次,就会抛出 java.lang.Out Of Memory Error:GC overhead limit exceeded 错误。简单地说,就是应用程序已经基本耗尽了所有可用内存, GC 也无法回收。

此类问题的原因与解决方案跟 Java heap space 非常类似,可以参考上文。

3 Permgen space

该错误表示永久代(Permanent Generation)已用满,通常是因为加载的 class 数目太多或体积太大。

原因分析

永久代存储对象主要包括以下几类:

(1)加载/缓存到内存中的 class 定义,包括类的名称,字段,方法和字节码;

(2)常量池;

(3)对象数组/类型数组所关联的 class;

(4)JIT 编译器优化后的 class 信息。

PermGen 的使用量与加载到内存的 class 的数量/大小正相关。

解决方案

根据 Permgen space 报错的时机,可以采用不同的解决方案,如下所示:

(1)程序启动报错,修改 -XX:MaxPermSize 启动参数,调大永久代空间。

(2)应用重新部署时报错,很可能是没有应用没有重启,导致加载了多份 class 信息,只需重启 JVM 即可解决。

(3)运行时报错,应用程序可能会动态创建大量 class,而这些 class 的生命周期很短暂,但是 JVM 默认不会卸载 class,可以设置 -XX:+CMSClassUnloadingEnabled 和 -XX:+UseConcMarkSweepGC这两个参数允许 JVM 卸载 class。

如果上述方法无法解决,可以通过 jmap 命令 dump 内存对象 jmap-dump:format=b,file=dump.hprof ,然后利用 Eclipse MAT (https://www.eclipse.org/mat) 功能逐一分析开销最大的 classloader 和重复 class。

4 Metaspace

JDK 1.8 使用 Metaspace 替换了永久代(Permanent Generation),该错误表示 Metaspace 已被用满,通常是因为加载的 class 数目太多或体积太大。

此类问题的原因与解决方法跟 Permgen space 非常类似,可以参考上文。需要特别注意的是调整 Metaspace 空间大小的启动参数为 -XX:MaxMetaspaceSize。

5 Unable to create new native thread

每个 Java 线程都需要占用一定的内存空间,当 JVM 向底层操作系统请求创建一个新的 native 线程时,如果没有足够的资源分配就会报此类错误。

原因分析

JVM 向 OS 请求创建 native 线程失败,就会抛出 Unable to create new native thread,常见的原因包括以下几类:

(1)线程数超过操作系统最大线程数 ulimit 限制;

(2)线程数超过 kernel.pid_max(只能重启);

(3)native 内存不足;

该问题发生的常见过程主要包括以下几步:

1、JVM 内部的应用程序请求创建一个新的 Java 线程;

2、JVM native 方法代理了该次请求,并向操作系统请求创建一个 native 线程;

3、操作系统尝试创建一个新的 native 线程,并为其分配内存;

4、如果操作系统的虚拟内存已耗尽,或是受到 32 位进程的地址空间限制,操作系统就会拒绝本次 native 内存分配;

5、JVM 将抛出 java.lang.Out Of Memory Error:Unable to create new native thread 错误。

解决方案

(1)升级配置,为机器提供更多的内存;

(2)降低 Java Heap Space 大小;

(3)修复应用程序的线程泄漏问题;

(4)限制线程池大小;

(5)使用 -Xss 参数减少线程栈的大小;

(6)调高 OS 层面的线程最大数:执行 ulimia-a 查看最大线程数限制,使用 ulimit-u xxx 调整最大线程数限制。

ulimit -a … 省略部分内容 … max user processes (-u) 16384

6 Out of swap space

该错误表示所有可用的虚拟内存已被耗尽。虚拟内存(Virtual Memory)由物理内存(Physical Memory)和交换空间(Swap Space)两部分组成。当运行时程序请求的虚拟内存溢出时就会报 Outof swap space? 错误。

原因分析

该错误出现的常见原因包括以下几类:

(1)地址空间不足;

(2)物理内存已耗光;

(3)应用程序的本地内存泄漏(native leak),例如不断申请本地内存,却不释放。

(4)执行 jmap-histo:live 命令,强制执行 Full GC;如果几次执行后内存明显下降,则基本确认为 Direct Byte Buffer 问题。

解决方案

根据错误原因可以采取如下解决方案:

(1)升级地址空间为 64 bit;

(2)使用 Arthas 检查是否为 Inflater/Deflater 解压缩问题,如果是,则显式调用 end 方法。

(3)Direct Byte Buffer 问题可以通过启动参数 -XX:MaxDirectMemorySize 调低阈值。

(4)升级服务器配置/隔离部署,避免争用。

7 Kill process or sacrifice child

有一种内核作业(Kernel Job)名为 Out of Memory Killer,它会在可用内存极低的情况下“杀死”(kill)某些进程。OOM Killer 会对所有进程进行打分,然后将评分较低的进程“杀死”,具体的评分规则可以参考 Surviving the Linux OOM Killer。

不同于其他的 OOM 错误, Kill process or sacrifice child 错误不是由 JVM 层面触发的,而是由操作系统层面触发的。

原因分析

默认情况下,Linux 内核允许进程申请的内存总量大于系统可用内存,通过这种“错峰复用”的方式可以更有效的利用系统资源。

然而,这种方式也会无可避免地带来一定的“超卖”风险。例如某些进程持续占用系统内存,然后导致其他进程没有可用内存。此时,系统将自动激活 OOM Killer,寻找评分低的进程,并将其“杀死”,释放内存资源。

解决方案

(1)升级服务器配置/隔离部署,避免争用。

(2)OOM Killer 调优。

8 Requested array size exceeds VM limit

JVM 限制了数组的最大长度,该错误表示程序请求创建的数组超过最大长度限制。

JVM 在为数组分配内存前,会检查要分配的数据结构在系统中是否可寻址,通常为 Integer.MAX_VALUE-2。

此类问题比较罕见,通常需要检查代码,确认业务是否需要创建如此大的数组,是否可以拆分为多个块,分批执行。

9 Direct buffer memory

Java 允许应用程序通过 Direct Byte Buffer 直接访问堆外内存,许多高性能程序通过 Direct Byte Buffer 结合内存映射文件(Memory Mapped File)实现高速 IO。

原因分析

Direct Byte Buffer 的默认大小为 64 MB,一旦使用超出限制,就会抛出 Direct buffer memory 错误。

解决方案

(1)Java 只能通过 Byte Buffer.allocateDirect 方法使用 Direct Byte Buffer,因此,可以通过 Arthas 等在线诊断工具拦截该方法进行排查。

(2)检查是否直接或间接使用了 NIO,如 netty,jetty 等。

(3)通过启动参数 -XX:MaxDirectMemorySize 调整 Direct Byte Buffer 的上限值。

(4)检查 JVM 参数是否有 -XX:+DisableExplicitGC 选项,如果有就去掉,因为该参数会使 System.gc() 失效。

(5)检查堆外内存使用代码,确认是否存在内存泄漏;或者通过反射调用 sun.misc.Cleaner 的 clean() 方法来主动释放被 Direct ByteBuffer 持有的内存空间。

(6)内存容量确实不足,升级配置。


3、简述redis特点及其应用场景

1 Redis 简介

Redis (Remote Dictionary Server) ,远程字典服务,Redis是一个开源的、遵循BSD协议的、基于内存的而且目前比较流行的键值数据库(key-value database),是一个非关系型数据库。redis 提供将内存通过网络远程共享的一种服务,提供类似功能的还有memcached,但相比memcached,redis还提供了易扩展、高性能、具备数据持久性等功能。 Redis 在高并发、低延迟环境要求比较高的环境使用量非常广泛。

2 Redis 特性

速度快:10W QPS,基于内存,C语言实现

单线程

持久化

支持多种数据结构

支持多种编程语言

功能丰富:支持Lua脚本,发布订阅,事务,pipeline等功能

简单:代码短小精悍(单机核心代码只有23000行左右),单线程开发容易,不依赖外部库,使用简单

主从复制

支持高可用和分布式

2.1 单线程

Redis 6.0版本前一直是单线程方式处理用户的请求

单线程为何如此快?

纯内存

非阻塞

避免线程切换和竞态消耗

注意事项:

一次只运行一条命令

拒绝长(慢)命令:keys,flushall,flushdb,slow lua script,mutil/exec,operate big value(collection)

其实不是单线程:早期版本是单进程单线程,3版本后实际还有其它的线程,实现特定功能,如:fysnc file descriptor,close file descriptor

3 redis 对比 memcached

支持数据的持久化:可以将内存中的数据保持在磁盘中,重启redis服务或者服务器之后可以从备份文件中恢复数据到内存继续使用

支持更多的数据类型:支持string(字符串)、hash(哈希数据)、list(列表)、set(集合)、zset(有序集

合)

支持数据的备份:可以实现类似于数据的master-slave模式的数据备份,另外也支持使用快照+AOF

支持更大的value数据:memcache单个key value最大只支持1MB,而redis最大支持512MB(生产不建议超过2M,性能受影响)

在Redis6版本前,Redis 是单线程,而memcached是多线程,所以单机情况下没有memcached 并发高,性能更好,但redis 支持分布式集群以实现更高的并发,单Redis实例可以实现数万并发

支持集群横向扩展:基于redis cluster的横向扩展,可以实现分布式集群,大幅提升性能和数据安全性

都是基于 C 语言开发

4 redis 典型应用场景

Session 共享:常见于web集群中的Tomcat或者PHP中多web服务器session共享

缓存:数据查询、电商网站商品信息、新闻内容

计数器:访问排行榜、商品浏览数等和次数相关的数值统计场景

微博/微信社交场合:共同好友,粉丝数,关注,点赞,评论等

消息队列:ELK的日志缓存、部分业务的订阅发布系统

地理位置:基于GEO(地理信息定位),实现摇一摇,附近的人,外卖等功能


4、对比redis的RDB、AOF模式的优缺点

Redis 提供了两种持久化的方式,分别是RDB(Redis DataBase)和AOF(Append Only File)。

RDB,简而言之,就是在不同的时间点,将Redis 存储的数据生成快照并存储到磁盘等介质上。

AOF,则是换了一个角度来实现持久化,那就是将Redis 执行过的所有写指令记录下来,在下次Redis 重新启动时,只要把这些写指令从前到后再重复执行一遍,就可以实现数据恢复了。

RDB 和AOF 两种方式也可以同时使用,在这种情况下,如果Redis 重启的话,则会优先采用AOF 方式来进行数据恢复,这是因为AOF 方式的数据恢复完整度更高。

RDB

RDB持久化方式,是将Redis某一时刻的数据持久化到磁盘中,是一种快照式的持久化方法。

RDB持久化方式:Redis在进行数据持久化的过程中,会先将数据写入到一个临时文件中,待持久化过程都结束了,才会用这个临时文件替换上次持久化好的文件。正是这种特性,让我们可以随时来进行备份,因为快照文件总是完整可用的。

对于RDB 方式,Redis 会单独创建一个子进程来进行持久化,而主进程是不会进行任何IO 操作的,这样就确保了Redis 极高的性能。

RDB优点:如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB 方式要比AOF 方式更加的高效。

RDB缺点:如果你对数据的完整性非常敏感,那么RDB 方式就不太适合你,因为即使你每5 分钟都持久化一次,当Redis 故障时,仍然会有近5 分钟的数据丢失。所以,Redis 还提供了另一种持久化方式,那就是AOF。

AOF

AOF方式是将执行过的写指令记录下来,在数据恢复时按照从前到后的顺序再将指令都执行一遍。

实现方式:我们通过配置Redis.conf 中的appendonly yes 就可以打开AOF功能。如果有写操作(如SET 等),Redis 就会被追加到AOF 文件的末尾。

AOF 持久化的方式:默认的AOF 持久化策略是每秒钟fsync 一次(fsync是指把缓存中的写指令记录到磁盘中),因为在这种情况下,Redis 仍然可以保持很好的处理性能,即使Redis 故障,也只会丢失最近1 秒钟的数据。

如果在追加日志时,恰好遇到磁盘空间满或断电等情况导致日志写入不完整,也没有关系,Redis 提供了Redis-check-aof 工具,可以用来进行日志修复。

因为采用了追加方式,如果不做任何处理的话,AOF 文件会变得越来越大,为此,Redis 提供了AOF 文件重写(rewrite)机制,即当AOF 文件的大小超过所设定的阈值时,Redis 就会启动AOF 文件的内容压缩,只保留可以恢复数据的最小指令集。举个例子或许更形象,假如我们调用了100 次INCR 指令,在AOF 文件中就要存储100 条指令,但这明显是很低效的,完全可以把这100条指令合并成一条SET 指令,这就是重写机制的原理。

AOF 优点:我们通过一个场景再现来说明。某同学在操作Redis 时,不小心执行了FLUSHALL,导致Redis 内存中的数据全部被清空了,这是很悲剧的事情。不过这也不是世界末日,只要Redis 配置了AOF 持久化方式,且AOF文件还没有被重写(rewrite),我们就可以用最快的速度暂停Redis 并编辑AOF文件,将最后一行的FLUSHALL 命令删除,然后重启Redis,就可以恢复Redis的所有数据到FLUSHALL 之前的状态了。是不是很神奇,这就是AOF 持久化方式的好处之一。但是如果AOF 文件已经被重写了,那就无法通过这种方法来恢复数据了。

AOF缺点:比如在同样数据规模的情况下,AOF文件要比RDB文件的体积大。而且,AOF 方式的恢复速度也要慢于RDB 方式。

如果你直接执行BGREWRITEAOF 命令,那么Redis 会生成一个全新的AOF文件,其中便包括了可以恢复现有数据的最少的命令集。

如果运气比较差,AOF 文件出现了被写坏的情况,也不必过分担忧,Redis并不会贸然加载这个有问题的AOF 文件,而是报错退出。这时可以通过以下步骤来修复出错的文件:

1.备份被写坏的AOF 文件。

2.运行Redis-check-aof –fix 进行修复。

3.用diff -u 来看下两个文件的差异,确认问题点。

4.重启Redis,加载修复后的AOF 文件。


5、实现redis哨兵,模拟master故障场景


1 redis 哨兵(Sentinel)

1.1 redis 集群介绍

主从架构无法实现master和slave角色的自动切换,即当master出现redis服务异常、主机断电、磁盘损坏等问题导致master无法使用,而redis主从复制无法实现自动的故障转移(将slave 自动提升为新master),需要手动修改环境配置,才能切换到slave redis服务器,另外当单台Redis服务器性能无法满足业务写入需求的时候,也无法横向扩展Redis服务的并行写入性能

需要解决以上的两个核心问题:

        master和slave角色的无缝切换,让业务无感知从而不影响业务使用

        可横向动态扩展Redis服务器,从而实现多台服务器并行写入以实现更高并发的目的。

Redis 集群实现方式:

        客户端分片:由应用决定将不同的KEY发送到不同的Redis服务器

        代理分片:由代理决定将不同的KEY发送到不同的Redis服务器,代理程序如:codis,twemproxy等

        Redis Cluster:着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。

1.2 哨兵 (Sentinel) 工作原理

Redis Sentinal:着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。

Sentinel 故障转移 :

(1)多个sentinel发现并确认master有问题

(2)选举出一个sentinel作为领导

(3)选出一个slave作为master

(4)通知其余slave成为新master的slave

(5)通知客户端主从变化

(6)等待老的master复活成为新master的slave

Sentinel 进程是用于监控redis集群中Master主服务器工作的状态,在Master主服务器发生故障的时候,可以实现Master和Slave服务器的切换,保证系统的高可用,此功能在redis2.6+的版本已引用,Redis的哨兵模式到了2.8版本之后就稳定了下来。一般在生产环境也建议使用Redis的2.8版本的以后版本

哨兵(Sentinel) 是一个分布式系统,可以在一个架构中运行多个哨兵(sentinel) 进程,这些进程使用流言协议(gossip protocols)来接收关于Master主服务器是否下线的信息,并使用投票协议(Agreement Protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master

每个哨兵(Sentinel)进程会向其它哨兵(Sentinel)、Master、Slave定时发送消息,以确认对方是否”活”着,如果发现对方在指定配置时间(此项可配置)内未得到回应,则暂时认为对方已离线,也就是所谓的”主观认为宕机” (主观:是每个成员都具有的独自的而且可能相同也可能不同的意识),英文名称:Subjective Down,简称SDOWN

有主观宕机,对应的有客观宕机。当“哨兵群”中的多数Sentinel进程在对Master主服务器做出SDOWN的判断,并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后,得出的Master Server下线判断,这种方式就是“客观宕机”(客观:是不依赖于某种意识而已经实际存在的一切事物),英文名称是:Objectively Down, 简称 ODOWN

通过一定的vote算法,从剩下的slave从服务器节点中,选一台提升为Master服务器节点,然后自动修改相关配置,并开启故障转移(failover)

Sentinel 机制可以解决master和slave角色的自动切换问题,但单个 Master 的性能瓶颈问题无法解决,类似于MySQL中的MHA功能

Redis Sentinel中的Sentinel节点个数应该为大于等于3且最好为奇数

客户端初始化时连接的是Sentinel节点集合,不再是具体的Redis节点,但Sentinel只是配置中心不是代理。

Redis Sentinel 节点与普通redis 没有区别,要实现读写分离依赖于客户端程序

redis 3.0 之前版本中,生产环境一般使用哨兵模式,3.0后推出redis cluster功能,可以支持更大规模的生产环境

sentinel中的三个定时任务:

每10秒每个sentinel对master和slave执行info

发现slave节点

确认主从关系

每2秒每个sentinel通过master节点的channel交换信息(pub/sub)

通过sentinel__:hello频道交互

交互对节点的“看法”和自身信息

每1秒每个sentinel对其他sentinel和redis执行ping

2 实现redis哨兵

准备三台机器:

节点                IPRedis                        版本

master     Sentinel10.0.0.7            Redis-6.2.4

slave1     Sentinel10.0.0.17          Redis-6.2.4

slave2     Sentinel10.0.0.27          Redis-6.2.4

2.1 哨兵的准备实现主从复制架构

哨兵的前提是已经实现了一个redis的主从复制的运行环境,从而实现一个一主两从基于哨兵的高可用redis架构

注意:master 的配置文件中masterauth 和slave 都必须相同

所有主从节点的redis.conf中关健配置

#在所有主从节点执行

[root@master ~]#vim /apps/redis/etc/redis.conf

bind 0.0.0.0

masterauth 123456

requirepass 123456

#在所有从节点执行

[root@slave1 ~]#vim /apps/redis/etc/redis.conf

replicaof 10.0.0.7 6379

#在所有主从节点执行

[root@master ~]#systemctl restart redis.service

查看master服务器状态

[root@master ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:master

connected_slaves:2

slave0:ip=10.0.0.17,port=6379,state=online,offset=182,lag=0

slave1:ip=10.0.0.27,port=6379,state=online,offset=182,lag=1

master_failover_state:no-failover

master_replid:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:182

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:182

查看slave1状态

[root@slave1 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:slave

master_host:10.0.0.7

master_port:6379

master_link_status:up

master_last_io_seconds_ago:1

master_sync_in_progress:0

slave_repl_offset:308

slave_priority:100

slave_read_only:1

replica_announced:1

connected_slaves:0

master_failover_state:no-failover

master_replid:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:308

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:308

查看slave2状态

[root@slave2 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:slave

master_host:10.0.0.7

master_port:6379

master_link_status:up

master_last_io_seconds_ago:2

master_sync_in_progress:0

slave_repl_offset:406

slave_priority:100

slave_read_only:1

replica_announced:1

connected_slaves:0

master_failover_state:no-failover

master_replid:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:406

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1

repl_backlog_histlen:406

2.2 编辑哨兵的配置文件

Sentinel实际上是一个特殊的redis服务器,有些redis指令支持,但很多指令并不支持。默认监听在26379/tcp端口

哨兵可以不和Redis服务器部署在一起,但一般部署在一起以节约成本

所有redis节点使用相同的以下示例的配置文件

#如果是编译安装,在源码目录有sentinel.conf,复制到安装目录即可,如:/apps/redis/etc/sentinel.conf

[root@master ~]#cd redis-6.2.4/

[root@master redis-6.2.4]#ls

00-RELEASENOTES  CONTRIBUTING  INSTALL    README.md  runtest-cluster    sentinel.conf  TLS.md

BUGS            COPYING      Makefile  redis.conf  runtest-moduleapi  src            utils

CONDUCT          deps          MANIFESTO  runtest    runtest-sentinel  tests

[root@master redis-6.2.4]#cp sentinel.conf /apps/redis/etc/

[root@master redis-6.2.4]#vim /apps/redis/etc/sentinel.conf

bind 0.0.0.0

port 26379

daemonize yes

pidfile /apps/redis/run/redis-sentinel.pid

logfile /apps/redis/log/sentinel_26379.log

dir /tmp

sentinel monitor mymaster 10.0.0.7 6379 2

#mymaster是集群的名称,此行指定当前mymaster集群中master服务器的地址和端口

#2为法定人数限制(quorum),即有几个sentinel认为master down了就进行故障转移,一般此值是所有

sentinel节点(一般总数是>=3的奇数,如:3,5,7等)的一半以上的整数值,比如,总数是3,即3/2=1.5,

取整为2,是master的ODOWN客观下线的依据

sentinel auth-pass mymaster 123456

#mymaster集群中master的密码,注意此行要在上面行的下面

sentinel down-after-milliseconds mymaster 3000

#(SDOWN)判断mymaster集群中所有节点的主观下线的时间,单位:毫秒,建议3000

sentinel parallel-syncs mymaster 1

#发生故障转移后,可以同时向新master同步数据的slave的数量,数字越小总同步时间越长,但可以减轻新master的负载压力

sentinel failover-timeout mymaster 180000

#所有slaves指向新的master所需的超时时间,单位:毫秒

sentinel deny-scripts-reconfig yes  #禁止修改脚本

[root@master redis-6.2.4]#scp /apps/redis/etc/sentinel.conf 10.0.0.17:/apps/redis/etc/

[root@master redis-6.2.4]#scp /apps/redis/etc/sentinel.conf 10.0.0.27:/apps/redis/etc/

三个哨兵服务器的配置都如下

[root@master redis-6.2.4]#grep -vE "^#|^$" /apps/redis/etc/sentinel.conf

bind 0.0.0.0

port 26379

daemonize yes

pidfile /apps/redis/run/redis-sentinel.pid

logfile /apps/redis/log/sentinel_26379.log

dir /tmp

sentinel monitor mymaster 10.0.0.7 6379 2

sentinel auth-pass mymaster 123456

sentinel down-after-milliseconds mymaster 3000

acllog-max-len 128

sentinel parallel-syncs mymaster 1

sentinel failover-timeout mymaster 180000

sentinel deny-scripts-reconfig yes

SENTINEL resolve-hostnames no

SENTINEL announce-hostnames no

2.3 启动哨兵

三台哨兵服务器都要启动

#如果是编译安装在所有节点生成新的service文件

[root@master redis-6.2.4]#vim /lib/systemd/system/redis-sentinel.service

[Unit]

Description=Redis Sentinel

After=network.target

[Service]

ExecStart=/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf --supervised systemd

ExecStop=/bin/kill -s QUIT $MAINPID

User=redis

Group=redis

RuntimeDirectory=redis

RuntimeDirectoryMode=0755

[Install]

WantedBy=multi-user.target

[root@master redis-6.2.4]#scp /lib/systemd/system/redis-sentinel.service 10.0.0.17:/lib/systemd/system/redis-sentinel.service

[root@master redis-6.2.4]#scp /lib/systemd/system/redis-sentinel.service 10.0.0.27:/lib/systemd/system/redis-sentinel.service

#注意所有节点的目录权限,否则无法启动服务

[root@master redis-6.2.4]#chown -R redis.redis /apps/redis/

[root@master redis-6.2.4]#ll /apps/redis/etc/sentinel.conf

-rw-r--r-- 1 redis redis 14292 May  5 13:03 /apps/redis/etc/sentinel.conf

[root@slave1 ~]#chown -R redis.redis /apps/redis/

[root@slave1 ~]#ll /apps/redis/etc/sentinel.conf

-rw-r--r-- 1 redis redis 14291 May  5 13:03 /apps/redis/etc/sentinel.conf

[root@slave2 ~]#chown -R redis.redis /apps/redis/

[root@slave2 ~]#ll /apps/redis/etc/sentinel.conf

-rw-r--r-- 1 redis redis 14291 May  5 13:03 /apps/redis/etc/sentinel.conf

#重新加载配置文件

[root@master redis-6.2.4]#systemctl daemon-reload

[root@slave1 ~]#systemctl daemon-reload

[root@slave2 ~]#systemctl daemon-reload

#如果是编译安装,在所有哨兵服务器执行下面操作启动哨兵

[root@master redis-6.2.4]#/apps/redis/bin/redis-sentinel /apps/redis/etc/sentinel.conf

2.4 验证三台哨兵服务器端口

[root@master redis-6.2.4]#ss -ntl

State      Recv-Q Send-Q              Local Address:Port                            Peer Address:Port

LISTEN    0      511                            *:26379                                      *:*

LISTEN    0      511                            *:6379                                        *:*

LISTEN    0      128                            *:22                                          *:*

LISTEN    0      100                    127.0.0.1:25                                          *:*

LISTEN    0      511                        [::1]:6379                                    [::]:*

LISTEN    0      128                          [::]:22                                      [::]:*

LISTEN    0      100                        [::1]:25                                      [::]:*

[root@slave1 ~]#ss -ntl

State      Recv-Q Send-Q              Local Address:Port                            Peer Address:Port

LISTEN    0      511                            *:26379                                      *:*

LISTEN    0      511                            *:6379                                        *:*

LISTEN    0      128                            *:22                                          *:*

LISTEN    0      100                    127.0.0.1:25                                          *:*

LISTEN    0      511                        [::1]:6379                                    [::]:*

LISTEN    0      128                          [::]:22                                      [::]:*

LISTEN    0      100                        [::1]:25                                      [::]:*

[root@slave2 ~]#ss -ntl

State      Recv-Q Send-Q              Local Address:Port                            Peer Address:Port

LISTEN    0      128                            *:22                                          *:*

LISTEN    0      100                    127.0.0.1:25                                          *:*

LISTEN    0      511                            *:26379                                      *:*

LISTEN    0      511                            *:6379                                        *:*

LISTEN    0      128                          [::]:22                                      [::]:*

LISTEN    0      100                        [::1]:25                                      [::]:*

LISTEN    0      511                        [::1]:6379                                    [::]:*

2.5 查看哨兵日志

master的哨兵日志

[root@master ~]#tail -f /apps/redis/log/sentinel_26379.log

2759:X 05 May 2022 11:23:51.222 * Removing the pid file.

2759:X 05 May 2022 11:23:51.223 # Sentinel is now ready to exit, bye bye...

2811:X 05 May 2022 11:35:03.800 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

2811:X 05 May 2022 11:35:03.800 # Redis version=6.2.4, bits=64, commit=00000000, modified=0, pid=2811, just started

2811:X 05 May 2022 11:35:03.800 # Configuration loaded

2811:X 05 May 2022 11:35:03.810 * Increased maximum number of open files to 10032 (it was originally set to 1024).

2811:X 05 May 2022 11:35:03.810 * monotonic clock: POSIX clock_gettime

2811:X 05 May 2022 11:35:03.815 * Running mode=sentinel, port=26379.

2811:X 05 May 2022 11:35:03.817 # Sentinel ID is e432c1d2045d68f260da2f755fb706ed889ee3d9

2811:X 05 May 2022 11:35:03.817 # +monitor master mymaster 10.0.0.7 6379 quorum 2

slave的哨兵日志

[root@slave1 ~]#tail -f /apps/redis/log/sentinel_26379.log

2712:X 05 May 2022 11:35:00.115 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo

2712:X 05 May 2022 11:35:00.116 # Redis version=6.2.4, bits=64, commit=00000000, modified=0, pid=2712, just started

2712:X 05 May 2022 11:35:00.116 # Configuration loaded

2712:X 05 May 2022 11:35:00.121 * Increased maximum number of open files to 10032 (it was originally set to 1024).

2712:X 05 May 2022 11:35:00.122 * monotonic clock: POSIX clock_gettime

2712:X 05 May 2022 11:35:00.123 * Running mode=sentinel, port=26379.

2712:X 05 May 2022 11:35:00.124 # Sentinel ID is 19e17c40424e15f994f98592c9d2957171603a10

2712:X 05 May 2022 11:35:00.124 # +monitor master mymaster 10.0.0.7 6379 quorum 2

2712:X 05 May 2022 11:35:03.153 # +sdown sentinel e432c1d2045d68f260da2f755fb706ed889ee3d9 10.0.0.7 26379 @ mymaster 10.0.0.7 6379

2712:X 05 May 2022 11:35:04.369 # -sdown sentinel e432c1d2045d68f260da2f755fb706ed889ee3d9 10.0.0.7 26379 @ mymaster 10.0.0.7 6379

[root@slave2 ~]#tail -f /apps/redis/log/sentinel_26379.log

2752:X 05 May 2022 11:34:50.876 # Configuration loaded

2752:X 05 May 2022 11:34:50.878 * Increased maximum number of open files to 10032 (it was originally set to 1024).

2752:X 05 May 2022 11:34:50.880 * monotonic clock: POSIX clock_gettime

2752:X 05 May 2022 11:34:50.889 * Running mode=sentinel, port=26379.

2752:X 05 May 2022 11:34:50.890 # Sentinel ID is 6e3c75087dcb5e35aceee95db2854f4e1cb18bee

2752:X 05 May 2022 11:34:50.890 # +monitor master mymaster 10.0.0.7 6379 quorum 2

2752:X 05 May 2022 11:34:53.925 # +sdown sentinel 19e17c40424e15f994f98592c9d2957171603a10 10.0.0.17 26379 @ mymaster10.0.0.7 6379

2752:X 05 May 2022 11:34:53.926 # +sdown sentinel e432c1d2045d68f260da2f755fb706ed889ee3d9 10.0.0.7 26379 @ mymaster 10.0.0.7 6379

2752:X 05 May 2022 11:35:00.252 # -sdown sentinel 19e17c40424e15f994f98592c9d2957171603a10 10.0.0.17 26379 @ mymaster10.0.0.7 6379

2752:X 05 May 2022 11:35:04.557 # -sdown sentinel e432c1d2045d68f260da2f755fb706ed889ee3d9 10.0.0.7 26379 @ mymaster 10.0.0.7 6379

2.6 查看sentinel状态

在sentinel状态中尤其是最后一行,涉及到master IP是多少,有几个slave,有几个sentinels,必须是符合全部服务器数量

[root@master ~]#redis-cli -p 26379

127.0.0.1:26379> 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=10.0.0.7:6379,slaves=2,sentinels=3

#两个slave,三个sentinel服务器,如果sentinels值不符合,检查myid可能冲突

2.7 测试数据同步

[root@master ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> set date 20220505

OK

[root@slave1 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> get date

"20220505"

[root@slave2 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> get date

"20220505"

2.8 停止Redis Master 节点测试故障转移

[root@master ~]#systemctl stop redis.service

查看各节点上哨兵信息:

[root@master ~]#redis-cli -p 26379

127.0.0.1:26379> 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=10.0.0.27:6379,slaves=2,sentinels=3

#10.0.0.27 slave2自动切换为master

故障转移时sentinel的信息:

[root@slave1 ~]#tail -f /apps/redis/log/sentinel_26379.log

2712:X 05 May 2022 13:03:56.875 # +failover-state-reconf-slaves master mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:56.940 * +slave-reconf-sent slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:57.152 * +slave-reconf-inprog slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:57.331 # -odown master mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:58.228 * +slave-reconf-done slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:58.461 # +failover-end master mymaster 10.0.0.7 6379

2712:X 05 May 2022 13:03:58.461 # +switch-master mymaster 10.0.0.7 6379 10.0.0.27 6379

2712:X 05 May 2022 13:03:58.462 * +slave slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.27 6379

2712:X 05 May 2022 13:03:58.462 * +slave slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2712:X 05 May 2022 13:04:01.469 # +sdown slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

[root@master ~]#tail -f /apps/redis/log/sentinel_26379.log

2811:X 05 May 2022 11:35:03.817 # Sentinel ID is e432c1d2045d68f260da2f755fb706ed889ee3d9

2811:X 05 May 2022 11:35:03.817 # +monitor master mymaster 10.0.0.7 6379 quorum 2

2811:X 05 May 2022 13:03:55.957 # +sdown master mymaster 10.0.0.7 6379

2811:X 05 May 2022 13:03:56.184 # +new-epoch 1

2811:X 05 May 2022 13:03:56.245 # +vote-for-leader 19e17c40424e15f994f98592c9d2957171603a10 1

2811:X 05 May 2022 13:03:56.944 # +config-update-from sentinel 19e17c40424e15f994f98592c9d2957171603a10 10.0.0.17 26379 @ mymaster 10.0.0.7 6379

2811:X 05 May 2022 13:03:56.945 # +switch-master mymaster 10.0.0.7 6379 10.0.0.27 6379

2811:X 05 May 2022 13:03:56.945 * +slave slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.27 6379

2811:X 05 May 2022 13:03:56.983 * +slave slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2811:X 05 May 2022 13:04:00.055 # +sdown slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

[root@slave2 ~]#tail -f /apps/redis/log/sentinel_26379.log

2752:X 05 May 2022 13:03:56.083 # +new-epoch 1

2752:X 05 May 2022 13:03:56.084 # +try-failover master mymaster 10.0.0.7 6379

2752:X 05 May 2022 13:03:56.132 # +vote-for-leader 6e3c75087dcb5e35aceee95db2854f4e1cb18bee 1

2752:X 05 May 2022 13:03:56.153 # 19e17c40424e15f994f98592c9d2957171603a10 voted for 19e17c40424e15f994f98592c9d2957171603a10 1

2752:X 05 May 2022 13:03:56.244 # e432c1d2045d68f260da2f755fb706ed889ee3d9 voted for 19e17c40424e15f994f98592c9d2957171603a10 1

2752:X 05 May 2022 13:03:56.938 # +config-update-from sentinel 19e17c40424e15f994f98592c9d2957171603a10 10.0.0.17 26379 @ mymaster 10.0.0.7 6379

2752:X 05 May 2022 13:03:56.939 # +switch-master mymaster 10.0.0.7 6379 10.0.0.27 6379

2752:X 05 May 2022 13:03:56.940 * +slave slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 13:03:56.940 * +slave slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 13:03:59.963 # +sdown slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2.9 故障转移后的redis配置文件会被自动修改

故障转移后redis.conf中的replicaof行的master IP会被修改

[root@slave1 ~]#grep ^replicaof /apps/redis/etc/redis.conf

replicaof 10.0.0.27 6379

哨兵配置文件的sentinel monitor IP 同样也会被修改

[root@slave1 ~]#grep "monitor mymaster" /apps/redis/etc/sentinel.conf

sentinel monitor mymaster 10.0.0.27 6379 2  #自动修改此行

[root@slave2 ~]#grep "monitor mymaster" /apps/redis/etc/sentinel.conf

sentinel monitor mymaster 10.0.0.27 6379 2

[root@master ~]#grep "monitor mymaster" /apps/redis/etc/sentinel.conf

sentinel monitor mymaster 10.0.0.27 6379 2

2.10 查看当前 redis状态

新的master 状态

[root@slave2 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:master  #提升为master

connected_slaves:1

slave0:ip=10.0.0.17,port=6379,state=online,offset=1867449,lag=0

master_failover_state:no-failover

master_replid:58f2e7e6203f5dea3021a3ad6b627849cd1a80c6

master_replid2:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_repl_offset:1867449

second_repl_offset:1112913

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:818874

repl_backlog_histlen:1048576

[root@slave1 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:slave

master_host:10.0.0.27  #指向新的master

master_port:6379

master_link_status:up

master_last_io_seconds_ago:1

master_sync_in_progress:0

slave_repl_offset:1826043

slave_priority:100

slave_read_only:1

replica_announced:1

connected_slaves:0

master_failover_state:no-failover

master_replid:58f2e7e6203f5dea3021a3ad6b627849cd1a80c6

master_replid2:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_repl_offset:1826043

second_repl_offset:1112913

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:777468

repl_backlog_histlen:1048576

2.11 测试数据同步

[root@slave2 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> set fruit orange

OK

[root@slave1 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> get fruit

"orange"

2.12 恢复故障的原master重新加入redis集群

[root@master ~]#systemctl start redis.service

[root@master ~]#grep ^replicaof /apps/redis/etc/redis.conf

replicaof 10.0.0.27 6379

在原 master上观察状态

[root@master ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:slave

master_host:10.0.0.27

master_port:6379

master_link_status:up

master_last_io_seconds_ago:1

master_sync_in_progress:0

slave_repl_offset:2398880

slave_priority:100

slave_read_only:1

replica_announced:1

connected_slaves:0

master_failover_state:no-failover

master_replid:58f2e7e6203f5dea3021a3ad6b627849cd1a80c6

master_replid2:0000000000000000000000000000000000000000

master_repl_offset:2398880

second_repl_offset:-1

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2325269

repl_backlog_histlen:73612

127.0.0.1:6379> get fruit

"orange"

[root@master ~]#redis-cli -p 26379

127.0.0.1:26379> 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=10.0.0.27:6379,slaves=2,sentinels=3

观察新master上状态和日志

[root@slave2 ~]#redis-cli

127.0.0.1:6379> AUTH 123456

OK

127.0.0.1:6379> INFO replication

# Replication

role:master

connected_slaves:2

slave0:ip=10.0.0.17,port=6379,state=online,offset=3034646,lag=0

slave1:ip=10.0.0.7,port=6379,state=online,offset=3034646,lag=1

master_failover_state:no-failover

master_replid:58f2e7e6203f5dea3021a3ad6b627849cd1a80c6

master_replid2:1067b30c7ff6a77e0b2655096cb057d0ffea30e1

master_repl_offset:3034646

second_repl_offset:1112913

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:1986071

repl_backlog_histlen:1048576

[root@slave2 ~]#tail -f /apps/redis/log/sentinel_26379.log

2752:X 05 May 2022 13:03:56.939 # +switch-master mymaster 10.0.0.7 6379 10.0.0.27 6379

2752:X 05 May 2022 13:03:56.940 * +slave slave 10.0.0.17:6379 10.0.0.17 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 13:03:56.940 * +slave slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 13:03:59.963 # +sdown slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 14:46:15.590 # -sdown slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

2752:X 05 May 2022 14:46:25.578 * +convert-to-slave slave 10.0.0.7:6379 10.0.0.7 6379 @ mymaster 10.0.0.27 6379

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容