redis
安装redis
yum install epel-release
yum install redis
redis desktop manager远程连接redis
https://snapcraft.io/redis-desktop-manager
redis 主从哨兵
https://www.cnblogs.com/jaycekon/p/6237562.html 哨兵集群
主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
哨兵有两个作用
通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。
当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机
然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。
故障切换(failover)的过程。假设主服务器宕机,哨兵1先检测到这个结果,系统并不会马上进行failover过程,仅仅是哨兵1主观的认为主服务器不可用,这个现象成为主观下线。当后面的哨兵也检测到主服务器不可用,并且数量达到一定值时,那么哨兵之间就会进行一次投票,投票的结果由一个哨兵发起,进行failover操作。切换成功后,就会通过发布订阅模式,让各个哨兵把自己监控的从服务器实现切换主机,这个过程称为客观下线。这样对于客户端而言,一切都是透明的
配置3个哨兵和1主2从的Redis服务器来演示这个过程
--------------------------------------------
首先配置Redis的主从服务器,修改redis.conf文件如下
# 使得Redis服务器可以跨网络访问
bind 0.0.0.0
# 设置密码
requirepass "123456"
# 指定主服务器,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
slaveof 192.168.11.128 6379
# 主服务器密码,注意:有关slaveof的配置只是配置从服务器,主服务器不需要配置
masterauth 123456
上述内容主要是配置Redis服务器,从服务器比主服务器多一个slaveof的配置和密码。
---------------------------------------------------------
配置3个哨兵,每个哨兵的配置都是一样的。在Redis安装目录下有一个sentinel.conf文件,copy一份进行修改
# 禁止保护模式
protected-mode no
# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,2代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。
sentinel monitor mymaster 192.168.11.128 6379 2
# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码
# sentinel auth-pass <master-name> <password>
sentinel auth-pass mymaster 123456
Redis的安装目录的src目录,通过下面的命令启动服务器和哨兵
# 启动Redis服务器进程
./redis-server ../redis.conf
# 启动哨兵进程
./redis-sentinel ../sentinel.conf
注意启动的顺序。首先是主机(192.168.11.128)的Redis服务进程,然后启动从机的服务进程,最后启动3个哨兵的服务进程
基于Docker搭建Redis一主两从三哨兵
redis的主从是实现redis集群和redis哨兵高可用的基础,redis的主从结构使从可以复制主上的数据,如果从与主之间网络断开,从会自动重连到主上
#拉取镜像
$ docker pull redis
获取官网配置案例
$ wget http://download.redis.io/redis-stable/redis.conf
对于master而言,配置文件修改以下几项
# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1
# 关闭保护模式
protected-mode no
# 让redis服务后台运行
daemonize yes
# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码. 只是练习配置,就不使用密码认证了)
# requirepass masterpassword
# 配置日志路径,为了便于排查问题,指定redis的日志文件目录
logfile "/var/log/redis/redis.log"
对于slave而言,配置文件修改以下几项:
# 注释这一行,表示Redis可以接受任意ip的连接
# bind 127.0.0.1
# 关闭保护模式
protected-mode no
# 让redis服务后台运行
daemonize yes
# 设定密码(可选,如果这里开启了密码要求,slave的配置里就要加这个密码)
requirepass masterpassword
# 设定主库的密码,用于认证,如果主库开启了requirepass选项这里就必须填相应的密码
masterauth <master-password>
# 设定master的IP和端口号,redis配置文件中的默认端口号是6379
# 低版本的redis这里会是slaveof,意思是一样的,因为slave是比较敏感的词汇,所以在redis后面的版本中不在使用slave的概念,取而代之的是replica
# 将35.236.172.131做为主,其余两台机器做从。ip和端口号按照机器和配置做相应修改。
replicaof 35.236.172.131 6379
# 配置日志路径,为了便于排查问题,指定redis的日志文件目录
logfile "/var/log/redis/redis.log"
启动容器
分别在主机和从机上按照上面的方法建立好配置文件,检查无误后就可以开始启动容器了。
我们在三台机器上分别将容器别名指定为redis-1, redis-2, redis-3,这样便于区分与说明,docker通过--name参数来指定容器的别名。redis-1是master上容器的别名,redis-2和redis-3是两个slave上的别名。
下面以运行redis-3容器为例说明容器的启动过程。另外两台机器上的容器redis-1和redis-2操作是相同的,只是要注意master的配置文件和slave不同。不过首先要启动主服务器,也就是redis-1容器。然后再启动redis-2和redis-3。
# 首先以后台模式运行容器
$ docker run -it --name redis-3 -v /root/redis.conf:/usr/local/etc/redis/redis.conf -d -p 6379:6379 redis /bin/bash
# 容器成功启动后,会打印一个长串的容器ID
a3952342094dfd5a56838cb6becb5faa7a34f1dbafb7e8c506e9bd7bb1c2951b
# 通过ps命令查看容器的状态,可以看到redis-3已经启动
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3952342094d redis "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 0.0.0.0:6379->6379/tcp redis-3
上面已经启动了容器,接下来进入容器里启动redis服务器
# 以交互模式进入容器redis-3
$ docker exec -it redis-3 bash
# 创建日志文件目录
$ mkdir /var/log/redis/
$ touch /var/log/redis/redis.log
# 启动redis服务器,如果没有任何输出,就说明成功了
$ redis-server /usr/local/etc/redis/redis.conf
# 在容器里启动一个redis客户端
$ redis-cli
# 执行info命令,查看服务器状态
127.0.0.1:6379> info
...
# 如果是主,这里的role的值会是master,如果是从,这里的role的值会是slave
role:slave
# 对于slave,还要查看master_link_status这个属性值。slave上这个属性值为up就说明主从复制是OK的,否者就有问题。如果从机状态不为up,首先排查主机的端口是否被限,然后查看redis日志排查原因
master_link_status:up
...
# 最后退出容器
$ exit
验证主从复制
主从搭建成功后,可以通过在master上写入一个key-value值,查看是否会同步到slave上,来验证主从同步是否能成功。
# 以交互模式进入容器redis-1中
$ docker exec -it redis-1 bash
运行一个redis-cli,向test_key写入一个值
$ redis-cli
127.0.0.1:6379> set test_key hello-world
OK
在任意slave机器上进入容器,也运行一个redis-cli,查询这个key的值。如果能查询到这个值,且与主机上的值相同,说明主从同步成功。经测试,主动同步成功。
127.0.0.1:6379> get test_key
"hello-world"
添加哨兵
获取并修改sentinel配置文件
wget http://download.redis.io/redis-stable/sentinel.conf
修改配置文件以下几项
# 让sentinel服务后台运行
daemonize yes
# 修改日志文件的路径
logfile "/var/log/redis/sentinel.log"
# 修改监控的主redis服务器
# 最后一个2表示,两台机器判定主被动下线后,就进行failover(故障转移)
sentinel monitor mymaster 35.236.172.131 6379 2
启动容器
与启动redis容器类似,启动一个别名为sentinel的容器
$ docker run -it --name sentinel -p 26379:26379 -v /root/sentinel.conf:/usr/local/etc/redis/sentinel.conf -d redis /bin/bash
运行哨兵
# 进入容器
$ docker exec -it sentinel bash
# 创建日志目录和文件
$ mkdir /var/log/redis
$ touch /var/log/redis/sentinel.log
# 启动哨兵
redis-sentinel /usr/local/etc/redis/sentinel.conf
# 查看日志,哨兵成功监听到一主和两从的机器
18:X 11 Jul 2019 13:25:55.416 # +monitor master mymaster 35.236.172.131 6379 quorum 2
18:X 11 Jul 2019 13:25:55.418 * +slave slave 35.201.200.251:6379 35.201.200.251 6379 @ mymaster 35.236.172.131 6379
18:X 11 Jul 2019 13:25:55.421 * +slave slave 34.80.172.42:6379 34.80.172.42 6379 @ mymaster 35.236.172.131 6379
```
##redis入门
### 一,缓存
缓存是为了调节速度不一致的两个或多个不同的物质的速度,在中间对速度较快的一方起到一个加
速访问速度较慢的一方的作用。cpu 速度比较快,为满足需求,增加缓存缓冲,提高cpu速率。
```bash
buffer 与 cache:
buffer:缓冲也叫写缓冲,一般用于写操作,可以将数据先写入内存在写入磁盘,buffer 一般用于写缓
冲,用于解决不同介质的速度不一致的缓冲,先将数据临时写入到里自己最近的地方,以提高写入速
度,CPU 会把数据线写到内存的磁盘缓冲区,然后就认为数据已经写入完成看,然后内核的线程在后
面的时间在写入磁盘,所以服务器突然断电会丢失内存中的部分数据。
cache:缓存也叫读缓存,一般用于读操作,CPU 读文件从内存读,如果内存没有就先从硬盘读到内存
再读到 CPU,将需要频繁读取的数据放在里自己最近的缓存区域,下次读取的时候即可快速读取
#浏览器缓存:
请求文件的最后修改时间
基于Etag
过期时间
cache-control: max-age
expires:
CDN
将服务内容分发至全网加速节点,利用全球调度系统使用户能够就近获取,有效降低访问延迟,提升服务可用性
请求过程:
提前对静态内容进行预缓存,避免大量的请求回源
1,用户向本地NDS申请域名地址,localdns 请求授权dns的解析,此时授权DNS已配置对该域名的cname为CDN加速的的域名
授权DNS返回加速域名及ip
2,用户向加速域名发送请求,该加速域名请求ip解析至CDN的智能dns,将根据用户的本地DNS返回离用户最近的cname节点,继而用户可以根据返回的ip对该节点进行请求
3,边缘节点返回请求的静态未过期资源,如果该节点资源已过期,则加速节点将对该资源进行回源
优势:
提前对静态内容进行预缓存,避免大量的请求回源,导致主站网络带宽被打满而导致数据无法更新,
CDN 可以将数据根据访问的热度不同而进行不同级别的缓存,访问量最高的资源访问 CDN边缘节点的内存,其次的放在 SSD 或者 SATA,再其次的放在云存储
调度准确-将用户调度到最近的边缘节点
性能优化 专门用于缓存响应速度快
安全相关-抵御攻击
节省带宽:由于用户请求由边缘节点响应
```

<https://github.com/ljianshu/Blog/issues/23>
### 二,redis
```
基于内存的键值非关系型数据库,提供将内存通过网络远程共享的一种服务,使用于高并发低延迟环境
```
#### 1,优点
```bash
基于内存的高性能key-value数据库
a.单线程,利用redis队列技术并将访问变为串行访问,消除了传统数据库串行控制的开销
b.redis具有快速和持久化的特征,速度快,因为数据存在内存中。
c.分布式 读写分离模式
d.支持丰富数据类型
e.支持事务,操作都是原子性,所谓原子性就是对数据的更改要么全部执行,要不全部不执行。
f.可用于缓存,消息,按key设置过期时间,过期后自动删
回收策略:
从最近最少使用的数据淘汰,挑选将要过期的数据淘汰。
volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
no-enviction(驱逐):禁止驱逐数据
redis和memcache优势:
a.memcache所有的值均是简单的字符串,redis支持更为丰富的数据类型
b.redis速度比memcached快很多
c.redis支持持久化
#redis和memcache区别:
a.存储方式 memcache存在内存中,redis存在硬盘中,保证数据持久化,重启redis服务可从备份文件中恢复数据至内存,支持快照和AOF,
b.数据类型 memcache对数据类型支持相对简单,redis有复杂的数据类型
支持更大的value数据,单个value最大支持512m
c.使用底层模型不同:底层实现方式以及客户端之间通信的应用协议不一样
d.redis最大可以达到1G而memcache只有1MB
redis 单线程, memcache多线程,单机情况memcache并发高,但redis支持分布式集群实现高并发
redis集群支持横向扩展
应用场景
Session 共享:常见于 web 集群中的 Tomcat 或者 PHP 中多 web 服务器 session 共享
消息队列:ELK 的日志缓存、部分业务的订阅发布系统
计数器:访问排行榜、商品浏览数等和次数相关的数值统计场景
缓存:数据查询、电商网站商品信息、新闻内容
微博/微信社交场合:共同好友、点赞评论等
```
#### 2,部署
```bash
# yum -y install redis
# 编译 http://download.redis.io/releases/
yum -y install gcc
make MALLOC=libc PREFIX=/usr/local/redis install
#MALLOC=libc 报错zmalloc.h:50:31: fatal error: jemalloc/jemalloc.h: No such file or directory
mkdir /usr/local/redis/etc
在源码目录中
cp redis.conf /usr/local/redis/etc/
/usr/local/redis/bin/redis-server /usr/local/redis/etc/redis.conf #前台运行
解决警告
1,backlog 参数控制的是三次握手的时候 server 端收到 client ack 确认号之后的队列值(最大容量数)
2, vm.overcommit_memory
vim /etc/sysctl.conf
net.core.somaxconn = 512
vm.overcommit_memory = 1
#0、表示内核将检查是否有足够的可用内存供应用进程使用;如果有足够的可用内存,内存申请允许;否则,内存申请失败并把错误返回给应用进程。
#1、表示内核允许分配所有的物理内存,而不管当前的内存状态如何。
#2、表示内核允许分配超过所有物理内存和交换空间总和的内存
sysctl -p
3,transparent hugepage
cat /proc/meminfo 查看transparent hugepage
echo never > /sys/kernel/mm/transparent_hugepage/enabled
cp /etc/rc.d/rc.local{,.bk}
echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled " >>/etc/rc.d/rc.local
chmod u+x /etc/rc.d/rc.local
ln -sv /usr/local/redis/bin/* /usr/bin/
groupadd -g 1000 redis && useradd -u 1000 -g 1000 redis -s /sbin/nologin
mkdir -pv /usr/local/redis/{etc,logs,data,run}
chown redis.redis -R /usr/local/redis/
redis-benchmark #redis 性能测试工具
redis-check-aof #AOF 文件检查工具
redis-check-rdb #RDB 文件检查工具
redis-cli #redis #客户端工具
redis-sentinel -> redis-server #哨兵,软连接到serve
redis-server #redis 服务端
redis-cli -h ip/hostname -p port -a passwd
```
1)配置文件
```bash
include /path/to/local.conf #引用配置文件
#bind 0.0.0.0 # 可以用空格隔开后多个监听 IP
bind 127.0.0.1
#redis3.2 之后加入的新特性,在没有设置 bind IP 和密码的时候只允许访问127.0.0.1:6379
protected-mode yes #保护模式,只允许本地连接
port 6379
tcp-backlog 511
#TCP监听的最大容纳数量,在高并发的环境下,你需要把这个值调高以避免客户端连接缓慢的问题。Linux 内核会把这个值缩小成 /proc/sys/net/core/somaxconn对应的值,要提升并发量需要修改这两个值才能达到目的
#unixsocket /tmp/redis.sock
#unixsocketperm 700
#指定redis监听的unix socket路径,默认不启用,unixsocketper指定文件的权限
timeout 0
#指定在一个 client 空闲多少秒之后关闭连接(0表示永不关闭)
tcp-keepalive 300
#单位是秒,表示将周期性的使用SO_KEEPALIVE检测客户端是否还处于健康状态,避免服务器一直阻塞,官方给出的建议值是300s,如果设置为0,则不会周期性的检测
daemonize yes #作为守护进程
supervised no #通过upstart和systemd管理Redis守护进程
#选项:
supervised no - 没有监督互动
supervised upstart - 通过将Redis置于SIGSTOP模式来启动信号
supervised systemd - signal systemd将READY = 1写入$ NOTIFY_SOCKET
supervised auto - 检测upstart或systemd方法基于 UPSTART_JOB或NOTIFY_SOCKET环境变量
pidfile /usr/local/redis/run/redis_6379.pid
#默认写到 /var/redis/run/redis_6379.pid 文件里面
loglevel notice
#日志级别
debug(记录大量日志信息,适用于开发、测试阶段)
verbose(较多日志信息)
notice(适量日志信息,使用于生产环境)
warning(仅有部分重要、关键信息才会被记录)
logfile /usr/local/redis/logs/redis_logs_6379.log
#syslog-enabled no
#想把日志记录到系统日志,就把它改成 yes,也可以可选择性的更新其他的syslog 参数以达到你的要求
# syslog-ident redis # 设置系统日志的ID
# syslog-facility local0 #指定系统日志设置,必须是 USER 或者是 LOCAL0-LOCAL7 之间的值
databases 16
#设置数据库的数目。默认的数据库是DB 0 ,可以在每个连接上使用select <dbid> 命令选择一个不同的数据库,dbid是一个介于0到databases - 1 之间的数值
always-show-logo no #日志显示log
#-----------------------------------------------
#快照机制
save 900 1
save 300 10
save 60 10000
#save "" 停用快照功能
stop-writes-on-bgsave-error yes
# 如果用户开启了RDB快照功能,那么在redis持久化数据到磁盘时如果出现失败,默认情况下,redis会停止接受所有的写请求。
这样做的好处在于可以让用户很明确的知道内存中的数据和磁盘上的数据已经存在不一致了。
如果redis不顾这种不一致,一意孤行的继续接收写请求,就可能会引起一些灾难性的后果。
如果下一次RDB持久化成功,redis会自动恢复接受写请求。
如果不在乎这种数据不一致或者有其他的手段发现和控制这种不一致的话,可以关闭这个功能,
以便在快照写入失败时,也能确保redis继续接受新的写请求
rdbcompression yes
# 对于存储到磁盘中的快照,可以设置是否进行压缩存储。
如果是的话,redis会采用LZF算法进行压缩。如果你不想消耗CPU来进行压缩的话,
可以设置为关闭此功能,但是存储在磁盘上的快照会比较大
rdbchecksum yes
# 在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,
如果希望获取到最大的性能提升,可以关闭此功能
dbfilename dump_6379.rdb
dir /usr/local/redis/data/ # 必须为目录
#------------------------------------------------------------------
#主从机制
slaveof <masterip> <masterport>
#主从复制,使用 slaveof 来让一个 redis 实例成为另一个reids 实例的副本,默认关闭
注意这个只需要在 slave 上配置
masterauth <master-password>
# 如果 master 需要密码认证,就在这里设置,默认不设置
#slave-serve-stale-data yes
当一个 slave 与 master 失去联系,或者复制正在进行的时候,
slave 可能会有两种表现:
1) 如果为 yes ,slave 仍然会应答客户端请求,但返回的数据可能是过时,
或者数据可能是空的在第一次同步的时候
2) 如果为 no ,在你执行除了 info he salveof 之外的其他命令时,
slave 都将返回一个 "SYNC with master in progress" 的错误
#slave-read-only yes
你可以配置一个 slave 实体是否接受写入操作。
通过写入操作来存储一些短暂的数据对于一个 slave 实例来说可能是有用的,
因为相对从 master 重新同步数而言,据数据写入到 slave 会更容易被删除。
但是如果客户端因为一个错误的配置写入,也可能会导致一些问题。
从 redis 2.6 版起,默认 slaves 都是只读的
repl-diskless-sync no
# 主从数据复制是否使用无硬盘复制功能。
新的从站和重连后不能继续备份的从站,需要做所谓的“完全备份”,即将一个RDB文件从主站传送到从站。
这个传送有以下两种方式:
1)硬盘备份:redis主站创建一个新的进程,用于把RDB文件写到硬盘上。过一会儿,其父进程递增地将文件传送给从站。
2)无硬盘备份:redis主站创建一个新的进程,子进程直接把RDB文件写到从站的套接字,不需要用到硬盘。
在硬盘备份的情况下,主站的子进程生成RDB文件。一旦生成,多个从站可以立即排成队列使用主站的RDB文件。
在无硬盘备份的情况下,一次RDB传送开始,新的从站到达后,需要等待现在的传送结束,才能开启新的传送。
如果使用无硬盘备份,主站会在开始传送之间等待一段时间(可配置,以秒为单位),希望等待多个子站到达后并行传送。
在硬盘低速而网络高速(高带宽)情况下,无硬盘备份更好。
repl-diskless-sync-delay 5
#当启用无硬盘备份,服务器等待一段时间后才会通过套接字向从站传送RDB文件,这个等待时间是可配置的。
这一点很重要,因为一旦传送开始,就不可能再为一个新到达的从站服务。从站则要排队等待下一次RDB传送。因此服务器等待一段
时间以期更多的从站到达。
延迟时间以秒为单位,默认为5秒。要关掉这一功能,只需将它设置为0秒,传送会立即启动。
repl-ping-slave-period 10
#从redis会周期性的向主redis发出PING包,你可以通过repl_ping_slave_period指令来控制其周期,默认是10秒。
repl-timeout 60
# 接下来的选项为以下内容设置备份的超时时间:
1)从从站的角度,同步期间的批量传输的I/O
2)从站角度认为的主站超时(数据,ping)
3)主站角度认为的从站超时(REPLCONF ACK pings)
确认这些值比定义的repl-ping-slave-period要大,否则每次主站和从站之间通信低速时都会被检测为超时。
repl-disable-tcp-nodelay no
# 同步之后是否禁用从站上的TCP_NODELAY
如果你选择yes,redis会使用较少量的TCP包和带宽向从站发送数据。但这会导致在从站增加一点数据的延时。
Linux内核默认配置情况下最多40毫秒的延时。
如果选择no,从站的数据延时不会那么多,但备份需要的带宽相对较多。
默认情况下我们将潜在因素优化,但在高负载情况下或者在主从站都跳的情况下,把它切换为yes是个好主意
repl-backlog-size 1mb
#设置备份的工作储备大小。工作储备是一个缓冲区,当从站断开一段时间的情况时,它替从站接收存储数据,
因此当从站重连时,通常不需要完全备份,只需要一个部分同步就可以,即把从站断开时错过的一部分数据接收。
工作储备越大,从站可以断开并稍后执行部分同步的断开时间就越长。
只要有一个从站连接,就会立刻分配一个工作储备。
repl-backlog-ttl 3600
#主站有一段时间没有与从站连接,对应的工作储备就会自动释放。
这个选项用于配置释放前等待的秒数,秒数从断开的那一刻开始计算,值为0表示不释放
#slave-priority 100
从站优先级是可以从redis的INFO命令输出中查到的一个整数。当主站不能正常工作时
redis sentinel使用它来选择一个从站并将它提升为主站。
低优先级的从站被认为更适合于提升,因此如果有三个从站优先级分别是10,
100,25,sentinel会选择优先级为10的从站,因为它的优先级最低。
然而优先级值为0的从站不能执行主站的角色,因此优先级为0的从站永远不会被redis sentinel提升。
默认优先级是100
#min-slaves-to-write 3
#min-slaves-max-lag 10
主站可以停止接受写请求,当与它连接的从站少于N个,滞后少于M秒,N个从站必须是在线状态。
延迟的秒数必须<=所定义的值,延迟秒数是从最后一次收到的来自从站的ping开始计算。ping通常是每秒一次。
这一选项并不保证N个备份都会接受写请求,但是会限制在指定秒数内由于从站数量不够导致的写操作丢失的情况。
如果想要至少3个从站且延迟少于10秒,如上配置即可
#slave-announce-ip 5.5.5.5
#slave-announce-port 1234
Redis master能够以不同的方式列出所连接slave的地址和端口。
例如,“INFO replication”部分提供此信息,除了其他工具之外,Redis Sentinel还使用该信息来发现slave实例。
此信息可用的另一个地方在masterser的“ROLE”命令的输出中。
通常由slave报告的列出的IP和地址,通过以下方式获得:
IP:通过检查slave与master连接使用的套接字的对等体地址自动检测地址。
端口:端口在复制握手期间由slavet通信,并且通常是slave正在使用列出连接的端口。
然而,当使用端口转发或网络地址转换(NAT)时,slave实际上可以通过(不同的IP和端口对)来到达。 slave可以使用以下两个选项,以便向master报告一组特定的IP和端口,
以便INFO和ROLE将报告这些值。
如果你需要仅覆盖端口或IP地址,则没必要使用这两个选项。
###############安全############
requirepass 123456
#rename-command CONFIG ""
命令重命名,为了安全考虑,可以将某些重要的、危险的命令重命名。
当你把某个命令重命名成空字符串的时候就等于取消了这个命令
maxclients 10000
设置客户端最大并发连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件
描述符数-32(redis server自身会使用一些),如果设置 maxclients为0
表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
maxmemory 1073741824
指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key
当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,
会把Key存放内存,Value会存放在swap区
#maxmemory-policy noeviction
当内存使用达到最大值时,redis使用的清除策略。有以下几种可以选择:
1)volatile-lru 利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
2)allkeys-lru 利用LRU算法移除任何key
3)volatile-random 移除设置过过期时间的随机key
4)allkeys-random 移除随机ke
5)volatile-ttl 移除即将过期的key(minor TTL)
6)noeviction noeviction 不移除任何key,只是返回一个写错误 ,默认选项
#maxmemory-samples 5
LRU 和 minimal TTL 算法都不是精准的算法,但是相对精确的算法(为了节省内存)
随意你可以选择样本大小进行检,redis默认选择3个样本进行检测,你可以通过maxmemory-samples进行设置样本数
#--------------APPEND ONLY MODE ------
#开启AOF
appendonly yes
默认redis使用的是rdb方式持久化,这种方式在许多应用中已经足够用了。但是redis如果中途宕机,
会导致可能有几分钟的数据丢失,根据save来策略进行持久化,Append Only File是另一种持久化方式,
可以提供更好的持久化特性。Redis会把每次写入的数据在接收后都写入appendonly.aof文件,
每次启动时Redis都会先把这个文件的数据读入内存里,先忽略RDB文件
appendfilename "appendonly_6379.aof"
appendfsync everysec | always | no
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 32mb
设置允许重写的最小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,只能用第二个命令杀
#--------------------------------
#集群配置
#cluster-enabled yes
集群开关,默认是不开启集群模式
#cluster-config-file nodes-6379.conf
集群配置文件的名称,每个节点都有一个集群相关的配置文件,持久化保存集群的信息。
这个文件并不需要手动配置,这个配置文件有Redis生成并更新,每个Redis集群节点需要一个单独的配置文件
请确保与实例运行的系统中配置文件名称不冲突
#cluster-node-timeout 15000
节点互连超时的阀值,集群节点超时毫秒数
#cluster-slave-validity-factor 10
在进行故障转移的时候,全部slave都会请求申请为master,但是有些slave可能与master断开连接一段时间了,
导致数据过于陈旧,这样的slave不应该被提升为master。该参数就是用来判断slave节点与master断线的时间是否过长。
判断方法是:
比较slave断开连接的时间和(node-timeout * slave-validity-factor) + repl-ping-slave-period
如果节点超时时间为三十秒, 并且slave-validity-factor为10,
假设默认的repl-ping-slave-period是10秒,即如果超过310秒slave将不会尝试进行故障转移
#cluster-migration-barrier 1
master的slave数量大于该值,slave才能迁移到其他孤立master上,如这个参数若被设为2,
那么只有当一个主节点拥有2 个可工作的从节点时,它的一个从节点会尝试迁移
#cluster-require-full-coverage yes
默认情况下,集群全部的slot有节点负责,集群状态才为ok,才能提供服务。
设置为no,可以在slot没有全部分配的时候提供服务。
不建议打开该配置,这样会造成分区的时候,小分区的master一直在接受写请求,而造成很长时间数据不一致
##slow log---------------------------------
#slowlog-log-slower-than 10000
slog log是用来记录redis运行中执行比较慢的命令耗时。
当命令的执行超过了指定时间,就记录在slow log中,slog log保存在内存中,所以没有IO操作。
执行时间比slowlog-log-slower-than大的请求记录到slowlog里面,单位是微秒,所以1000000就是1秒。
注意,负数时间会禁用慢查询日志,而0则会强制记录所有命令。
#slowlog-max-len 128
慢查询日志长度。当一个新的命令被写进日志的时候,最老的那个记录会被删掉,这个长度没有限制。
只要有足够的内存就行,你可以通过 SLOWLOG RESET 来释放内存
#latency-monitor-threshold 0
延迟监控功能是用来监控redis中执行比较缓慢的一些操作,用LATENCY打印redis实例在跑命令时的耗时图表。
只记录大于等于下边设置的值的操作,0的话,就是关闭监视。
默认延迟监控功能是关闭的,如果你需要打开,也可以通过CONFIG SET命令动态设置。
###-------------------- EVENT NOTIFICATION #####
#notify-keyspace-events Elg
键空间通知使得客户端可以通过订阅频道或模式,来接收那些以某种方式改动了 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类型的数据结构在编码上可以使用ziplist和hashtable。
ziplist的特点就是文件存储(以及内存存储)所需的空间较小,在内容较小时,性能和hashtable几乎一样。
因此redis对hash类型默认采取ziplist。如果hash中条目的条目个数或者value长度达到阀值,将会被重构为hashtable。
这个参数指的是ziplist中允许存储的最大条目个数,,默认为512,建议为128
#hash-max-ziplist-value 64
ziplist中允许条目value值最大字节数,默认为64,建议为1024
#list-max-ziplist-size -2
当取正值的时候,表示按照数据项个数来限定每个quicklist节点上的ziplist长度。比如,当这个参数配置成5的时候,表示每个quicklist节点的ziplist最多包含5个数据项。
当取负值的时候,表示按照占用字节数来限定每个quicklist节点上的ziplist长度。这时,它只能取-1到-5这五个值,每个值含义如下:
-5: 每个quicklist节点上的ziplist大小不能超过64 Kb。(注:1kb => 1024 bytes)
-4: 每个quicklist节点上的ziplist大小不能超过32 Kb。
-3: 每个quicklist节点上的ziplist大小不能超过16 Kb。
-2: 每个quicklist节点上的ziplist大小不能超过8 Kb。(-2是Redis给出的默认值)
-1: 每个quicklist节点上的ziplist大小不能超过4 Kb。
# list-compress-depth 0
这个参数表示一个quicklist两端不被压缩的节点个数。
注:这里的节点个数是指quicklist双向链表的节点个数,而不是指ziplist里面的数据项个数。
实际上,一个quicklist节点上的ziplist,如果被压缩,就是整体被压缩的。
参数list-compress-depth的取值含义如下:
0: 是个特殊值,表示都不压缩。这是Redis的默认值。
1: 表示quicklist两端各有1个节点不压缩,中间的节点压缩。
2: 表示quicklist两端各有2个节点不压缩,中间的节点压缩。
3: 表示quicklist两端各有3个节点不压缩,中间的节点压缩。
依此类推…
由于0是个特殊值,很容易看出quicklist的头节点和尾节点总是不被压缩的,以便于在表的两端进行快速存取。
#set-max-intset-entries 512
数据量小于等于set-max-intset-entries用intset,大于set-max-intset-entries用set
#zset-max-ziplist-entries 128
zset-max-ziplist-value 64
数据量小于等于zset-max-ziplist-entries用ziplist,大于zset-max-ziplist-entries用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,持久化
> RDB持久化: 将Reids在内存中的数据库记录定时dump到磁盘上的RDB持久化 异步方式保存,半持久化模式
>
> RDB: 内存 快照形式
>
> AOF(append only file)持久化: 将Reids的操作日志以追加的方式写入文件, 全持久化模式
>
> * 区别
>
> 1,RDB持久化是指在指定的时间间隔内将内存中的数据集快照写入磁盘,实际操作过程是fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储。
>
> 2,AOF持久化以日志的形式记录服务器所处理的每一个写、删除操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录
>
> * RDB优点
>
> 1). 一旦采用该方式,那么你的整个Redis数据库将只包含一个文件,这对于文件备份而言是非常完美的。比如,你可能打算每个小时归档一次最近24小时的数据,同时还要每天归档一次最近30天的数据。通过这样的备份策略,一旦系统出现灾难性故障,我们可以非常容易的进行恢复。
>
> 2). 对于灾难恢复而言,RDB是非常不错的选择。因为我们可以非常轻松的将一个单独的文件压缩后再转移到其它存储介质上。
>
> 3). 性能最大化。对于Redis的服务进程而言,在开始持久化时,它唯一需要做的只是fork出子进程,之后再由子进程完成这些持久化的工作,这样就可以极大的避免服务进程执行IO操作了。
>
> 4). 相比于AOF机制,如果数据集很大,RDB的启动效率会更高。
>
> RDB又存在哪些劣势呢?
>
> 1). 如果你想保证数据的高可用性,即最大限度的避免数据丢失,那么RDB将不是一个很好的选择。因为系统一旦在定时持久化之前出现宕机现象,此前没有来得及写入磁盘的数据都将丢失。
>
> 2). 由于RDB是通过fork子进程来协助完成数据持久化工作的,因此,如果当数据集较大时,可能会导致整个服务器停止服务几百毫秒,甚至是1秒钟
>
> * AOF
>
> 1). 该机制可以带来更高的数据安全性,即数据持久性。Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事实上,每秒同步也是异步完成的,其效率也是非常高的,所差的是一旦系统出现宕机现象,那么这一秒钟之内修改的数据将会丢失。而每修改同步,我们可以将其视为同步持久化,即每次发生的数据变化都会被立即记录到磁盘中。可以预见,这种方式在效率上是最低的。至于无同步,无需多言,我想大家都能正确的理解它。
>
> 2). 由于该机制对日志文件的写入操作采用的是append模式,因此在写入过程中即使出现宕机现象,也不会破坏日志文件中已经存在的内容。然而如果我们本次操作只是写入了一半数据就出现了系统崩溃问题,不用担心,在Redis下一次启动之前,我们可以通过redis-check-aof工具来帮助我们解决数据一致性的问题。
>
> 3). 如果日志过大,Redis可以自动启用rewrite机制。即Redis以append模式不断的将修改数据写入到老的磁盘文件中,同时Redis还会创建一个新的文件用于记录此期间有哪些修改命令被执行。因此在进行rewrite切换时可以更好的保证数据安全性。
>
> 4). AOF包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。事实上,我们也可以通过该文件完成数据的重建。
>
> AOF的劣势有哪些呢?
>
> 1). 对于相同数量的数据集而言,AOF文件通常要大于RDB文件。RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
>
> 2). 根据同步策略的不同,AOF在运行效率上往往会慢于RDB。总之,每秒同步策略的效率是比较高的,同步禁用策略的效率和RDB一样高效。
>
> 二者选择的标准,就是看系统是愿意牺牲一些性能,换取更高的缓存一致性(aof),还是愿意写操作频繁的时候,不启用备份来换取更高的性能,待手动运行save的时候,再做备份(rdb)。rdb这个就更有些 eventually consistent的意思了。
>
> 注意事项:
>
> 1,在dump rdb过程中,aof如果停止同步,会不会丢失?
>
> 不会,所有操做都在内存的队列里,dump完成后统一操做
>
> 2,aof 重写 :内存中的数据逆化成命令写入到AOF 日志里,解决日志过大问题
>
> 3, 优先使用aof 恢复数据
>
> 4,可以同时使用RDB 和AOF
>
> 5,恢复时RDB比较快,该数据为内存映射,直接载入内存,而aof为命令,需要逐条执行
```BASH
# RDB 可并行配置rdb 与aof
save 900 1 #在900秒(15分钟)之后,如果至少有1个key发生变化,则dump内存快照。
save 300 10 #在300秒(5分钟)之后,如果至少有10个key发生变化,则dump内存快照。
save 60 10000 #在60秒(1分钟)之后,如果至少有10000个key发生变化,则dump内存快照。
#AOF
appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,该策略为AOF的缺省策略。
appendfsync no #从不同步。高效但是数据不会被持久化。
```
#### 4,脚本安装
```bash
#! /bin/bash
#
yum -y install gcc
cd /usr/local/src
wget http://download.redis.io/releases/redis-4.0.14.tar.gz
tar xf redis-4.0.14.tar.gz && cd redis-4.0.14
make MALLOC=libc PREFIX=/usr/local/redis install
#解决报警
cat >>/etc/sysctl.conf<<END
net.core.somaxconn = 512
vm.overcommit_memory = 1
END
sysctl -p
echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo "echo never > /sys/kernel/mm/transparent_hugepage/enabled" >> /etc/rc.d/rc.local
chmod u+x /etc/rc.d/rc.local
#配置文件
ln -sv /usr/local/redis/bin/* /usr/bin/
useradd redis -s /sbin/nologin -M
mkdir -pv /usr/local/redis/{etc,logs,data,run}
chown redis.redis -R /usr/local/redis/
#常用配置
#cp /usr/local/src/redis-4.0.14/redis.conf /usr/local/redis/etc/
cat >> /usr/local/redis/etc/redis.conf <<EOF
#bind 0.0.0.0 # 可以用空格隔开后多个监听 IP
bind 127.0.0.1
#redis3.2 之后加入的新特性,在没有设置 bind IP 和密码的时候只允许访问127.0.0.1:6379
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /usr/local/redis/run/redis_6379.pid
loglevel notice
logfile /usr/local/redis/logs/redis_logs_6379.log
databases 16
always-show-logo no
#-----------------------------------------------
#快照机制
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes #快照错误是否允许写入
rdbcompression yes
rdbchecksum yes
dbfilename dump_6379.rdb
dir /usr/local/redis/data/
#------------------------------------------------------------------
#主从机制
#slaveof 192.168.36.75 6379
#masterauth redhat
slave-serve-stale-data yes
slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 30
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 1mb
repl-backlog-ttl 3600
slave-priority 100
requirepass redhat
#rename-command
maxclients 10000
maxmemory 1073741824
#--------------------
#开启AOF
appendonly yes
#Append Only File
appendfilename "appendonly_6379.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 32mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
#--------------------------------
#集群配置
#cluster-enabled yes
#cluster-config-file nodes-6379.conf
#cluster-node-timeout 15000
#cluster-replica-validity-factor 10
#cluster-migration-barrier 1
#cluster-require-full-coverage no
#---------------------------------
#slow log
#Slow log
#slowlog-log-slower-than 10000
#slowlog-max-len 128
EOF
cat >> /usr/lib/systemd/system/redis.service <<END
[Unit]
Description=Redis persistent key-value database
After=network.target
After=network-online.target
Wants=network-online.target
[Service]
#ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStart=/usr/bin/redis-server /usr/local/redis/etc/redis.conf --supervised systemd
ExecReload=/bin/kill -s HUP \$MAINPID
ExecStop=/bin/kill -s QUIT \$MAINPID
Type=notify
User=root
Group=root
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
[Install]
WantedBy=multi-user.target
END
```
#### 5,普通用户启动
```bash
cp -r /usr/local/redis/* . #复制程序到普通用户目录
cat redis/etc/redis.conf #更改配置,data pid 等
#bind 0.0.0.0 # 可以用空格隔开后多个监听 IP
bind 127.0.0.1
#redis3.2 之后加入的新特性,在没有设置 bind IP 和密码的时候只允许访问127.0.0.1:6379
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile /home/yon/redis/run/redis_6379.pid
loglevel notice
logfile /home/yon/redis/logs/redis_logs_6379.log
databases 16
always-show-logo no
#-----------------------------------------------
#快照机制
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error no
rdbcompression yes
rdbchecksum yes
dbfilename dump_6379.rdb
dir /home/yon/redis/data/
#------------------------------------------------------------------
#主从机制
#slaveof ip port
#slave-serve-stale-data yes
#slave-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 30
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 1mb
repl-backlog-ttl 3600
slave-priority 100
requirepass 123456
#rename-command
maxclients 10000
maxmemory 1073741824
#--------------------
#开启AOF
appendonly yes
#Append Only File
appendfilename "appendonly_6379.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 32mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
#--------------------------------
#集群配置
#cluster-enabled yes
#cluster-config-file nodes-6379.conf
#cluster-node-timeout 15000
#cluster-replica-validity-factor 10
#cluster-migration-barrier 1
#cluster-require-full-coverage no
#---------------------------------
#slow log
#Slow log
#slowlog-log-slower-than 10000
#slowlog-max-len 128
#启动
/home/yon/redis/bin/redis-server /home/yon/redis/etc/redis.conf
修改端口启动不同的进程
```
#### 6,数据类型
```bash
# string 字符串
set key1 value1
get key1
del key1
MSET key1 value1 key2 value2 #批量设置
MGET key1 key2
append key1 xxxx #追加数据
set num 10
incr num #数值递增
decr num #递减
strlen key1 #string 长度
# 列表
列表是一个双向可读写的管道,其头部是左侧尾部是右侧,一个列表最多可以包含 2^32-1 个元素即4294967295 个元素
LPUSH list1 j1 j2 j3 j4
Rpush list1 j5
LPOP list1 j4
Rpop list1 j5
LLEN list1
#集合 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据
SADD set1 v1
SADD set2 v2 v4
type set2
SMEMBERS set2
差集:已属于 A 而不属于 B 的元素称为 A 与 B 的差(集)
SDIFF set1 set2
交集:已属于 A 且属于 B 的元素称为 A 与 B 的交(集)
SINTER set1 set2
并集:已属于 A 或属于 B 的元素为称为 A 与 B 的并(集)
SUNION set1 set2
#sorted set 有序集合
string 类型元素的集合,且不允许重复的成员,每个元素都会关联一个 double(双精度浮点型)类型的分数,通过分数来为集合中的成员进行从小到大的排序,序集合的成员是唯一的,但分数(score)却可以重复,集合是通过哈希表实现的.添加,删除,查找的复杂度都是 O(1), 集合中最大的成员数为 2^32 - 1 (4294967295, 每个集合可存储 40 多亿个成员)
ZADD zset1 1 v1
ZADD zset2 2 v2
type
ZADD paihangbang 10 key1 20 key2 30 key3
ZREVRANGE paihangbang 0 -1 withscores
ZCARD zset1 #集合长度
> ZADD zset2 1 v1 2 v2 4 v3 5 v5
ZRANGE zset1 1 3 #基于索引返回值
ZRANK zset1 v2 #返回某个数值的索引
#hash
是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,Redis 中每个 hash 可以存储 232 - 1 键值对
HSET hset1 name tom age 18
HGET hset1 name
HDEL hset1 age
HSET hset1 name tom age 19
HKEYS hset1
#消息队列
生产者消费者模式和发布者订阅者模式
1,
在生产者消费者(Producer/Consumer)模式下,上层应用接收到的外部请求后开始处理其当前步骤的操作,在执行完成后将已经完成的操作发送至指定的频道(channel)当中,并由其下层的应用监听该频道并继续下一步的操作,如果其处理完成后没有下一步的操作就直接返回数据给外部请求,如果还有下一步的操作就再将任务发布到另外一个频道,由另外一个消费者继续监听和处理。
模式:
生产者消费者模式下,多个消费者同时监听一个队里,但是一个消息只能被最先抢到消息的消费者消费,即消息任务是一次性读取和处理,此模式在分布式业务架构中非常常用,比较常用的软件还有RabbitMQ、Kafka、RocketMQ、ActiveMQ 等
队列:
队列当中的 消息由不同的生产者写入也会有不同的消费者取出进行消费处理,但是一个消息一定是只能被取出一次也就是被消费一次。
2,生产者发布信息
LPUSH channel1 msg1 #管带左侧写入
LPUSH channel1 msg2
LPUSH channel1 msg3
LRANGE channel1 0 -1 #查看队列所有信息
RPOP channel1 #管道右侧消费
LRANGE channel1 0 -1 #查看
发布者订阅
在发布者订阅者模式下,发布者将消息发布到指定的 channel 里面,凡是监听该 channel 的消费者都会收到同样的一份消息,这种模式类似于是收音机模式,即凡是收听某个频道的听众都会收到主持人发布的相同的消息内容。此模式常用语群聊天、群通知、群公告等场景
Subscriber:订阅者
Publisher:发布者
Channel:频道
```
#### 7,主从复制
```bash
#主从版本要一致
slave 要开启持久化并设置和 master 同样的连接密码,因为后期 slave 会有提升为 master 的可
能,Slave 端切换 master 同步后会丢失之前的所有数据,断开同步不会丢失数据
解决单点故障
#配置文件
master :监听在 ip 或 0.0.0.0
slave :
slaveof 192.168.36.75 6379
masterauth redhat
#salve-serve-stale-data yes
#salve-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 30
repl-ping-slave-period 10
repl-timeout 60
repl-disable-tcp-nodelay no
repl-backlog-size 1mb
repl-backlog-ttl 3600
#replica-priority 100
requirepass redhat
#rename-command
maxclients 10000
maxmemory 1073741824
```
#### 8,主从同步过程
```bash
支持全量同步(第一次)和增量同步(后续):过程
全量复制发生在slave初始化阶段
#1,slave 在执行slaveof ip port 后,连接master ,发出SYNC命令
#2,master 接受命令后,fork一个子进程并在后台执行bgsave,将内存的数据生成RDB文件发送到到slave
在执行bgsave之后,master 新写入的操做写入缓冲区
#3,slave 接受RDB文件并载入到内存,master将缓冲区的写操做同步到SLAVE,slave载入缓存区命令
部分同步
主从分别记录数据的偏移量
#4,slave 发送slave_repl_offset位置请求同步
#5,master根据slave的偏移量和自身的对比,如果不一致,则将slave要求的偏移位置之后的数据发送过去
#一些命令
命令配置 : slaveof ip port
CONFIG SET masterauth 123456
CONFIG SET requirepass 123456
info
select 1 #数据库1
keys *
BGSAVE fork一个save 子进程,在执行save过程中,不影响主进程,客户端可以正常连接redis,子进程执行完毕save后,通知主进程,子进程退出
SAVE 阻塞主进程,客户端无法连接redis,save结束后主进程开始工作,客户端可以连接
DBSIZE 当前库keys数量
FLUSHDB 清空当前库数据
FLUSHALL 清空所有库数据
#主从优化
2.8版之前没有提供增量复制的功能,当网络闪断或者 slave Redis 重启之后会导致主从之间的全量同步,2.8之后新加增量复制功能
repl-diskless-sync yes #yes 为支持 disk,master 将 RDB 文件先保存到磁盘在发送给 slave,no 为 maste直接将 RDB 文件发送给 slave,默认即为使用 no,Master RDB 文件不需要与磁盘交互
repl-diskless-sync-delay 5 #Master 准备好 RDB 文件后等等待传输时间
repl-ping-slave-period 10 #slave 端向 server 端发送 ping 的时间区间设置,默认为 10 秒
repl-timeout 60 #设置超时时间
repl-disable-tcp-nodelay no #是否启用 TCP_NODELAY,如设置成 yes,则 redis 会合并小的 TCP 包从而节省带宽,但会增加同步延迟(40ms),造成 master 与 slave 数据不一致,假如设置成 no,则 redis master会立即发送同步数据,没有延迟,前者关注性能,后者关注一致性
repl-backlog-size 1mb #master 的写入数据缓冲区,用于记录自上一次同步后到下一次同步过程中间的写入命令,计算公式:b repl-backlog-size = 允许从节点最大中断时长 * 主实例 offset 每秒写入量,比如 master 每秒最大写入 64mb,最大允许 60 秒,那么就要设置为 64mb*60 秒=3840mb(3.8G)=
repl-backlog-ttl 3600 #如果一段时间后没有 slave 连接到 master,则 backlog size 的内存将会被释放。如果值为 0 则表示永远不释放这部份内存。
slave-priority 100 #slave 端的优先级设置,值是一个整数,数字越小表示优先级越高。当 master 故障时将会按照优先级来选择 slave 端进行恢复,如果值设置为 0,则表示该 slave 永远不会被选择。
#min-slaves-to-write 0 #
#min-slaves-max-lag 10 #设置当一个 master 端的可用 slave 少于 N 个,延迟时间大于 M 秒时,不接收写操作
Master 的重启会导致 master_replid 发生变化,slave 之前的 master_replid 就和 master 不一致从而会引发所有 slave 的全量同步
```
> 旧版本复制
>
> 同步(sync)和命令传播(command propagate)两个操作
>
> - 同步操作用于将从服务器的数据库状态更新至主服务器当前所处的数据库状态;
> - 命令传播操作则用于在主服务器的数据库状态被修改,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态
>
> #### 同步
>
> 当客户端向从服务器发送SLAVEOF命令,要求从服务器复制主服务器时,从服务器首先需要执行同步操作,也即是,将从服务器的数据库状态更新至主服务器当前所处的数据库状态。
>
> 从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤:
>
> 1. 从服务器向主服务器发送SYNC命令;
> 2. 收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令;
> 3. 当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器**执行BGSAVE命令时的数据库状态**。
> 4. 主服务器将记录在缓冲区里面的所有写命令发送给从服务器,**从服务器执行这些写命令**,将自己的数据库状态更新至主服务器数据库当前所处的状态
>
> ##### 命令传播
>
> 在执行完同步操作之后,主从服务器之间数据库状态已经相同了。但这个状态并非一成不变,如果主服务器执行了写操作,那么主服务器的数据库状态就会修改,并导致主从服务器状态不再一致。
>
> 所以为了让主从服务器再次回到一致状态,主服务器需要对从服务器执行命令传播操作:主服务器会将自己执行的写命令,也即是造成主从服务器不一致的那条写命令,发送给从服务器执行,当从服务器执行了相同的写命令之后,主从服务器将再次回到一致状态
>
> #### 缺陷
>
> 从服务器对主服务器的复制可以分为以下两种情况:
>
> - 初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制的主服务器和上一次复制的主服务器不同;
>
> - 断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动重连接重新连上了主服务器,并继续复制主服务器
>
> 断线后重新连接,从服务器发送sync命令,主将所有数据RDB给从,相当于重新全量复制更新
>
> #### 新版
>
> 为了解决旧版复制功能在处理断线重复制情况时的低效问题,Redis从2.8版本开始,使用**PSYNC**命令代替SYNC命令来执行复制时的同步操作
>
> PSYNC命令具有完整重同步(full resynchronization)和部分重同步(partial resynchronization)两种模式
>
> * 完整重同步用于处理初次复制情况:完整重同步的执行步骤和SYNC命令的执行步骤基本一样,它们都是通过让主服务器创建并发送RDB文件,以及向从服务器发送保存在缓冲区里面的写命令来进行同步
> * 部分重同步则用于处理断线后重复制情况:当从服务器在断线后重新连接主服务器时,**如果条件允许,主服务器可以将主从服务器连接断开期间执行的写命令发送给从服务器,从服务器只要接收并执行这些写命令,就可以将数据库更新至主服务器当前所处的状态**
>
> 部分重同步功能由以下三个部分构成:
>
> - 主服务器的**复制偏移量**(replication offset)和从服务器的复制偏移量;
> - **主服务器的复制积压缓冲区(replication backlog)**;
> - **服务器的运行ID**(run ID)。
>
> 复制偏移量
>
> 执行复制的双方——主服务器和从服务器会分别维护一个复制偏移量:
>
> - 主服务器每次向从服务器传播N个字节的数据时,就将自己的复制偏移量的值加上N;
> - 从服务器每次收到主服务器传播来的N个字节的数据时,就将自己的复制偏移量的值加上N
>
> 通过对比主从服务器的复制偏移量,程序可以很容易地知道主从服务器是否处于一致状态:
>
> - 如果主从服务器处于一致状态,那么主从服务器两者的偏移量总是相同的;
> - 相反,如果主从服务器两者的偏移量并不相同,那么说明主从服务器并未处于一致状态
>
> 从服务器断线连接后,向主报告自身的偏移量,,主执行部分重同步,**复制积压缓冲区**
>
> 复制积压缓冲区是由主服务器维护的一个固定长度(fixed-size)先进先出(FIFO)队列,默认大小为1MB
>
> 和普通先进先出队列随着元素的增加和减少而动态调整长度不同,固定长度先进先出队列的长度是固定的,当入队元素的数量大于队列长度时,最先入队的元素会被弹出,而新元素会被放入队列
>
> 主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,并且复制积压缓冲区会为队列中的每个字节记录相应的复制偏移量
>
> 当从服务器重新连上主服务器时,从服务器会通过PSYNC命令将自己的复制偏移量offset发送给主服务器,主服务器会根据这个复制偏移量来决定对从服务器执行何种同步操作
>
> - 如果offset偏移量之后的数据(也即是偏移量offset+1开始的数据)仍然存在于复制积压缓冲区里面,那么主服务器将对从服务器执行部分重同步操作;
> - 相反,如果offset偏移量之后的数据已经不存在于复制积压缓冲区,那么主服务器将对从服务器执行完整重同步操作
>
> <https://www.cnblogs.com/lukexwang/p/4711977.html>
#### 9,常见问题
```
master 密码不正确
redis 版本不一致
开启安全模式无法远程连接 protected mod
master 监听地址与端口,防火墙,iptables selinux
```
#### 10,导入导出
```bash
#redis-dump
gem install redis-dump
导出
redis-dump -u :password@172.20.0.1:6379 > 172.20.0.1.json
导入
cat 172.20.0.1.json | redis-load -u :password@172.20.0.2:6379
#AOF 导入
源实例生成 aof 文件
1,清空目标实例的全部数据
redis-cli -h 172.20.0.2 -a password flushall
2,在源实例生成aof 文件
redis-cli -h 172.20.0.1 -a password config set appendonly yes
3,目标实例导入(appendonly.aof 在本目录下
redis-cli -h 172.20.0.2 -a password --pipe < appendonly.aof
4,源实例关闭aof
redis-cli -h 172.20.0.1 -a password config set appendonly no
#rdb 迁移
1,BGSAVE 生成 rdb 文件
2,转移至目标实例
获取目标实例的数据目录
CONFIG GET dir
清空其他rdb文件,将源rdb 文件移动至该实例数据目录
重启redis-server 服务
#源实例db0迁移至目标实例db1 未测试
cat redis_mv.sh
#!/bin/bash
redis-cli -h 172.20.0.1 -p 6379 -a password -n 0 keys "*" | while read key
do
redis-cli -h 172.20.0.1 -p 6379 -a password -n 0 --raw dump $key | perl -pe 'chomp if eof' | redis-cli -h 172.20.0.2 -p 6379 -a password -n 1 -x restore $key 0
echo "migrate key $key"
done
```
### 三 ,集群
主从架构无法实现 master 与slave 角色的自动切换,无法横向扩展服务的并行写入性能。集群实现方式:客户端分片,代理分片,Redis Cluster
#### 1,Sentinel(哨兵)
>**redis 主从模式下,主节点故障后不能提供服务,需人工干预,调整从节点晋升为主节点**
>
>一主多从,主挂了选举从晋升为主,
>
>从2.8之后稳定的redis sentinel 解决了redis 人工干预的问题
>
><https://www.cnblogs.com/biglittleant/p/7770960.html>
```bash
一个分布式系统为redis提供高可用性.sentinel执行:
#监控(Monitoring): Sentinel 会不断地定期检查你的主服务器和从服务器是否运作正常。
#提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知
#自动故障迁移(Automaticfailover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作, 它会将失效主服务器的其中 一个从服务器升级为新的主服务器, 并让失效主服务器的其他从服务器改为复制新的主服务器; 当客 户端试图连接失效的主服务器时, 集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主 服务器代替失效服务器
#高可用
Redis Sentinel是一个分布式架构,其中包含N个Sentinel节点和Redis数 据节点,每个Sentinel节点会对数据节点和其他Sentinel节点进行监控, 当它返现节点不可达时,会对节点做下线标识,如果被标识的是主节 点,它还会和其他Sentinel及诶单进行“协商”,当大多数节点都认为主 节点不可达时,会选举出一个Sentinel节点来完成自动故障转移的工作, 同时会将这个变化实时通知给redis的客户端,整个过程是自动的不需 要人工干预,有效的解决了redis的高可用问题
Redis Sentinel包含多个Sentinel节点,这样做带来两个好处:
对于节点的故障判断是由多个节点共同完成,这样可以有效的防止误判断
多个Sentinel节点出现个别节点不可用,也不会影响客户端的访问
```
```bash
#仲裁
当一个master被sentinel集群监控时,需要为它指定一个参数,这个参数指定了当需要判决master为不可用,并且进行failover时,所需要的sentinel数量,本文中我们暂时称这个参数为票数
当failover主备切换真正被触发后,failover并不会马上进行,还需要sentinel中的大多数sentinel授权后才可以进行failover。
当ODOWN时,failover被触发。failover一旦被触发,尝试去进行failover的sentinel会去获得“大多数”sentinel的授权(如果票数比大多数还要大的时候,则询问更多的sentinel)
集群中有5个sentinel,票数被设置为2,当2个sentinel认为一个master已经不可用了以后,将会触发failover,但是,进行failover的那个sentinel必须先获得至少3个sentinel的授权才可以实行failover。
如果票数被设置为5,要达到ODOWN状态,必须所有5个sentinel都主观认为master为不可用,要进行failover,那么得获得所有5个sentinel的授权
```
```bash
#配置版本号
当一个sentinel被授权后,它将会获得宕掉的master的一份最新配置版本号,当failover执行结束以后,这个版本号将会被用于最新的配置。因为大多数sentinel都已经知道该版本号已经被要执行failover的sentinel拿走了,所以其他的sentinel都不能再去使用这个版本号。这意味着,每次failover都会附带有一个独一无二的版本号
sentinel集群都遵守一个规则:如果sentinel A推荐sentinel B去执行failover,B会等待一段时间后,自行再次去对同一个master执行failover,这个等待的时间是通过failover-timeout配置项去配置的。从这个规则可以看出,sentinel集群中的sentinel不会再同一时刻并发去failover同一个master,第一个进行failover的sentinel如果失败了,另外一个将会在一定时间内进行重新进行failover,以此类推。
redis sentinel保证了活跃性:如果大多数sentinel能够互相通信,最终将会有一个被授权去进行failover.
redis sentinel也保证了安全性:每个试图去failover同一个master的sentinel都会得到一个独一无二的版本号
```
```bash
#配置传播
一旦一个sentinel成功地对一个master进行了failover,它将会把关于master的最新配置通过广播形式通知其它sentinel,其它的sentinel则更新对应master的配置
一个faiover要想被成功实行,sentinel必须能够向选为master的slave发送SLAVE OF NO ONE命令,然后能够通过INFO命令看到新master的配置信息
当将一个slave选举为master并发送SLAVE OF NO ONE后,即使其它的slave还没针对新master重新配置自己,failover也被认为是成功了的,然后所有sentinels将会发布新的配置信息
每个sentinel使用发布/订阅的方式持续地传播master的配置版本信息,配置传播的发布/订阅管道是:__sentinel__:hello
因为每一个配置都有一个版本号,所以以版本号最大的那个为标准
```
```
主观下线(Subjectively Down, 简称 SDOWN)指的是单个 Sentinel 实例对服务器做出的下线判断。
客观下线(Objectively Down, 简称 ODOWN)指的是多个 Sentinel 实例在对同一个服务器做出 SDOWN 判断, 并且通过 SENTINEL is-master-down-by-addr 命令互相交流之后, 得出的服务器下线判断
entinel的角度来看,如果发送了PING心跳后,在master-down-after-milliseconds时间内没有收到合法的回复,就达到了SDOWN的条件
当sentinel发送PING后,以下回复之一都被认为是合法的:
PING replied with +PONG.
PING replied with -LOADING error.
PING replied with -MASTERDOWN error.
其它任何回复(或者根本没有回复)都是不合法的
从SDOWN切换到ODOWN不需要任何一致性算法,只需要一个gossip协议:如果一个sentinel收到了足够多的sentinel发来消息告诉它某个master已经down掉了,SDOWN状态就会变成ODOWN状态。如果之后master可用了,这个状态就会相应地被清理掉。
正如之前已经解释过了,真正进行failover需要一个授权的过程,但是所有的failover都开始于一个ODOWN状态。
ODOWN状态只适用于master,对于不是master的redis节点sentinel之间不需要任何协商,slaves和sentinel不会有ODOWN状态
```
```bash
#故障转移操作由以下步骤组成
1,发现主服务器已经进入客观下线状态。
2,对我们的当前纪元进行自增(详情请参考 Raft leader election ), 并尝试在这个纪元中当选。
3,如果当选失败, 那么在设定的故障迁移超时时间的两倍之后, 重新尝试当选。 如果当选成功, 那么执行以下步骤。
4,选出一个从服务器,并将它升级为主服务器。
5,向被选中的从服务器发送 SLAVEOF NO ONE 命令,让它转变为主服务器。
6,通过发布与订阅功能, 将更新后的配置传播给所有其他 Sentinel , 其他 Sentinel 对它们自己的配置进行更新。
7,向已下线主服务器的从服务器发送 SLAVEOF 命令, 让它们去复制新的主服务器。
8,当所有从服务器都已经开始复制新的主服务器时, 领头 Sentinel 终止这次故障迁移操作
每当一个 Redis 实例被重新配置(reconfigured) —— 无论是被设置成主服务器、从服务器、又或者被设置成其他主服务器的从服务器 —— Sentinel 都会向被重新配置的实例发送一个 CONFIG REWRITE 命令, 从而确保这些配置会持久化在硬盘里。
Sentinel 使用以下规则来选择新的主服务器
1,在失效主服务器属下的从服务器当中, 那些被标记为主观下线、已断线、或者最后一次回复 PING 命令的时间大于五秒钟的从服务器都会被淘汰。
2,在失效主服务器属下的从服务器当中, 那些与失效主服务器连接断开的时长超过 down-after 选项指定的时长十倍的从服务器都会被淘汰。
3,在经历了以上两轮淘汰之后剩下来的从服务器中, 我们选出复制偏移量(replication offset)最大的那个从服务器作为新的主服务器; 如果复制偏移量不可用, 或者从服务器的复制偏移量相同, 那么带有最小运行 ID 的那个从服务器成为新的主服务器
```
#### 2,部署
获取
```
$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make
$ src/redis-server
$ src/redis-cli
redis> set foo bar
OK
redis> get foo
"bar"
```
```bash
redis
192.168.36.75 master
192.168.36.76 slave
192.168.36.77 slave
sentinel
# 192.168.36.75 配置
bind 0.0.0.0
port 26379
dir "/usr/local/redis/sentinel"
pidfile "/usr/local/redis/sentinel/sentinel.pid"
logfile "/usr/local/redis/sentinel/sentinel_26379.log"
daemonize yes
sentinel auth-pass mymaster redhat
sentinel monitor mymaster 192.168.36.77 6379 2
sentinel deny-scripts-reconfig yes
sentinel down-after-milliseconds redis-master 5000
sentinel failover-timeout redis-master 900000
sentinel parallel-syncs redis-master 2
#192.168.36.76
bind 192.168.36.76
port 26379
dir "/usr/local/redis/sentinel"
pidfile "/usr/local/redis/sentinel/sentinel.pid"
logfile "/usr/local/redis/sentinel/sentinel_26379.log"
daemonize yes
sentinel auth-pass mymaster redhat
sentinel monitor mymaster 192.168.36.77 6379 2
sentinel deny-scripts-reconfig yes
# 192.168.36.77
bind 0.0.0.0
port 26379
dir "/usr/local/redis/sentinel"
pidfile "/usr/local/redis/sentinel/sentinel.pid"
logfile "/usr/local/redis/sentinel/sentinel_26379.log"
daemonize yes
sentinel auth-pass mymaster redhat
sentinel monitor mymaster 192.168.36.77 6379 2
sentinel deny-scripts-reconfig yes
#启动顺序
Master---->Slave----->Sentinel
/usr/local/redis/bin/redis-sentinel /usr/local/redis/etc/sentinel.conf
#注意
sentinel 节点不要部署在同一台机器
至少不是三个且奇数个的 sentinel 节点,增加选举的准确性因为领导者选举需要至少一半加1个节点
sentinel节点集合可以只监控一个主节点,也可以监控多个主节点, 尽量使用一套sentinel监控一个主节点。
sentinel的数据节点与普通的 redis 数据节点没有区别
客户端初始化连接的是 Sentinel节点集合,不再是具体的 redis 节 点,但是Sentinel 是配置中心不是代理。
#主故障后,sentinel 通过选举重新推举出新的master,原来的主恢复后需要重新使用config set masterauth xxxx 进行连接到新主上
https://www.cnblogs.com/biglittleant/p/7770960.html
```
#### 3,redis-cluster

> 架构特点:
>
> 1、所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽。
> 2、节点的fail是通过集群中超过半数的节点检测失效时才生效。
> 3、客户端与redis节点直连,不需要中间proxy层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。
> 4、redis-cluster把所有的物理节点映射到[0-16383]slot上(不一定是平均分配),cluster 负责维护node<->slot<->value。
>
> 5、Redis集群预分好16384个桶,当需要在 Redis 集群中放置一个 key-value 时,根据 CRC16(key) mod 16384的值,决定将一个key放到哪个桶中
>
> 节点分配:
>
> 采用哈希槽 (hash slot)的方式来分配16384个slot ,三个节点分别承担的slot区间:
>
> 节点A覆盖0-5460;
> 节点B覆盖5461-10922;
> 节点C覆盖10923-16383.
>
> 获取数据:
>
> 如果存入一个值,按照redis cluster哈希槽的[算法](http://lib.csdn.net/base/datastructure): CRC16('key')384 = 6782。 那么就会把这个key 的存储分配到 B 上了。同样,当我连接(A,B,C)任何一个节点想获取'key'这个key时,也会这样的算法,然后内部跳转到B节点上获取数据
>
> 新增节点:
>
> 新增一个节点D,redis cluster的这种做法是从各个节点的前面各拿取一部分slot到D上
>
> 节点A覆盖1365-5460
> 节点B覆盖6827-10922
> 节点C覆盖12288-16383
> 节点D覆盖0-1364,5461-6826,10923-12287
>
>
> 同样删除一个节点也是类似,移动完成后就可以删除这个节点
>保证高可用,使用主从模式,一个主节点对应一个或多个从节点,主节点挂掉后,选取从节点升级为主,保证集群可用
配置
```bash
#配置先决条件
1,redis node 采用相同的硬件配置,相同的密码,
2,节点开启必须的参数
cluster-enabled yes
cluster-config-file nodes-6380.conf #配置文件自动创建和维护
3,redis 服务器没有任何数据
4,先启动单机为redis 且没有任何key value
#redis 版本为3,4 ,集群需要下载ruby redis
redis-server -v
Redis server v=4.0.14
#使用ruby-2.3.8
yum -y install zlib-devel openssl*
wget https://cache.ruby-lang.org/pub/ruby/2.3/ruby-2.3.8.tar.gz
cd ruby-2.3.8
./configure
make && make install
#####重要,需要安装ruby redis 插件
gem install redis
cp /usr/local/src/redis-4.0.14/src/redis-trib.rb /usr/bin/ #通过脚本安装
redis-trib.rb 执行测试
######最重要,配置文件配置requirepass 后,需要处理
find / -name client.rb
vim /usr/local/lib/ruby/gems/2.3.0/gems/redis-4.1.2/lib/redis/client.rb
DEFAULTS = {
:url => lambda { ENV["REDIS_URL"] },
:scheme => "redis",
:host => "127.0.0.1",
:port => 6379,
:path => nil,
:timeout => 5.0,
:password => "redhat" #需要改变,不然出现 cant connect to node
##如果不配置需要在配置文件中注释掉requirepass
#所有redis 的配置文件
cat >> etc/redis.conf <<EOF
bind 192.168.36.73
protected-mode yes
port 6379
daemonize yes
dir /usr/local/redis/data/
loglevel notice
logfile redis_logs_6379.log
masterauth redhat
requirepass redhat
appendonly yes
cluster-enabled yes
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000
EOF
#启动
systemctl start redis && \
redis-server /usr/local/redis/cluster/redis-6380.conf
ps -ef | grep redis |awk '{print "kill -9 " $2}' | bash
redis集群启动后如果退出,服务不能再重启,需要清除data数据 ,节点配置,只剩下配置文件
cat >> redis-6380.conf <<EOF
bind 192.168.36.73
protected-mode yes
port 6380
daemonize yes
dir /usr/local/redis/cluster/
loglevel notice
logfile redis_logs_6379.log
masterauth redhat
requirepass redhat
appendonly yes
cluster-enabled yes
cluster-config-file nodes-6380.conf
cluster-node-timeout 15000
EOF
#在/usr/local/redis/cluster/ 生成的配置文件:
appendonly.aof dump.rdb nodes-6380.conf
```
集群显示:
```bash
#redis-trib.rb create --replicas 1 192.168.36.74:6379 192.168.36.75:6379 192.168.36.73:6379 192.168.36.73:6380 192.168.36.74:6380 192.168.36.75:6380
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
192.168.36.74:6379
192.168.36.75:6379
192.168.36.73:6379
Adding replica 192.168.36.75:6380 to 192.168.36.74:6379
Adding replica 192.168.36.73:6380 to 192.168.36.75:6379
Adding replica 192.168.36.74:6380 to 192.168.36.73:6379
M: 41f81639a1e2c1a3162ad9dedaedcd96fec07d96 192.168.36.74:6379
slots:0-5460 (5461 slots) master
M: 3d82a329a8806f78f1cca0fcb79805fb8e4681d4 192.168.36.75:6379
slots:5461-10922 (5462 slots) master
M: eaaf2fa8f24d95c9fe7126419cbfefad961599ad 192.168.36.73:6379
slots:10923-16383 (5461 slots) master
S: 11e441ae2f9d9bf4764145437501ff699a3558aa 192.168.36.73:6380
replicates 3d82a329a8806f78f1cca0fcb79805fb8e4681d4
S: 2d9160640b2eae6d4157830f7302aa6fbc2b103a 192.168.36.74:6380
replicates eaaf2fa8f24d95c9fe7126419cbfefad961599ad
S: 78d61d812a14653c27da73bf600bfd2ba15ebce8 192.168.36.75:6380
replicates 41f81639a1e2c1a3162ad9dedaedcd96fec07d96
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join.........
>>> Performing Cluster Check (using node 192.168.36.74:6379)
M: 41f81639a1e2c1a3162ad9dedaedcd96fec07d96 192.168.36.74:6379
slots:0-5460 (5461 slots) master
1 additional replica(s)
M: 3d82a329a8806f78f1cca0fcb79805fb8e4681d4 192.168.36.75:6379
slots:5461-10922 (5462 slots) master
1 additional replica(s)
S: 11e441ae2f9d9bf4764145437501ff699a3558aa 192.168.36.73:6380
slots: (0 slots) slave
replicates 3d82a329a8806f78f1cca0fcb79805fb8e4681d4
S: 2d9160640b2eae6d4157830f7302aa6fbc2b103a 192.168.36.74:6380
slots: (0 slots) slave
replicates eaaf2fa8f24d95c9fe7126419cbfefad961599ad
M: eaaf2fa8f24d95c9fe7126419cbfefad961599ad 192.168.36.73:6379
slots:10923-16383 (5461 slots) master
1 additional replica(s)
S: 78d61d812a14653c27da73bf600bfd2ba15ebce8 192.168.36.75:6380
slots: (0 slots) slave
replicates 41f81639a1e2c1a3162ad9dedaedcd96fec07d96
#检查状态
redis-cli -h ip -p6379 -aredhat
info replication #主从状态
cluster info #集群状态
cluster nodes #集群nodes 对应关系
#集群监控状态
redis-trib.rb check ip:port
```
#### 4,集群节点增删
```bash
#动态添加节点
redis-trib.rb add-node 新节点:port 已存在的集群节点:port
redis-trib.rb add-node 192.168.36.72:6379 192.168.36.73:6379 #注意192.168.36.73:6379 为已经存在的
新加节点无slave ,无插槽,再新加节点
redis-trib.rb add-node 192.168.36.72:6380 192.168.36.73:6379 #新添加后也是master
redis-cli -h 192.168.36.72 -a redhat
cluster nodes #查看192.168.36.72:6379
为192.168.36.72:6379 手动添加 slave
获取192.168.36.72:6379的id 在72:6380 上执行
cluster replicate 05324472b24fdbadde9adc7f6cd6bcf28cddafb9
CLUSTER nodes
确认是否为slave
在控制节点查看
redis-trib.rb info 192.168.36.73:6379
#分配插槽
槽位已分配完,从原来已分配槽位的节点分配槽位
16384/4 个master
redis-trib.rb reshard 192.168.36.73:6379
分配多少个槽位 4096
分配到哪个节点 192.168.36.72:6379(新添加master节点的id)
从哪个节点分配 all yes
如果节点有数据,分配槽位会失败
将数据删除互后报错,找到报错节点修复
redis-trib.rb fix 192.168.36.72:6379
继续分:
redis-trib.rb reshard 192.168.36.73:6379
查看已经分配的槽位,4096减去已分配的,继续分,填写id 源 all yes
有数据热横向扩容(停服
```
```bash
#动态删除节点
保证被删除的节点没有数据
redis-trib.rb reshard 192.168.36.72:6379
选择迁移的个数
选择接收源
选择迁移源
done
#查看槽位是否为空
redis-trib.rb info 192.168.36.72:6379
#删除集群节点
redis-trib.rb del-node ip:port node_id
redis-trib.rb del-node 192.168.36.72:6379 05324472b24fdbadde9adc7f6cd6
redis-trib.rb check 912.168.36.73:6379
```
#### 重新分配slave
```bash
#查询信息只能在控制主机上执行,在其他主机需要
find / -name client.rb
修改 vim client.rb 添加密码
redis-trib.rb info 192.168.36.74:6379
master 不能与slave 在同一个服务器上
CLUSTER nodes
#在从节点找到节点id 执行
cluster replicate node_id
直至不再交叉被分为止,(应该是无数据操做)
```
#### master 宕机
```bash
systemctl stop redis 后该slave 升级为 新的master ,可读写
原来的master重新激活后变为新主的从
cluster nodes 查看
```
#### 导入数据
```bash
导入的数据不能有与目前cluster 中数据重复 key
使用集群数据导入命令
导入之前关闭各redis服务器的密码
CONFIG SET requirepass "" #在master上操做
导入命令不同
redis 5
#redis-cli --cluster import 集群服务器 IP:PORT --cluster-from 外部 Redis node-IP:PORT --cluster-copy --cluster-replace
redis4 :
redis-trib.rb import --from 来源ip:port 接收IP:port --copy或--replace方式
```
redis-trib.rb
```bash
redis.trib.rb 为redis 源程序提供,还需要ruby环境(注意版本),rubygem redis
1. create:创建集群
2. check:检查集群
3. info:查看集群信息
4. fix:修复集群
5. reshard:在线迁移slot
6. rebalance:平衡集群节点slot数量
7. add-node:添加新节点
8. del-node:删除节点
9. set-timeout:设置节点的超时时间
10. call:在集群所有节点上执行命令
11. import:将外部redis数据导入集群
#创建集群
redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384
--replicas参数指定集群中每个主节点配备几个从节点,这里设置为1。
主从节点的选择及槽的分配,其算法如下:
1> 把节点按照host分类,这样保证master节点能分配到更多的主机中。
2> 遍历host列表,从每个host列表中弹出一个节点,放入interleaved数组。直到所有的节点都弹出为止。
3> 将interleaved数组中前master个数量的节点保存到masters数组中。
4> 计算每个master节点负责的slot数量,16384除以master数量取整,这里记为N。
5> 遍历masters数组,每个master分配N个slot,最后一个master,分配剩下的slot。
6> 接下来为master分配slave,分配算法会尽量保证master和slave节点不在同一台主机上。对于分配完指定slave数量的节点,还有多余的节点,也会为这些节点寻找master。分配算法会遍历两次masters数组。
7> 第一次遍历master数组,在余下的节点列表找到replicas数量个slave。每个slave为第一个和master节点host不一样的节点,如果没有不一样的节点,则直接取出余下列表的第一个节点。
8> 第二次遍历是分配节点数除以replicas不为整数而多出的一部分节点。
#检查集群状态
redis-trib.rb check ip:port 指定任意一个节点即可
#集群信息
redis-trib.rb info ip:port
#修复集群
目前1fix命令能修复两种异常:
1. 节点中存在处于迁移中(importing或migrating状态)的slot。
2. 节点中存在未分配的slot。
其它异常不能通过fix命令修复
#在线迁移
redis-trib.rb reshard ip:6379 指定任意一个节点
从指定节点迁出
redis-trib.rb reshard host:port --from <arg> --to <arg> --slots <arg> --yes --timeout <arg> --pipeline <arg>
host:port:必传参数,集群内任意节点地址,用来获取整个集群信息。
--from:源节点id,如果有多个源节点,使用逗号分隔,如果是all,则源节点为集群内出目标节点外的其它所有主节点。
--to:目标节点id,只能填写一个。
--slots:需要迁移槽的总数量。
--yes:迁移无需用户手动确认。
--timeout:控制每次migrate操作的超时时间,默认为60000毫秒。
--pipeline:控制每次批量迁移键的数量,默认为10
redis-trib.rb reshard --from a8b3d0f9b12d63dab3b7337d602245d96dd55844 --to f413fb7e6460308b17cdb71442798e1341b56cbc --slots 10923 --yes --pipeline 20 127.0.0.1:6383
#平衡节点
rebalance host:port
--weight <arg>
--auto-weights
--use-empty-masters
--timeout <arg>
--simulate
--pipeline <arg>
--threshold <arg>
--weight <arg>:节点的权重,格式为node_id=weight,如果需要为多个节点分配权重的话,需要添加多个--weight <arg>参数,即--weight b31e3a2e=5 --weight 60b8e3a1=5,node_id可为节点名称的前缀,只要保证前缀位数能唯一区分该节点即可。没有传递–weight的节点的权重默认为1。
--auto-weights:自动将每个节点的权重默认为1。如果--weight和--auto-weights同时指定,则--auto-weights会覆盖前者。
--threshold <arg>:只有节点需要迁移的slot阈值超过threshold,才会执行rebalance操作。
--use-empty-masters:默认没有分配slot节点的master是不参与rebalance的。如果要让其参与rebalance,需添加该参数。
--timeout <arg>:设置migrate命令的超时时间。
--simulate:设置该参数,只会提示用户会迁移哪些slots,而不会执行真正的迁移操作。
--pipeline <arg>:定义cluster getkeysinslot命令一次取出的key数量,不传的话使用默认值为10。
redis-trib.rb rebalance --weight a8b3d0f9b12d63dab3b7337d602245d96dd55844=3 --weight f413fb7e6460308b17cdb71442798e1341b56cbc=2 --use-empty-masters 127.0.0.1:6379
#删除节点
redis-trib.rb del-node host:port node_id
在删除节点之前,其对应的槽必须为空,所以,在进行节点删除动作之前,必须使用redis-trib.rb reshard将其迁移出去
#添加新节点
redis-trib add-node new_host:new_port existing_host:existing_port --slave --master-id <arg>
new_host:new_port:待添加的节点,必须确保其为空或不在其它集群中
在集群所有节点上执行命令
redis-trib.rb call host:port command arg arg .. arg
redis-trib.rb call 127.0.0.1:6379 set hello world
#将外部redis 数据导入集群
redis-trib.rb import --from 127.0.0.1:6378 127.0.0.1:6379
1> 通过load_cluster_info_from_node方法加载集群信息,check_cluster方法检查集群是否健康。
2> 连接外部redis节点,如果外部节点开启了cluster_enabled,则提示错误([ERR] The source node should not be a cluster node.)
3> 通过scan命令遍历外部节点,一次获取1000条数据。
4> 遍历这些key,计算出key对应的slot。
5> 执行migrate命令,源节点是外部节点,目的节点是集群slot对应的节点,如果设置了--copy参数,则传递copy参数,其会保留源节点的key,如果设置了--replace,则传递replace参数。如果目标节点中存在同名key,其值会被覆盖。两个参数可同时指定。
6> 不停执行scan命令,直到遍历完所有key。
7> 迁移完成
```
#### 其他
codis
```
分布式解决方案,Codis Proxy codis-proxy 无状态,
不负责记录是否在哪保存,数据在 zookeeper 记录,即 codis proxy 向 zookeeper 查询 key 的记录位置,proxy 将请求转发到一个组进行处理,一个组里面有一个 master 和一个或者多个 slave 组成,默认有1024 个槽位,redis cluster 默认有 16384 个槽位,其把不同的槽位的内容放在不同的 group
```
memcached - repcached
```bash
#基于 repcached 的双主数据同步
yum -y install gcc
yum -y install libevent*
# wget https://sourceforge.net/projects/repcached/files/repcached/2.2.1-1.2.8/memcached1.2.8-repcached-2.2.1.tar.gz
tar xvf memcached-1.2.8-repcached-2.2.1.tar.gz
cd memcached-1.2.8-repcached-2.2.1
./configure --prefix=/usr/local/repcached --enable-replication
vim +55 memcached.c
改为
55 /* FreeBSD 4.x doesn't have IOV_MAX exposed. */
56 #ifndef IOV_MAX
57 # define IOV_MAX 1024
58 #endif
make && make install
启动
/usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 192.168.36.75 -X 16000
/usr/local/repcached/bin/memcached -d -m 2048 -p 11211 -u root -c 2048 -x 192.168.36.74 -X 16000
```
### 四,redis面试
```bash
内存通过网络进行共享的基于键值对存储的NOSQL数据库,支持基本数据类型,值为字符串
Redis是单进程单线程的,利用队列技术将并发访问变为串行访问,消除了传统数据库串行控制的开销
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
双向链接实现消息队列
对存入的Key-Value设置expire时间, Redis的主要缺点是数据库容量受到物理内存的限制,不能用作海量数据的高性能读写
适合的场景主要局限在较小数据量的高性能操作和运算上
#Redis的全称 Remote Dictionary Server
#Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
一个事务从开始到执行会经历以下三个阶段:
开始事务。
命令入队。
执行事务
#分布式锁
setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放
#如果在setnx之后执行expire之前进程意外crash或者要重启维护,那会怎样
set指令有非常复杂的参数,可以同时把setnx和expire合成一条指令来用的
#假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
使用keys指令可以扫出指定模式的key列表。
#如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题
redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复,
以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。
三个特点:
数据可以保存在硬盘中,重启服务,数据可从硬盘加载值内存
#持久化
数据集中每N秒钟有超过M次更新,就将数据写入磁盘,或手工调用命令SAVE或BGSAVE
BGSAVE 快照镜像全量持久化,aof做增量持久化,因为bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。在redis实例重启时,优先使用aof来恢复内存的状态,如果没有aof日志,就会使用rdb文件来恢复
aof文件过大恢复时间过长怎么办?你告诉面试官,Redis会定期做aof重写,压缩aof文件日志大小,Redis4.0之后有了混合持久化的功能,将bgsave的全量和aof的增量做了融合处理,这样既保证了恢复的效率又兼顾了数据的安全性
取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据
#Pipeline有什么好处,为什么要用pipeline
可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目
#同步机制
Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
#Redis集群, 原理是什么
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
#MySQL里有2000w数据,redis中只存20w的数据,如何保证redis中的数据都是热点数据
redis内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略 ,数据淘汰策略
noeviction:返回错误当内存限制达到并且客户端尝试执行会让更多内存被使用的命令
allkeys-lru: 尝试回收最少使用的键(LRU),使得新添加的数据有空间存放。
volatile-lru: 尝试回收最少使用的键(LRU),但仅限于在过期集合的键,使得新添加的数据有空间存放。
allkeys-random: 回收随机的键使得新添加的数据有空间存放。
volatile-random: 回收随机的键使得新添加的数据有空间存放,但仅限于在过期集合的键。
volatile-ttl: 回收在过期集合的键,并且优先回收存活时间(TTL)较短的键,使得新添加的数据有空间存放。
#字符串类型的值能存储最大容量是多少 512M
Redis需要把所有数据放到内存中
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘
#Redis需要把所有数据放到内存中
Redis为了达到最快的读写速度将数据都读到内存中,并通过异步的方式将数据写入磁盘。redis具有快速和数据持久化的特征。如果不将数据放在内存中,磁盘I/O速度为严重影响redis的性能
#集群方案
1,codis 支持在节点数量改变情况下,旧节点数据可恢复到新hash节点。
2,在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key 进行hash计算,然后去对应的redis实例操作数据。 这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的替代算法方案,数据震荡后的自动脚本恢复,实例的监控
#集群方案什么情况下会导致整个集群不可用
有A,B,C三个节点的集群,在没有复制模型的情况下,如果节点B失败了,那么整个集群就会以为缺少5501-11000这个范围的槽而不可用
#reis 适用场景
会话缓存
全页缓存 消息队列 排行榜计算器 发布订阅
#Redis哈希槽的概念
Redis集群没有使用一致性hash,而是引入了哈希槽的概念,Redis集群有16384个哈希槽,每个key通过CRC16校验后对16384取模来决定放置哪个槽,集群的每个节点负责一部分hash槽
#Redis集群的主从复制模型
为了使在部分节点失败或者大部分节点无法通信的情况下集群仍然可用,所以集群使用了主从复制模型,每个节点都会有N-1个复制品,按需为每个主节点配备slave 节点
#Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作
#Redis集群之间是如何复制,异步复制
Redis集群最大节点个数 16384
#集群选择数据库 Redis集群目前无法做数据库选择,默认在0数据库
#测试Redis的连通性 ping pong
# Redis中的管道
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应。这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复 管道(pipelining
# Redis事务
事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断,事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行
#Redis事务相关的命令 MULTI、EXEC、DISCARD、WATCH
#redis key 过期时间永久有效
EXPIRE和PERSIST命令
#Redis如何做内存优化 使用散列表(hashes),散列表(是说散列表里面存储的数少)使用的内存非常小,所以你应该尽可能的将你的数据模型抽象到一个散列表里面
```
##主从配置文件
复制两个redis配置文件(启动两个redis,只需要一份redis程序,两个不同的redis配置文件即可)
```bash
mkdir redis-master-slave
cp path/to/redis/conf/redis.conf path/to/redis-master-slave master.conf
cp path/to/redis/conf/redis.conf path/to/redis-master-slave slave.conf
```
修改配置
```bash
## master.conf
port 6379
## master.conf
port 6380
slaveof 127.0.0.1 6379
```
分别启动两个redis
```bash
redis-server path/to/redis-master-slave/master.conf
redis-server path/to/redis-master-slave/slave.conf
```
##哨兵
3个redis(1主2从),1个哨兵
```bash
mkdir redis-sentinel
cd redis-sentinel
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis01.conf
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis02.conf
cp redis/path/conf/redis.conf path/to/redis-sentinel/redis03.conf
touch sentinel.conf
```
将 redis01设置为master,将redis02,redis03设置为slave
```bash
vim redis01.conf
port 63791
vim redis02.conf
port 63792
slaveof 127.0.0.1 63791
vim redis03.conf
port 63793
slaveof 127.0.0.1 63791
vim sentinel.conf
daemonize yes
port 26379
sentinel monitor mymaster 127.0.0.1 63793 1
# 下面解释含义
mymaster 为主节点名字,可以随便取,后面程序里边连接的时候要用到
127.0.0.1 63793 为主节点的 ip,port
1 后面的数字 1 表示选举主节点的时候,投票数。1表示有一个sentinel同意即可升级为master
```
启动哨兵,使用jedis连接哨兵操作redis
```bash
redis-server path/to/redis-sentinel/redis01.conf
redis-server path/to/redis-sentinel/redis02.conf
redis-server path/to/redis-sentinel/redis03.conf
redis-server path/to/redis-sentinel/sentinel.conf --sentinel
```
##redis-cluster
https://blog.csdn.net/qq_42815754/article/details/82832335
https://blog.csdn.net/qq_42815754/article/details/82912130
```bash
##编译http://download.redis.io/releases/
wget http://download.redis.io/releases/redis-3.0.0.tar.gz
#解压
yum install gcc-c++
make
make install PREFIX=/usr/local/redis #目录
## ls /usr/local/redis/bin
##默认启动
./redis-server
下载redis压缩包,然后解压压缩文件;
进入到解压缩后的redis文件目录(此时可以看到Makefile文件),编译redis源文件;
把编译好的redis源文件安装到/usr/local/redis目录下,如果/local目录下没有redis目录,会自动新建redis目录;
进入/usr/local/redis/bin目录,直接./redis-server启动redis(此时为前端启动redis);
将redis启动方式改为后端启动,具体做法:把解压缩的redis文件下的redis.conf文件复制到/usr/local/redis/bin目录下,然后修改该redis.conf文件->daemonize:no 改为daemonize:yse;
在/bin目录下通过./redis-server redis.conf启动redis(此时为后台启动)。
综上redis单机版安装启动完成。
3.1 在usr/local目录下新建redis-cluster目录,用于存放集群节点
3.2 把redis目录下的bin目录下的所有文件复制到/usr/local/redis-cluster/redis01
cp -r redis/bin/ redis-cluster/redis01
3.3 删除redis01目录下的快照文件dump.rdb,并且修改该目录下的redis.cnf文件,具体修改两处地方:一是端口号修改为7001,二是开启集群创建模式,打开注释即可。分别如下图所示:
删除dump.rdb文件
修改端口
将cluster-enabled yes 的注释打开
3.4 将redis-cluster/redis01文件复制5份到redis-cluster目录下(redis02-redis06),创建6个redis实例,模拟Redis集群的6个节点。然后将其余5个文件下的redis.conf里面的端口号分别修改为7002-7006。分别如下图所示:
创建redis02-06目录
3.5启动
cd redis01
./redis-server redis.conf
cd ..
cd redis02
./redis-server redis.conf
cd ..
cd redis03
./redis-server redis.conf
cd ..
cd redis04
./redis-server redis.conf
cd ..
cd redis05
./redis-server redis.conf
cd ..
cd redis06
./redis-server redis.conf
cd ..
执行start-all.sh脚本,启动6个redis节点
##gem install redis -v 3.0.0
```
ip变更造成的redis集群不可用的解决及数据备份和恢复
https://blog.csdn.net/u011535541/article/details/78470862
redis主从:是备份关系, 我们操作主库,数据也会同步到从库。 如果主库机器坏了,从库可以上。就好比你 D盘的片丢了,但是你移动硬盘里边备份有。
redis哨兵:哨兵保证的是HA,保证特殊情况故障自动切换,哨兵盯着你的“redis主从集群”,如果主库死了,它会告诉你新的老大是谁。
redis集群:集群保证的是高并发,因为多了一些兄弟帮忙一起扛。同时集群会导致数据的分散,整个redis集群会分成一堆数据槽,即不同的key会放到不不同的槽中。
主从保证了数据备份,哨兵保证了HA 即故障时切换,集群保证了高并发性。

浙公网安备 33010602011771号