Redis

Redis

本节所讲:

1  Redis概述

2  安装Redis

3  Redis基本操作

4  Redis持久化

5  Redis主从架构(实现读写分离)

6  使用sentinel实现主从架构高可用

1  Redis概述

1.1  Redis是什么

Redis的出现时间并不长,是NoSQL中的一种,基于键-值型的存储,与memcache类似,但是memcache中只是内存的缓存,而Redis不仅是内存中的缓存,还提供持久存储,2009年第一次发布Redis。

Redis 全称(REmote DIctionary Server)远程字典服务器,而这个字典服务器从本质上来讲,主要是提供数据结构的远程存储功能的,可以理解为Redis是一个高级的K-V存储,和数据结构存储,因为Redis除了能够存储K-V这种简单的数据之外,还能够存储,列表、字典、hash表、等对应的数据结构。

在性能上Redis不比memcache差,因为Redis整个运行通通都是在内存中实现的,它的所有的数据集都是保存在内存中的,内存中的数据会周期性的写入到磁盘上,以实现数据的持久功能,而这种写磁盘并不是用于访问,而仅是冗余功能,所以Redis所有功能都在内存中完成,因为此性能也是可想而知。

Redis与mamcache不同之处在于Redis有一个周期性的将数据保存到磁盘上的机制,而且不只一种,有两种机制,这也是Redis持久化的一种实现,另外与mamcache有所区别的是,Redis是单线程服务器,只有一个线程来响应所有的请求。

Redis支持主从模式,但是Redis的主从模式默认就有一个sentinel工具,从而实现主从架构的高可用,也就是说,Redis能够借助于sentinel工具来监控主从节点,当主节点发生故障时,会自己提升另外一个从节点成为新的主节点。

在Redis 3.0版本发布,开始支持Redis集群,从而可以实现分布式,可以将用户的请求分散至多个不同节点。

1.2  支持的数据类型

支持存储的数据类型有、String(字符串,包含整数), List(列表), Hash(关联数组), Sets(集合), Sorted Sets(有序集合), Bitmaps(位图), HyperLoglog。

1.3 性能评估

1、100万较小的键存储字符串,大概消耗100M内存。

2、由于Redis是单线程,如果服务器主机上有多个CPU,只有一个能够使用,但并不意味着CPU会成为瓶颈,因为Redis是一个比较简单的K-V数据存储,CPU通常不会成为瓶颈的。

3、在常见的linux服务器上,500K(50万)的并发,只需要一秒钟处理,如果主机硬件较好的情况下,每秒钟可以达到上百万的并发。

1.4 与Memcache对比

Memcache是一个分布式的内存对象缓存系统

而Redis是可以实现持久存储

Memcache是一个LRU的缓存

Redis支持更多的数据类型

Memcache是多线程的

Redis是单线程的

二者性能几乎不相上下,实际上Redis会受到硬盘持久化的影响,但是性能仍然保持在与Memcache不相上下,是非常了不起的

1.4.1 Redis优势

丰富的(资料形态)操作

String(字符串,包含整数), List(列表), Hash(关联数组), Sets(集合), Sorted Sets(有序集合), Bitmaps(位图), HyperLoglog

内建Replication和culster(自身支持复制及集群功能)

支持就地更新(in-place update)操作,直接可以在内存中完成更新操作

支持持久化(磁盘)

避免雪崩效应,万一出现雪崩效应,所有的数据都无法恢复,但Redis由于有持久性的数据,可以实现恢复

1.4.2 Memcached优势

多线程

善用多核CPU

更少的阻塞操作

更少的内存开销

更少的内存分配压力

可能有更少的内存碎片

2 部署Redis

2.1 源码包安装Redis

[root@Bob210 ~]# yum install -y gcc* #安装依赖

[root@Bob210 ~]# tar -xf redis-3.2.12.tar.gz -C /usr/local/

[root@Bob210 ~]# cd /usr/local/redis-3.2.12/

[root@Bob210 redis-3.2.12]# make

[root@Bob210 redis-3.2.12]# make install

cd src && make install

make[1]: Entering directory `/usr/local/redis-3.2.12/src'

 

Hint: It's a good idea to run 'make test' ;)

 

    INSTALL install

    INSTALL install

    INSTALL install

    INSTALL install

    INSTALL install

make[1]: Leaving directory `/usr/local/redis-3.2.12/src'

2.2 配置Redis

[root@Bob210 redis-3.2.12]# vim /usr/local/redis-3.2.12/utils/redis_init_script #编辑服务启动脚本

#!/bin/sh

#

# Simple Redis init.d script conceived to work on Linux systems

# as it does use of the /proc filesystem.

 

REDISPORT=6379

EXEC=/usr/local/redis-3.2.12/src/redis-server #启动程序

CLIEXEC=/usr/local/redis-3.2.12/src/redis-cli #客户端命令

 

PIDFILE=/var/run/redis_${REDISPORT}.pid

CONF="/usr/local/redis-3.2.12/${REDISPORT}.conf" #配置文件位置

 

case "$1" in

    start)

        if [ -f $PIDFILE ]

        then

                echo "$PIDFILE exists, process is already running or crashed"

        else

                echo "Starting Redis server..."

                $EXEC $CONF

        fi

        ;;

    stop)

        if [ ! -f $PIDFILE ]

        then

                echo "$PIDFILE does not exist, process is not running"

        else

                PID=$(cat $PIDFILE)

                echo "Stopping ..."

                $CLIEXEC -p $REDISPORT shutdown

                while [ -x /proc/${PID} ]

                do

                    echo "Waiting for Redis to shutdown ..."

                    sleep 1

                done

                echo "Redis stopped"

        fi

        ;;

    *)

        echo "Please use start or stop as first argument"

        ;;

esac

[root@Bob210 redis-3.2.12]# cp /usr/local/redis-3.2.12/redis.conf /usr/local/redis-3.2.12/6379.conf #按照上面的设置配置文件

2.3 启动与停止

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/utils/redis_init_script start & #启动(如果有密码,需要在启动脚本中添加密码)

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/utils/redis_init_script stop #停止

3 Redis常用操作

3.1 配置文件

参考链接:

https://www.cnblogs.com/zhang-ke/p/5981108.html

https://www.cnblogs.com/kreo/p/4423362.html

 

[root@Bob210 redis-3.2.12]# cat /usr/local/redis-3.2.12/6379.conf | grep -Ev '^$|^#'

bind 127.0.0.1 #服务端监听的地址,默认监听在127.0.0.1地址上,可以指定为0.0.0.0地址,或某个特定的地址,或可以指定多个,使用空格分隔即可。

protected-mode yes #是否开启保护模式,默认开启。开启该参数后,若配置里没有指定bind和密码,redis只会本地进行访问,拒绝外部访问。

port 6379 #监听端口

tcp-backlog 511 #此参数确定了TCP连接中已完成队列(完成三次握手之后)的长度, 当然此值必须不大于Linux系统定义的/proc/sys/net/core/somaxconn值,默认是511,而Linux的默认参数值是128。当系统并发量大并且客户端速度缓慢的时候,可以将这二个参数一起参考设定。该内核参数默认值一般是128,对于负载很大的服务程序来说大大的不够。一般会将它修改为2048或者更大。在/etc/sysctl.conf中添加:net.core.somaxconn = 2048,然后在终端中执行sysctl -p。

timeout 0 #此参数为设置客户端空闲超过timeout,服务端会断开连接,为0则服务端不会主动断开连接,不能小于0。

tcp-keepalive 300 #如果设置不为0,就使用配置tcp的SO_KEEPALIVE值,使用keepalive有两个好处:检测挂掉的对端。降低中间设备出问题而导致网络看似连接却已经与对端端口的问题。在Linux内核中,设置了keepalive,redis会定时给对端发送ack。检测到对端关闭需要两倍的设置值。

daemonize no #是否在后台运行,如果设置为yes,则启动命令不需要添加&

supervised no

pidfile /var/run/redis_6379.pid

loglevel notice

logfile ""

databases 16 #数据库数量,在分布式中只能使用一个。

save 900 1 #900秒(15分钟)内至少1个key值改变(则进行数据库保存--持久化)。

save 300 10 #300秒(5分钟)内至少10个key值改变(则进行数据库保存--持久化)。

save 60 10000 #60秒(1分钟)内至少10000个key值改变(则进行数据库保存--持久化)。

stop-writes-on-bgsave-error yes #当RDB持久化出现错误后,是否依然进行继续进行工作,yes:不能进行工作,no:可以继续进行工作,可以通过info中的rdb_last_bgsave_status了解RDB持久化是否有错误。

rdbcompression yes #使用压缩rdb文件,rdb文件压缩使用LZF压缩算法,yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间

rdbchecksum yes #是否校验rdb文件。从rdb格式的第五个版本开始,在rdb文件的末尾会带上CRC64的校验和。这跟有利于文件的容错性,但是在保存rdb文件的时候,会有大概10%的性能损耗,所以如果你追求高性能,可以关闭该配置。

dbfilename dump.rdb #rdb文件名

dir ./ #数据目录,数据库的写入会在这个目录。rdb、aof文件也会写在这个目录

slave-serve-stale-data yes #当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:1) 如果slave-serve-stale-data设置为yes(默认设置),从库会继续响应客户端的请求。2) 如果slave-serve-stale-data设置为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误”SYNC with master in progress”。

slave-read-only yes #作为从服务器,默认情况下是只读的(yes),可以修改成NO,用于写(不建议)。

repl-diskless-sync no #是否使用socket方式复制数据。目前redis复制提供两种方式,disk和socket。如果新的slave连上来或者重连的slave无法部分同步,就会执行全量同步,master会生成rdb文件。有2种方式:disk方式是master创建一个新的进程把rdb文件保存到磁盘,再把磁盘上的rdb文件传递给slave。socket是master创建一个新的进程,直接把rdb文件以socket的方式发给slave。disk方式的时候,当一个rdb保存的过程中,多个slave都能共享这个rdb文件。socket的方式就的一个个slave顺序复制。在磁盘速度缓慢,网速快的情况下推荐用socket方式。

repl-diskless-sync-delay 5 #diskless复制的延迟时间,防止设置为0。一旦复制开始,节点不会再接收新slave的复制请求直到下一个rdb传输。所以最好等待一段时间,等更多的slave连上来。

repl-disable-tcp-nodelay no #是否禁止复制tcp链接的tcp nodelay参数,可传递yes或者no。默认是no,即使用tcp nodelay。如果master设置了yes来禁止tcp nodelay设置,在把数据复制给slave的时候,会减少包的数量和更小的网络带宽。但是这也可能带来数据的延迟。默认我们推荐更小的延迟,但是在数据量传输很大的场景下,建议选择yes。

slave-priority 100 #当master不可用,Sentinel会根据slave的优先级选举一个master。最低的优先级的slave,当选master。而配置成0,永远不会被选举。

requirepass foobared #密码,在登录Redis后执行某些命令是需要。

appendonly no #默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入 appendonly.aof 文件,每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件。

appendfilename "appendonly.aof" #aof的文件名

appendfsync everysec #aof持久化策略的配置,no表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快。always表示每次写入都执行fsync,以保证数据同步到磁盘。everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。

no-appendfsync-on-rewrite no #在aof重写或者写入rdb文件的时候,会执行大量IO,此时对于everysec和always的aof模式来说,执行fsync会造成阻塞过长时间,no-appendfsync-on-rewrite字段设置为默认设置为no。如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。设置为yes表示rewrite期间对新写操作不fsync,暂时存在内存中,等rewrite完成后再写入,默认为no,建议yes。Linux的默认fsync策略是30秒。可能丢失30秒数据。

auto-aof-rewrite-percentage 100 #aof自动重写配置。当目前aof文件大小超过上一次重写的aof文件大小的百分之多少进行重写,即当aof文件增长到一定大小的时候Redis能够调用bgrewriteaof对日志文件进行重写。当前AOF文件大小是上次日志重写得到AOF文件大小的二倍(设置为100)时,自动启动新的日志重写过程。

auto-aof-rewrite-min-size 64mb #设置允许重写的最小aof文件大小,避免了达到约定百分比但尺寸仍然很小的情况还要重写

aof-load-truncated yes #aof文件可能在尾部是不完整的,当redis启动的时候,aof文件的数据被载入内存。重启可能发生在redis所在的主机操作系统宕机后,尤其在ext4文件系统没有加上data=ordered选项(redis宕机或者异常终止不会造成尾部不完整现象。)出现这种现象,可以选择让redis退出,或者导入尽可能多的数据。如果选择的是yes,当截断的aof文件被导入的时候,会自动发布一个log给客户端然后load。如果是no,用户必须手动redis-check-aof修复AOF文件才可以。

lua-time-limit 5000 #如果达到最大时间限制(毫秒),redis会记个log,然后返回error。当一个脚本超过了最大时限。只有SCRIPT KILL和SHUTDOWN NOSAVE可以用。第一个可以杀没有调write命令的东西。要是已经调用了write,只能用第二个命令杀。

slowlog-log-slower-than 10000 #执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。

slowlog-max-len 128 #慢查询日志长度。当一个新的命令被写进日志的时候,最老的那个记录会被删掉。这个长度没有限制。只要有足够的内存就行。你可以通过 SLOWLOG RESET 来释放内存。

latency-monitor-threshold 0 #延迟监控功能是用来监控redis中执行比较缓慢的一些操作,用LATENCY打印redis实例在跑命令时的耗时图表。只记录大于等于下边设置的值的操作。0的话,就是关闭监视。默认延迟监控功能是关闭的,如果你需要打开,也可以通过CONFIG SET命令动态设置。

notify-keyspace-events ""

#键空间通知使得客户端可以通过订阅频道或模式,来接收那些以某种方式改动了 Redis 数据集的事件。因为开启键空间通知功能需要消耗一些 CPU ,所以在默认配置下,该功能处于关闭状态。

#notify-keyspace-events 的参数可以是以下字符的任意组合,它指定了服务器该发送哪些类型的通知:

##K 键空间通知,所有通知以 __keyspace@__ 为前缀

##E 键事件通知,所有通知以 __keyevent@__ 为前缀

##g DEL 、 EXPIRE 、 RENAME 等类型无关的通用命令的通知

##$ 字符串命令的通知

##l 列表命令的通知

##s 集合命令的通知

##h 哈希命令的通知

##z 有序集合命令的通知

##x 过期事件:每当有过期键被删除时发送

##e 驱逐(evict)事件:每当有键因为 maxmemory 政策而被删除时发送

##A 参数 g$lshzxe 的别名

#输入的参数中至少要有一个 K 或者 E,否则的话,不管其余的参数是什么,都不会有任何 通知被分发。详细使用可以参考

hash-max-ziplist-entries 512 #数据量小于等于hash-max-ziplist-entries的用ziplist,大于hash-max-ziplist-entries用hash。

hash-max-ziplist-value 64 #value大小小于等于hash-max-ziplist-value的用ziplist,大于hash-max-ziplist-value用hash。

list-max-ziplist-size -2 #

list-compress-depth 0

set-max-intset-entries 512 #数据量小于等于set-max-intset-entries用iniset,大于set-max-intset-entries用set。

zset-max-ziplist-entries 128 #数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用zset。

zset-max-ziplist-value 64 #value大小小于等于zset-max-ziplist-value用ziplist,大于zset-max-ziplist-value用zset。

hll-sparse-max-bytes 3000 #value大小小于等于hll-sparse-max-bytes使用稀疏数据结构(sparse),大于hll-sparse-max-bytes使用稠密的数据结构(dense)。一个比16000大的value是几乎没用的,建议的value大概为3000。如果对CPU要求不高,对空间要求较高的,建议设置到10000左右。

activerehashing yes #Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存。

client-output-buffer-limit normal 0 0 0 #对客户端输出缓冲进行限制可以强迫那些不从服务器读取数据的客户端断开连接,用来强制关闭传输缓慢的客户端。对于normal client,第一个0表示取消hard limit,第二个0和第三个0表示取消soft limit,normal client默认取消限制,因为如果没有寻问,他们是不会接收数据的。

client-output-buffer-limit slave 256mb 64mb 60 #对于slave client和MONITER client,如果client-output-buffer一旦超过256mb,又或者超过64mb持续60秒,那么服务器就会立即断开客户端连接。

client-output-buffer-limit pubsub 32mb 8mb 60 #对于pubsub client,如果client-output-buffer一旦超过32mb,又或者超过8mb持续60秒,那么服务器就会立即断开客户端连接。

hz 10 #redis执行任务的频率为1s除以hz。

aof-rewrite-incremental-fsync yes #在aof重写的时候,如果打开了aof-rewrite-incremental-fsync开关,系统会每32MB执行一次fsync。这对于把文件写入磁盘是有帮助的,可以避免过大的延迟峰值。

3.2 常用命令

参考链接:

https://www.cnblogs.com/kongzhongqijing/p/6867960.html

命令:

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/src/redis-cli --help #查看命令使用帮助

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/src/redis-cli [选项] [参数] ...

选项:

-h [host] 指定主机

-p [port] 指定端口

-s [socket] 指定socket文件。如果客户端和服务器在同一台服务器上指定了socket文件则仅使用socket通信而不需要使用TCP等协议通信,可降低开销。

-a [password] 指定认证密码

-r [repeat] 连接成功后运行指定的命令的次数

-i [interval] 连接成功后每个命令执行完成的等待时间

...

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/src/redis-cli

127.0.0.1:6379> info #获取数据库信息

127.0.0.1:6379> help #获取使用帮助,redis的help命令非常强大,因为redis支持众多的数据结构,每一种数据结构当中都支持N种操作,因此需使用 help @group方式来获取某一种数据结构所支持的操作。

redis-cli 3.2.12

To get help about Redis commands type:

      "help @<group>" to get a list of commands in <group>

      "help <command>" for help on <command>

      "help <tab>" to get a list of possible help topics

      "quit" to exit

 

To set redis-cli perferences:

      ":set hints" enable online hints

      ":set nohints" disable online hints

Set your preferences in ~/.redisclirc

127.0.0.1:6379> help @string #获取字符串支持的操作。

127.0.0.1:6379> help append #获取append命令的使用方法

 

  APPEND key value #命令格式

  summary: Append a value to a key #使用说明

  since: 2.0.0 #说明此命令是从哪个版本引入的

  group: string #该命令所属的组

127.0.0.1:6379> select 1 #切换到1号数据库(也叫名称空间)

OK

127.0.0.1:6379[1]> select 15 #切换到15号数据库(最大15,最小0)

OK

127.0.0.1:6379[15]> select 0 #切换到0号数据库

OK

127.0.0.1:6379> FLUSHDB #删除当前库中的所有key

OK

127.0.0.1:6379> FLUSHALL #清空所有的库

OK

127.0.0.1:6379> CONFIG GET dir #获取数据库写入的目录的配置

1) "dir"

2) "/root"

3.3 键的遵循

键的名称可以使用ASCII字符,长度不要过长,键的长度越长则消耗的空间越多。

在同一个库中(名称空间),键的名称不得重复,如果复制键的名称,实际上是修改键中的值。

在不同的库中(名称空间),键的名称可以重复。

键可以实现自动过期。

3.4 字符串操作

127.0.0.1:6379> help set #查看set用法

 

  SET key value [EX seconds] [PX milliseconds] [NX|XX] #set 键名 键值 [有效期 秒] [有效期 毫秒] [只有key不存在时才设置key的值|只有key存在时才设置key的值]

  summary: Set the string value of a key

  since: 1.0.0

  group: string

127.0.0.1:6379> set a b #设置键名为a的键值为b

OK

127.0.0.1:6379> get a #获取键名为a的键值

"b"

127.0.0.1:6379> set a c NX #如果a不存在则设置a的键值为c(失败)

(nil)

127.0.0.1:6379> set c a XX #如果c存在则设置c的键值为a(失败)

(nil)

127.0.0.1:6379> get c #c不存在

(nil)

127.0.0.1:6379> get a

"b"

127.0.0.1:6379> append a bc #在a中添加bc

(integer) 3 #这里显示a中共有3个字符

127.0.0.1:6379> get a #再次查看a的值

"bbc"

127.0.0.1:6379> strlen a #查看a的长度

(integer) 3

127.0.0.1:6379> set int 0

OK

127.0.0.1:6379> get int

"0"

127.0.0.1:6379> incr int #自增1(该命令只对整数有效)

(integer) 1

127.0.0.1:6379> incr int #再增1

(integer) 2

127.0.0.1:6379> get int #查看

"2"

127.0.0.1:6379> keys * #查看所有的键

1) "int"

2) "b"

3) "a"

127.0.0.1:6379> del a #删除键

(integer) 1

127.0.0.1:6379> keys *

1) "int"

2) "b"

3.5 列表操作

参考链接:https://redis.io/topics/data-types-intro

列表,可以理解为一个字符串的容器,它是众多元素组成的集合,可以在列表中对元素进行增删改查。而我们可以用键指向列表,那么这个键的值就对应了这个列表对象。

 

127.0.0.1:6379> RPUSH mylist A #创建列表mylist,并在右边加入一个元素A。(使用lpush或rpush命令时如果列表不存在则会自动创建列表)

127.0.0.1:6379> RPUSH mylist B #在列表的右边添加元素B

(integer) 2

127.0.0.1:6379> LPUSH mylist first #在列表的左边添加元素first

(integer) 3

127.0.0.1:6379> LINDEX mylist 0 #获取列表的第一个元素的值(索引从0开始)

"first"

127.0.0.1:6379> LRANGE mylist 0 6 #获取列表的第1-7个元素的值(从0开始)

1) "first"

2) "A"

3) "B"

127.0.0.1:6379> LRANGE mylist 0 -1 #获取列表中的所有元素的值(0代表第一个,-1代表最后一个)

1) "first"

2) "A"

3) "B"

127.0.0.1:6379> LRANGE mylist 0 -2 #获取列表中第1至倒数第二个元素的值(-1表示最后一个元素,-2表示list中的倒数第二个元素,以此类推。)

1) "first"

2) "A"

127.0.0.1:6379> RPUSH mylist 1 2 3 4 5 "foo bar" #一次添加多个元素

(integer) 9

127.0.0.1:6379> LRANGE mylist 0 -1

1) "first"

2) "A"

3) "B"

4) "1"

5) "2"

6) "3"

7) "4"

8) "5"

9) "foo bar"

127.0.0.1:6379> RPOP mylist #从列表的右边删除一个元素

"foo bar"

127.0.0.1:6379> LPOP mylist #从列表的左边删除一个元素

"first"

127.0.0.1:6379> LINDEX mylist 2

"1"

127.0.0.1:6379> LSET mylist 2 C #将列表的第3个元素的值改为C

OK

127.0.0.1:6379> LINDEX mylist 2

"C"

127.0.0.1:6379> LLEN mylist #查看列表中元素的数量

(integer) 7

3.6 认证

[root@Bob210 ~]# vim /usr/local/redis-3.2.12/6379.conf

 480 # requirepass foobared

 481 requirepass foobared #设置认证密码

[root@Bob210 ~]# /usr/local/redis-3.2.12/utils/redis_init_script stop

[root@Bob210 ~]# /usr/local/redis-3.2.12/utils/redis_init_script start

[root@Bob210 ~]# /usr/local/redis-3.2.12/src/redis-cli

127.0.0.1:6379> keys *

(error) NOAUTH Authentication required. #我们发现此时报错

127.0.0.1:6379> auth foobared

OK

127.0.0.1:6379> keys * #此时就不报错了

1) "ll"

2) "a"

3) "mylist"

[root@Bob210 ~]# /usr/local/redis-3.2.12/src/redis-cli -a foobared #也可以在登录数据库时指定密码

127.0.0.1:6379> keys *

1) "a"

4 持久化

参考链接:https://redis.io/topics/persistence

4.1 概述

默认情况下,redis工作时所有数据集都是存储于内存中的,不论是否有磁盘上的持久化数据,都是工作于内存当中,redis本身就是一个内存的数据库,把所有数据库相关的存储都存储在内存中,如果redis崩溃或断电会导致所有数据丢失,所以redis提供了持久化功能来保证数据的可靠性,redis持久化有两种实现,RDB和AOF。注意:持久本身不能取代备份;还应该制定备份策略,对redis数据库定期进行备份。

4.2 RDB

4.2.1介绍

RDB将数据存储为二进制格式的数据文件,默认启动的持久化机制;按事先定制的策略,周期性地将数据保存至磁盘,使用save命令即可设定周期和策略即可;数据文件默认为dump.rdb。也可以通过调用 SAVE或者 BGSAVE , 手动让 Redis 进行数据集保存操作。

当 Redis 需要保存 dump.rdb 文件时, 服务器执行以下操作:

1)Redis 调用forks. 同时拥有父进程和子进程。

2)子进程将数据集写入到一个临时 RDB 文件中。

3)当子进程完成对新 RDB 文件的写入时,Redis 用新 RDB 文件替换原来的 RDB 文件,并删除旧的 RDB 文件。

这种工作方式使得 Redis 可以从写时复制(copy-on-write)机制中获益。

4.2.2 方式

1)手动通过SAVE或BGSAVE保存。

SAVE: 是同步保存,在客户端使用save保存快照时,是在redis主线程中保存快照;因为redis的主线程是用于处理请求的,所以此时会阻塞所有客户端请求,每次的保存快照都是把内存中的数据完整的保存一份,并非是增量的,如果内存中的数据比较大,而还有大量的写操作请求时,此方式会引起大量的I/O,会导致redis性能下降。如果是在配置文件中定义的save,那么redis在持久化的时候,则会开启另外的进程去处理,不会阻塞redis的主进程。

BGSAVE:异步方式,将立即返回结果,但自动在后台保持操作,所以BGSAVE命令启动以后,前台不会被占用,客户端的请求是不会被阻塞(主进程不会被阻塞)。

例:

127.0.0.1:6379> SAVE

OK

127.0.0.1:6379> BGSAVE

Background saving started

2)借助于配置文件所定义的策略进行周期性的保存。

例:

[root@Bob210 ~]# vim /usr/local/redis-3.2.12/6379.conf

 202 save 900 1 #900秒内至少有1个键被改动时,自动保存一次数据

 203 save 300 10 #300秒内至少有10个键被改动时,自动保存一次数据

 204 save 60 10000 #60秒内至少有10000个键呗改动时,自动保存一次数据

4.2.3 优点

1)RDB是一个非常紧凑的文件,它保存了某个时间点得数据集,非常适用于数据集的备份,比如你可以在每个小时报保存一下过去24小时内的数据,同时每天保存过去30天的数据,这样即使出了问题你也可以根据需求恢复到不同版本的数据集.

2)RDB是一个紧凑的单一文件,很方便传送到另一个远端数据中心或者亚马逊的S3(可能加密),非常适用于灾难恢复.

3)RDB在保存RDB文件时父进程唯一需要做的就是fork出一个子进程,接下来的工作全部由子进程来做,父进程不需要再做其他IO操作,所以RDB持久化方式可以最大化redis的性能.

4)与AOF相比,在恢复大的数据集的时候,RDB方式会更快一些.

4.2.4 缺点

1)如果你希望在redis意外停止工作(例如电源中断)的情况下丢失的数据最少的话,那么RDB不适合你.虽然你可以配置不同的save时间点(例如每隔5分钟并且对数据集有100个写的操作),是Redis要完整的保存整个数据集是一个比较繁重的工作,你通常会每隔5分钟或者更久做一次完整的保存,万一在Redis意外宕机,你可能会丢失几分钟的数据.

2)RDB 需要经常fork子进程来保存数据集到硬盘上,当数据集比较大的时候,fork的过程是非常耗时的,可能会导致Redis在一些毫秒级内不能响应客户端的请求.如果数据集巨大并且CPU性能不是很好的情况下,这种情况会持续1秒,AOF也需要fork,但是你可以调节重写日志文件的频率来提高数据集的耐久度.

4.2.5 配置

[root@Bob210 ~]# vim /usr/local/redis-3.2.12/6379.conf

save 900 1 #900秒内至少有1个键被改动时,自动保存一次数据

save 300 10 #300秒内至少有10个键被改动时,自动保存一次数据

save 60 10000 #60秒内至少有10000个键呗改动时,自动保存一次数据

stop-writes-on-bgsave-error yes #在进行快照备份(RDB)时,一旦发生错误的话是否停止写操作

rdbcompression yes #RDB文件是否使用压缩,压缩会消耗CPU

rdbchecksum yes #是否对RDB文件做校验码检测,此项定义在redis启动时加载RDB文件是否对文件检查校验码,在redis生成RDB文件是会生成校验信息,在redis再次启动或装载RDB文件时,是否检测校验信息,如果检测的情况下会消耗时间,会导致redis启动时慢,但是能够判断RDB文件是否产生错误

dbfilename dump.rdb #定义RDB文件的名称

dir /var/lib/redis #定义RDB文件存放的目录路径

4.3 AOF

4.3.1 介绍

AOF:Append Only File,有着更好的持久化能力的解决方案,AOF类似于MySQL的二进制日志,记录每一次redis的写操作命令,以顺序IO方式附加在指定文件的尾部,是使用追加方式实现的,这也叫做一种附加日志类型的持久化机制,由于每一次的操作都记录,则会随着时间长而增大文件的容量,并且有些记录的命令是多余的,AOF不像RDB,RDB是保存数据集的本身。

4.3.2 方式

可以配置 Redis 多久才将数据 fsync 到磁盘一次。有三种方式:

1)每次有新命令追加到 AOF 文件时就执行一次 fsync :非常慢,也非常安全。

2)每秒 fsync 一次:足够快(和使用 RDB 持久化差不多),并且在故障时只会丢失 1 秒钟的数据。

3)从不 fsync :将数据交给操作系统来处理。更快,也更不安全的选择。

4)推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。

4.3.3 重写

因为 AOF 的运作方式是不断地将命令追加到文件的末尾, 所以随着写入命令的不断增加, AOF 文件的体积也会变得越来越大。举个例子, 如果你对一个计数器调用了 100 次 INCR , 那么仅仅是为了保存这个计数器的当前值, AOF 文件就需要使用 100 条记录(entry)。然而在实际上, 只使用一条 SET 命令已经足以保存计数器的当前值了, 其余 99 条记录实际上都是多余的。

为了处理这种情况, Redis 支持一种有趣的特性: 可以在不打断服务客户端的情况下, 对 AOF 文件进行重建(rebuild)。执行 BGREWRITEAOF 命令, Redis 将生成一个新的 AOF 文件, 这个文件包含重建当前数据集所需的最少命令。Redis 2.2 需要自己手动执行 BGREWRITEAOF 命令; Redis 2.4 则可以自动触发 AOF 重写。

 

AOF 重写和 RDB 创建快照一样,都巧妙地利用了写时复制机制:

1)Redis 执行 fork() ,现在同时拥有父进程和子进程。

2)子进程开始将新 AOF 文件的内容写入到临时文件。

3)对于所有新执行的写入命令,父进程一边将它们累积到一个内存缓存中,一边将这些改动追加到现有 AOF 文件的末尾,这样样即使在重写的中途发生停机,现有的 AOF 文件也还是安全的。

4)当子进程完成重写工作时,它给父进程发送一个信号,父进程在接收到信号之后,将内存缓存中的所有数据追加到新 AOF 文件的末尾。

5)搞定!现在 Redis 原子地用新文件替换旧文件,之后所有命令都会直接追加到新 AOF 文件的末尾。

4.3.3 优点

1)使用AOF 会让你的Redis更加耐久: 你可以使用不同的fsync策略:无fsync,每秒fsync,每次写的时候fsync.使用默认的每秒fsync策略,Redis的性能依然很好(fsync是由后台线程进行处理的,主线程会尽力处理客户端请求),一旦出现故障,你最多丢失1秒的数据.

2)AOF文件是一个只进行追加的日志文件,所以不需要写入seek,即使由于某些原因(磁盘空间已满,写的过程中宕机等等)未执行完整的写入命令,你也也可使用redis-check-aof工具修复这些问题.

3)Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写: 重写后的新 AOF 文件包含了恢复当前数据集所需的最小命令集合。 整个重写操作是绝对安全的,因为 Redis 在创建新 AOF 文件的过程中,会继续将命令追加到现有的 AOF 文件里面,即使重写过程中发生停机,现有的 AOF 文件也不会丢失。 而一旦新 AOF 文件创建完毕,Redis 就会从旧 AOF 文件切换到新 AOF 文件,并开始对新 AOF 文件进行追加操作。

4)AOF 文件有序地保存了对数据库执行的所有写入操作, 这些写入操作以 Redis 协议的格式保存, 因此 AOF 文件的内容非常容易被人读懂, 对文件进行分析(parse)也很轻松。 导出(export) AOF 文件也非常简单: 举个例子, 如果你不小心执行了 FLUSHALL 命令, 但只要 AOF 文件未被重写, 那么只要停止服务器, 移除 AOF 文件末尾的 FLUSHALL 命令, 并重启 Redis , 就可以将数据集恢复到 FLUSHALL 执行之前的状态。

4.3.5 缺点

1)对于相同的数据集来说,AOF 文件的体积通常要大于 RDB 文件的体积。

2)根据所使用的 fsync 策略,AOF 的速度可能会慢于 RDB 。 在一般情况下, 每秒 fsync 的性能依然非常高, 而关闭 fsync 可以让 AOF 的速度和 RDB 一样快, 即使在高负荷之下也是如此。 不过在处理巨大的写入载入时,RDB 可以提供更有保证的最大延迟时间(latency)。

4.3.6 配置

[root@Bob210 ~]# vim /usr/local/redis-3.2.12/6379.conf

appendonly no //定义是否开启AOF功能,默认为关闭

appendfilename "appendonly.aof" //定义AOF文件

appendfsync always //表示每次收到写命令时,立即写到磁盘上的AOF文件,虽然是最好的持久化功能,但是每次有写命令时都会有磁盘的I/O操作,容易影响redis的性能

appendfsync everysec //表示每秒钟写一次,不管每秒钟收到多少个写请求都往磁盘中的AOF文件中写一次

appendfsync no //表示append功能不会触发写操作,所有的写操作都是提交给OS,由OS自行决定是如何写的

no-appendfsync-on-rewrite no //当此项为yes时,表示在重写时,对于新的写操作不做同步,而暂存在内存中

auto-aof-rewrite-percentage 100 //表示当前AOF文件的大小是上次重写AOF文件的二倍时,则自动日志重写过程

auto-aof-rewrite-min-size 64mb //定义AOF文件重写过程的条件,最少为定义大小则触发重写过程

4.3.7 修复

服务器可能在程序正在对 AOF 文件进行写入时停机, 如果停机造成了 AOF 文件出错(corrupt), 那么 Redis 在重启时会拒绝载入这个 AOF 文件, 从而确保数据的一致性不会被破坏。当发生这种情况时, 可以用以下方法来修复出错的 AOF 文件:

1)为现有的 AOF 文件创建一个备份。

2)使用 Redis 附带的 redis-check-aof 程序,对原来的 AOF 文件进行修复:

$ redis-check-aof –fix

3)(可选)使用 diff -u 对比修复后的 AOF 文件和原始 AOF 文件的备份,查看两个文件之间的不同之处。

4)重启 Redis 服务器,等待服务器载入修复后的 AOF 文件,并进行数据恢复。

4.4 RDB切换AOF

在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :

1)为最新的 dump.rdb 文件创建一个备份。

2)将备份放到一个安全的地方。

3)执行以下两条命令:

redis-cli config set appendonly yes #开启了 AOF 功能: Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。

redis-cli config set save “” #关闭 RDB 功能。 这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。

4)确保写命令会被正确地追加到 AOF 文件的末尾。

5)重要:别忘了在 redis.conf 中打开 AOF 功能! 否则的话, 服务器重启之后, 之前通过 CONFIG SET 设置的配置就会被遗忘, 程序会按原来的配置来启动服务器。

4.5 RDB和AOF相互作用

在版本号大于等于 2.4 的 Redis 中, BGSAVE 执行的过程中, 不可以执行 BGREWRITEAOF 。 反过来说, 在 BGREWRITEAOF 执行的过程中, 也不可以执行 BGSAVE。这可以防止两个 Redis 后台进程同时对磁盘进行大量的 I/O 操作。

如果 BGSAVE 正在执行, 并且用户显示地调用 BGREWRITEAOF 命令, 那么服务器将向用户回复一个 OK 状态, 并告知用户, BGREWRITEAOF 已经被预定执行: 一旦 BGSAVE 执行完毕, BGREWRITEAOF 就会正式开始。 当 Redis 启动时, 如果 RDB 持久化和 AOF 持久化都被打开了, 那么程序会优先使用 AOF 文件来恢复数据集, 因为 AOF 文件所保存的数据通常是最完整的。

4.6 如何选择

1)一般来说, 如果想达到足以媲美 PostgreSQL 的数据安全性, 你应该同时使用两种持久化功能。

2)如果你非常关心你的数据, 但仍然可以承受数分钟以内的数据丢失, 那么你可以只使用 RDB 持久化。

3)有很多用户都只使用 AOF 持久化, 但我们并不推荐这种方式: 因为定时生成 RDB 快照(snapshot)非常便于进行数据库备份, 并且 RDB 恢复数据集的速度也要比 AOF 恢复的速度要快, 除此之外, 使用 RDB 还可以避免之前提到的 AOF 程序的 bug 。

5 主从

参考链接:https://redis.io/topics/replication

主库会基于pingcheck方式检查从库是否在线,如果在线则直接同步数据文件至从服务端,从服务端也可以主动发送同步请求到主服务端,主库如果是启动了持久化功能时,会不断的同步数据到磁盘上,主库一旦收到从库的同步请求时,主库会将内存中的数据做快照,然后把数据文件同步给从库,从库得到以后是保存在本地文件中(磁盘),而后则把该文件装载到内存中完成数据重建,链式复制也同步如此,因为主是不区分是真正的主,还是另外一个的从。

5.1 工作过程

1、启动slave。

2、slave会向master发送同步命令,请求主库上的数据,不论从是第一次连接,还是非第一次连接,master此时都会启动一个后台的子进程将数据快照保存在数据文件中,然后把数据文件发送给slave。

3、slave收到数据文件 以后会保存到本地,而后把文件重载装入内存。

5.2 特点

1、一个Master可以有多个Slave;

2、支持链式复制(一个slave也可以是其他的slave的slave);

3、Master以非阻塞方式同步数据至slave(master可以同时处理多个slave的读写请求,salve端在同步数据时也可以使用非阻塞方式);

5.3 部署

 

master

slave

ip

10.66.13.210

10.66.13.211

port

6379

6379

 

[root@Bob210 redis-3.2.12]# vim /usr/local/redis-3.2.12/6379.conf #首先要把主库的监听地址放开

  61 bind 0.0.0.0

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/utils/redis_init_script stop #需要重启

Stopping ...

Redis stopped

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/utils/redis_init_script start

Starting Redis server...

[root@Bob211 redis-3.2.12]# /usr/local/redis-3.2.12/src/redis-cli #进入从库

127.0.0.1:6379> SLAVEOF 10.66.13.210 6379 #临时配置,指定他的主库

45158:S 09 Aug 16:09:00.683 * SLAVE OF would result into synchronization with the master we are already connected with. No operation performed.

OK Already connected to specified master

[root@Bob211 redis-3.2.12]# vim /usr/local/redis-3.2.12/6379.conf #在从库的配置文件中设置

 266 slaveof 10.66.13.210 6379

127.0.0.1:6379> keys * #我们看到数据已经同步

1) "int"

2) "b"

127.0.0.1:6379> info Replication #查看slave信息

# Replication

role:slave

master_host:10.66.3.210

master_port:6379

master_link_status:down

master_last_io_seconds_ago:-1

master_sync_in_progress:0

slave_repl_offset:1

master_link_down_since_seconds:1533802946

slave_priority:100

slave_read_only:1

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

127.0.0.1:6379> info replication #查看master信息

# Replication

role:master

connected_slaves:1

slave0:ip=10.66.13.211,port=6379,state=online,offset=1693,lag=0

master_repl_offset:1693

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2

repl_backlog_histlen:1692

5.4 配置说明

slave-serve-stale-data yes //表示当主服务器不可以用时,则无法判定数据是否过期,此时从服务器仍然接收到读请求时,yes表示仍然响应(继续使用过期数据)

slave-read-only yes //启用slave时,该服务器是否为只读

repl-diskless-sync no //是否基于diskless机制进行sync操作,一般情况下如果disk比较慢,网络带宽比较大时,在做复制时,此项可以改为Yes

repl-diskless-sync-delay 5 //指定在slave下同步数据到磁盘的延迟时间,默认为5秒,0表示不延迟

slave-priority 100 //指定slave优先级,如果有多个slave时,那一个slave将优先被同步

min-slaves-to-write 3 //此项表示在主从复制模式当中,如果给主服务器配置了多个从服务器时,如果在从服务器少于3个时,那么主服务器将拒绝接收写请求,从服务器不能少于该项的指定值,主服务器才能正常接收用户的写请求

min-slaves-max-lag 10 //表示从服务器与主服务器的时差不能够相差于10秒钟以上,否则写操作将拒绝进行

masterauth foobard //如果master设置的有密码,则slave要指定密码

6 sentinel

参考链接:https://redis.io/topics/sentinel

sentinel安装在另外的主机上,sentinel主机既能监控又能提供配置功能,向sentinel指明主redis服务器即可(仅监控主服务器),sentinel可以从主服务中获取主从架构信息,并分辨从节点。

sentinel可以监控当前整个主从服务器架构的工作状态,一旦发现master离线的情况,sentinel会从多个从服务器中选择并提升一个从节点成为主节点。

当主节点被从节点取代以后,那么IP地址则发生了变化,客户所连接之前的主节点IP则无法连接,此时可以向sentinel发起查询请求,sentinel会告知客户端新的主节点的IP,所以sentinel是redis在主从架构中实现高可用的解决方案。

sentinel为了防止误判和单点故障,sentinel也应该组织为集群,sentinel多个节点同时监控redis主从架构,一旦有一个sentinel节点发现redis的主节点不在线时,sentinel会与其他的sentinel节点协商其他的sentinel节点是否也为同样发现redis的主节点不在线的情况,如果sentinel的多个点节点都发现redis的主节点都为离线的情况,那么则判定redis主节点为离线状态,以此方式避免误判,同样也避免了单点故障。

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

6.1 部署

我们在一台主机上面开启多个Redis实例,来模拟多台Redis服务器。

 

ip

port

sentinel

10.66.13.210

26379

master

10.66.13.210

6379

slave

10.66.13.210

6380

slave

10.66.13.210

6381

6.1.1 配置Redis

[root@Bob210 ~]# mkdir -pv /etc/redis #创建配置文件目录

[root@Bob210 ~]# cp /usr/local/redis-3.2.12/6379.conf /etc/redis/ #准备配置文件

[root@Bob210 ~]# cp /usr/local/redis-3.2.12/6379.conf /etc/redis/6380.conf

[root@Bob210 ~]# cp /usr/local/redis-3.2.12/6379.conf /etc/redis/6381.conf

[root@Bob210 ~]# mkdir -pv /usr/local/redis-3.2.12/db{6379,6380,6381} #准备数据库存放目录

[root@Bob210 ~]# mkdir -pv /var/log/redis #准备日志目录

[root@Bob210 ~]# sed -i 's/^port 6379/port 6380/' /etc/redis/6380.conf #修改端口号

[root@Bob210 ~]# sed -i 's/^port 6379/port 6381/' /etc/redis/6381.conf

[root@Bob210 ~]# sed -i 's/^pidfile \/var\/run\/redis_6379.pid/pidfile \/var\/run\/redis_6380.pid/' /etc/redis/6380.conf #修改pid路径

[root@Bob210 ~]# sed -i 's/^pidfile \/var\/run\/redis_6379.pid/pidfile \/var\/run\/redis_6381.pid/' /etc/redis/6381.conf

[root@Bob210 ~]# sed -i 's/^logfile ""/logfile \/var\/log\/redis\/redis_6379.log/' /etc/redis/6379.conf #修改日志路径

[root@Bob210 ~]# sed -i 's/^logfile ""/logfile \/var\/log\/redis\/redis_6380.log/' /etc/redis/6380.conf

[root@Bob210 ~]# sed -i 's/^logfile ""/logfile \/var\/log\/redis\/redis_6381.log/' /etc/redis/6381.conf

[root@Bob210 ~]# sed -i 's/^dir .\//dir \/usr\/local\/redis-3.2.12\/db6379/' /etc/redis/6379.conf #修改数据库存放目录

[root@Bob210 ~]# sed -i 's/^dir .\//dir \/usr\/local\/redis-3.2.12\/db6380/' /etc/redis/6380.conf

[root@Bob210 ~]# sed -i 's/^dir .\//dir \/usr\/local\/redis-3.2.12\/db6381/' /etc/redis/6381.conf

[root@Bob210 ~]# sed -i '/^# slaveof <masterip> <masterport>/a slaveof 10.66.13.210 6379\' /etc/redis/6380.conf #slave设置指定其master

[root@Bob210 ~]# sed -i '/^# slaveof <masterip> <masterport>/a slaveof 10.66.13.210 6379\' /etc/redis/6381.conf

 

[root@Bob210 ~]# vim /etc/init.d/redis-6379 #准备Redis启动脚本

#!/bin/sh

#chkconfig:2345 85 15

# Simple Redis init.d script conceived to work on Linux systems

# as it does use of the /proc filesystem.

 

REDISPORT=6379

EXEC=/usr/local/redis-3.2.12/src/redis-server

CLIEXEC=/usr/local/redis-3.2.12/src/redis-cli

 

PIDFILE=/var/run/redis_${REDISPORT}.pid

CONF="/etc/redis/${REDISPORT}.conf"

 

startRedis()

{

        if [ -f $PIDFILE ]

        then

                echo "$PIDFILE exists, process is already running or crashed"

        else

                echo "Starting Redis server..."

                $EXEC $CONF

        fi

}

 

stopRedis()

{

        if [ ! -f $PIDFILE ]

        then

                echo "$PIDFILE does not exist, process is not running"

        else

                PID=$(cat $PIDFILE)

                echo "Stopping ..."

                $CLIEXEC -p $REDISPORT shutdown

                while [ -x /proc/${PID} ]

                do

                    echo "Waiting for Redis to shutdown ..."

                    sleep 1

                done

                echo "Redis stopped"

        fi

}

case "$1" in

    start)

startRedis

        ;;

    stop)

stopRedis

        ;;

    restart)

stopRedis

startRedis

;;

    *)

        echo "Please use start or stop as first argument"

        ;;

esac

[root@Bob210 ~]# cp /etc/init.d/redis-6379 /etc/init.d/redis-6380

[root@Bob210 ~]# cp /etc/init.d/redis-6379 /etc/init.d/redis-6381

[root@Bob210 ~]# sed -i 's/^REDISPORT=6379/REDISPORT=6380/' /etc/init.d/redis-6380

[root@Bob210 ~]# sed -i 's/^REDISPORT=6379/REDISPORT=6381/' /etc/init.d/redis-6381

[root@Bob210 ~]# chkconfig --add redis-6379 #添加开机自启动

[root@Bob210 ~]# chkconfig --add redis-6380

[root@Bob210 ~]# chkconfig --add redis-6381

6.1.2配置sentinel

[root@Bob210 ~]# cp /usr/local/redis-3.2.12/sentinel.conf /etc/redis/

[root@Bob210 ~]# sed -i '/^# bind 127.0.0.1 192.168.1.1/a bind 0.0.0.0\' /etc/redis/sentinel.conf #修改bind

[root@Bob210 ~]# sed -i 's/^sentinel monitor mymaster 127.0.0.1 6379 2/sentinel monitor mymaster 10.66.13.210 6379 1/' /etc/redis/sentinel.conf

[root@Bob210 ~]# vim /etc/init.d/redis-sentinel #准备启动脚本

#!/bin/sh

#chkconfig:2345 85 15

 

EXEC=/usr/local/redis-3.2.12/src/redis-sentinel

CONF=/etc/redis/sentinel.conf

 

startSentinel()

{

nohup $EXEC $CONF &

}

 

stopSentinel()

{

ps aux | grep ${EXEC} | grep -v grep &> /dev/null

if [ $? -eq 0 ]

then

kill -9 `ps aux | grep -v grep | grep /usr/local/redis-3.2.12/src/redis-sentinel | awk '{print $2}'`

else

echo 'stop failed'

fi

}

 

case "$1" in

    start)

startSentinel

        ;;

    stop)

stopSentinel

        ;;

    restart)

stopSentinel

startSentinel

;;

    *)

        echo "Please use start or stop as first argument"

        ;;

esac

[root@Bob210 ~]# chmod +x /etc/init.d/redis-sentinel

[root@Bob210 ~]# chkconfig --add redis-sentinel

6.1.3启动

[root@Bob210 ~]# service redis-6379 start #分别启动3个Redis实例

Starting Redis server...

[root@Bob210 ~]# service redis-6380 start

Starting Redis server...

[root@Bob210 ~]# service redis-6381 start

Starting Redis server...

[root@Bob210 ~]# service redis-sentinel start #启动sentinel

6.1.4模拟故障

[root@Bob210 ~]# ps aux | grep redis | grep -v grep #查看进程

root       4844  0.0  0.4  36688  7636 ?        Ssl  Aug28   1:14 /usr/local/redis-3.2.12/src/redis-server 0.0.0.0:6380        

root       5193  0.1  0.5  38736  9696 ?        Ssl  Aug28   0:58 /usr/local/redis-3.2.12/src/redis-server 0.0.0.0:6379        

root       5251  0.2  0.4  36692  7896 pts/0    Sl   Aug28   2:06 /usr/local/redis-3.2.12/src/redis-sentinel 0.0.0.0:26379 [sentinel]

root       5282  0.1  0.5  38736  9688 ?        Ssl  Aug28   0:57 /usr/local/redis-3.2.12/src/redis-server 0.0.0.0:6381

[root@Bob210 ~]#  /usr/local/redis-3.2.12/src/redis-cli

127.0.0.1:6379> info replication

# Replication

role:master

connected_slaves:2

slave0:ip=10.66.13.210,port=6380,state=online,offset=295,lag=1

slave1:ip=10.66.13.210,port=6381,state=online,offset=295,lag=0

master_repl_offset:295

repl_backlog_active:1

repl_backlog_size:1048576

repl_backlog_first_byte_offset:2

repl_backlog_histlen:294

127.0.0.1:6379> exit

[root@Bob210 ~]#  /usr/local/redis-3.2.12/src/redis-cli -p 6380

127.0.0.1:6380> info replication

# Replication

role:slave

master_host:10.66.13.210

master_port:6379

master_link_status:up

master_last_io_seconds_ago:9

master_sync_in_progress:0

slave_repl_offset:337

slave_priority:100

slave_read_only:1

connected_slaves:0

master_repl_offset:0

repl_backlog_active:0

repl_backlog_size:1048576

repl_backlog_first_byte_offset:0

repl_backlog_histlen:0

[root@Bob210 ~]# /usr/local/redis-3.2.12/src/redis-cli -p 26379 #进入sentinel

127.0.0.1:26379> info sentinel #查看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.66.13.210:6379,slaves=3,sentinels=1 #此时的master是6379

[root@Bob210 ~]# service redis-6379 stop #关掉master

[root@Bob210 ~]# /usr/local/redis-3.2.12/src/redis-cli -p 26379

127.0.0.1:26379> info sentinel #再次查看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.66.13.210:6381,slaves=3,sentinels=1 #此时的master是6381

 

说明:

即使以前的master恢复后,其master身份也不会恢复。

当master故障时它会向sentinel发请求去寻址,并根据sentinel的反馈,进行连接新的redis主节点,这一点需要使用redis专用客户端来实现。Redis客户端会根据sentinel返回的新节点IP进行连接。

6.2常用操作

6.2.1sentinel常用命令

[root@Bob210 ~]# /usr/local/redis-3.2.12/src/redis-cli -p 26379

127.0.0.1:26379> sentinel masters #查看所有监控的master信息

127.0.0.1:26379> sentinel slaves mymaster #获取master名为mymaster的所有slave信息

127.0.0.1:26379> sentinel master mymaster #获取名为mymaster的master信息

127.0.0.1:26379> sentinel get-master-addr-by-name mymaster #根据master名字获取其IP地址

127.0.0.1:26379> sentinel reset #用于重置,包括名称,清除服务器所有运行状态,故障转移、等等

127.0.0.1:26379> sentinel failover mymaster #手动向某一组redis集群发起执行故障转移

6.2.2 启动说明

虽然 Redis Sentinel 释出为一个单独的可执行文件 redis-sentinel , 但实际上它只是一个运行在特殊模式下的 Redis 服务器, 你可以在启动一个普通 Redis 服务器时通过给定 –sentinel 选项来启动 Redis Sentinel。两种方式在运行时是一样的。但是,在运行Sentinel时必须使用配置文件,因为系统将使用此文件以保存当前状态,以便重新启动时将重新加载当前状态。如果没有给出配置文件或者配置文件路径不可写,Sentinel将拒绝启动。默认情况下,Sentinel会侦听与TCP端口26379的连接,因此要使 Sentinels正常工作,必须打开服务器的端口26379,以便从其他Sentinel实例的IP地址接收连接。否则,Sentinels无法连通,也无法就该怎么做达成一致,因此永远不会执行故障转移。

方式一:

对于 redis-sentinel 程序, 可以用以下命令来启动 Sentinel 系统:

[root@Bob210 redis-3.2.12]# nohup /usr/local/redis-3.2.12/src/redis-sentinel /usr/local/redis-3.2.12/sentinel.conf &

方式二:

对于 redis-server 程序, 你可以用以下命令来启动一个运行在 Sentinel 模式下的 Redis 服务器:

[root@Bob210 redis-3.2.12]# /usr/local/redis-3.2.12/src/redis-server /usr/local/redis-3.2.12/sentinel.conf --sentinel

6.2.3配置文件

1、语法

Redis 源码中包含了一个名为 sentinel.conf 的文件, 这个文件是一个带有详细注释的 Sentinel 配置文件示例。配置文件中的语法格式为:

sentinel <选项的名字> <主服务器的名字> <选项的值>

配置文件至少包含以下内容:

[root@Bob210 redis-3.2.12]# cat /usr/local/redis-3.2.12/sentinel.conf | grep -Ev '^$|^#'

sentinel monitor mymaster 127.0.0.1 6379 2 #指定sentinel监视一个名为mymaster的集群名称(如果同时监控多组Redis集群时该名称不能相同),这个主服务器IP为127.0.0.1,端口号为6379,将这个主服务器判断为失效至少需要2个sentinel同意(才会执行自动故障迁移)。不过要注意, 无论你设置要多少个 Sentinel 同意才能判断一个服务器失效, 一个 Sentinel 都需要获得系统中多数(majority) Sentinel 的支持, 才能发起一次自动故障迁移, 并预留一个给定的配置纪元 (configuration Epoch ,一个配置纪元就是一个新主服务器配置的版本号)。

sentinel down-after-milliseconds mymaster 60000 #如果mymaster服务器在60秒没有返回sentinel发送的ping命令回复或返回一个错误,则sentinel将该服务器标记为“主观下线”。

sentinel failover-timeout mymaster 180000 #如果在180秒内未完成故障迁移,则认为迁移失败。

sentinel parallel-syncs mymaster 1 #在发生主备切换的过程中,只允许有1个slave对新master进行同步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值