Redis学习笔记
参考官方文档
一、common item
1.1 redis-cli:
-
常用选项
redis-cli -h <hostname> -p <port> -a <passwd> -u <uri>
redis-cli -u redis://passwd@hostname:port/0
-
常见集群操作命令:
- config get // 不用重启情况下的配置更新和查看
- config set
- flushall 清库
- select 2 // 切换db,一般一个redis实例可以有多个db,这个db可以通过配置调整,通过select进行切换, 默认连接db0
- dbsize 查看db大小
- ping pong // 实例可用性
- connect hostname port // 切换当前连接实例
- debug restart // 重启本实例, redis-cli默认会一直重试至连接上未知,如果连不上,会显示当前error和断连接状态, 一般这个命令不允许执行, 连接上之后,redis-cli会默认连接至上次连接的db
- 使用multi可以连续执行多个命令,如
multi 开始记录 ping ping ... set a b get a exec 开始执行
- clear 清屏
- info
- info replication 可以查看当前实例的信息(主?从?)
- 特殊操作模式
redis-cli -p 5555 --stat -i <interval>
查看当前数据情况,负载情况, 默认15秒一次
redis-cli --bigkeys 查看大key
redis-cli --scan | head -10 使用scan参数,而非KEYS , 避免redis server阻塞
redis-cli --scan --pattern '-11*' 查找符合匹配规则的key
redis-cli Pub/Sub 模式暂时不看[TODO]
reids-cli monitor //打印当前实例收到的所有命令, 什么时候,来自哪个套接字的哪个命令
redis-cli --latency //延迟监控 --latency-history, --latency-dist
redis-cli --rdb /tmp/dump.rdb // 远程备份某个redis实例的数据至本地
redis-cli --slave // 让当前cli模拟一个slave的状态, 获取master给slave发送的同步replication stream
当redis被用作cache服务器的时候,通过maxmemory来设定一个上限值,配合LRU算法进行内存驱逐,暂时不看详情参考[TODO]
1.2 configration:
-
redis配置生效方式
- 命令行 redis-server -p 4444 --slaveof hostname port
- 通过配置文件指定(生产推荐) redis-server [/path/to/redis.conf]
- 通过交互更改 CONFIG GET CONFIG SET
- 官方配置参考5.0版本
- 我司配置样例cluster模式参考最后附录1
1.3 replication
- 机制:
- master会将所有的命令stream发送给replica, 包括cli write, keys expire, 和其他操作
- 当master replica断链接重连后,replica会尝试获取在断链期间丢失的数据,部分同步
- 当部分同步行不通时,replica会请求一个全同步,触发master的snapshot,然后将其发送个replica,然后再去重写数据
- 同步方式
- 默认async, sync可选,sync暂时不了解
- 其他
- 当master没有配置持久化的时候,不能打开其自动重启功能,一般重启功能都在k8s中定义,因为一旦master没有持久化,而且重启了,会导致旗下所有slave同步它的空数据
- redis replication原理,replication中的每个节点,不管是master还是replica,都有一个基于数据集产生的一个replicationID, 类似这样
ReplicationID, offset
, 每当有master将自己的replicationstream发送给slvae时,这个offset就会增加相应的字节数 - 当slave链接到master的时候,会使用PSYNC命令,将之前他链接的masterReplicationID,连同他当前的处理进度(他自己的offsetS), 然后master就会将相比于offsetS,新增的replicationStream发送给slave
- 到底哪个slave在failover的时候能够当选?——不能配置某个必须当选,但是可以配置某些绝对不能当选
- replication的创建
- 加入master: 5.0 使用replicaof, 其他版本使用slaveof
- 配置只读 slave-read-only yes
- master添加密码
masterauth <master-password>
,requirepass <your passwd>
- a -> b -> c集群,c仍然会和a的dataset保持一致
- replication如何处理keys过期
- 不能总是依赖master往replica去同步时钟来完成
- 具体实现方式如下
- replicas不会让keys过期,他们只等待master让keys过期,如果master的某个key过期了,那就把DEL命令传输给replicas
- 其他待学习
- [TODO]docker中的replication网络NAT[TODO]
-
[TODO]当master restart之后,可能其他replica已经成为master了, 那么之前没传完的数据该如何部分重传?
1.4 persistency
当redis实例启动的时候,如果appendonly no, 则无论是否打开rdb,都会默认加载指定目录下的dbfilename,如果appendonly yes, 则优先加载appendfilename, 如果appendfilename不存在,则不会加载dbfilename
- RDB
默认redis会以快照方式,将redisDB保存在dump.rdb中
触发方式有三种- save
- bgsave
save <sec> <num of keyschange>
save 60 10 每六十秒统计一次,如果有超过10个key发生变更,则触发一次快照- 如果使用save '',rdb会被关闭或者
redis-cli config set save ''
- AOF
fsync的方式,最高提供命令级别的fsync策略,支持(有新命令,秒级别,从不)的fsync策略
默认关闭
appendonly yes // 打开aof
appendfilename "appendonly.aof"
appendfsync everysec(default)|always|no // fsync频率
AOF提供”BGREWRITEAOF“命令,重新生成一个新的AOF,其中包含更少的命令来创建当前数据集
redis-check-aof –fix 提供aof文件corrupt情况下的文件修复
aof工作原理[TODO] -
aof和RDB
BGSAVE和BGREWRITEAOF命令不能同时执行
aof过大时,支持aof文件的重写,用于达到复制相同复制集的情况下的,减小aof文件大小 - diff
当一个单实例模型重启时
rdb:DB loaded from disk: xxxx seconds
aof: DB loaded from append only file: xxx seconds
rdb+aof: DB loaded from append only file: 0.010 seconds- 当rdb+aof时,会产生两个文件,一个aof文件,一个rdb文件
- 重启时,当rdb文件丢失,redis启动之后,通过aof文件,仍然能够恢复服务
- 重启时,当aof文件丢失,redis启动之后,通过rdb文件,不能正常启动(这种情况如何修复?这个时候,需要将aof配置关闭,以单rdb方式打开,此时redis处于rdb状态,需要重新使用config set appendonly yes打开aof才可以回归正常)
二、sentinel知识总结
为redis instance的一种HA方案,同时提供monitor,notification(API触发接口),auto failover 和 configration provider
2.1 有关sentinel集群
- sentinel的启动必须指定配置文件,配置文件只需指定监控master即可
- sentinel集群的每个实力必须互通,默认26379端口
- sentinel集群至少sentinel * 3
- (异步复制原因)sentinel + redis不保证failover期间的write操作是被保留的,【TODO】这里要再继续学习
- sentinel, docker, NAT, port mapping , 使用docker的端口映射,将会打断sentinel的自动发现功能,也会影响master的对应的slave列表功能,【TODO】稍后查看相关sentinel with docker
- sentinel是依靠master的INFO信息来进行replica发现
- 有关sentinel master mymaster 这个信息里面的flags, 正常情况下值为master,也有可能出现s_down或者o_down, 分别表示对应Subjectively Down(主观)和Objectively Down(客观), 比如debug sleep 30和直接ctrl+c终止redis-server进程,都会触发S_down, O_down暂时还没去了解
2.2 sentinel启动配置
-
sentinel monitor <master-group-name> <ip> <port> <quorum>
quorum解释:- 集群中至少有
<quorum>
个sentinel认为master不可用,failover才会被授权执行。 - 这个failover又是谁来启动呢?又是被谁授权呢?
如果: sentinel集群有5个sentinel: 且都配置sentinel monitor mymaster ip port 2
那么: 有两个(至少)sentinel说master不可用了,这2个中的其中一个sentinel就会发起failover初始化,然后,集群中的5个sentinel如果至少有3个sentinel认为该master不可用了,那么这个failover就会被授权执行 - 这么多sentinel是怎样标记那个故障master的状态,并完成判断的呢?
答:sentinel集群的每个sentinel都是有互相交流的,当集群中的sentinel发现一个master不可用(通过down-after-milliseconds断定)时,这个sentinel就会对这个master标记一个sdown状态,当第二个sentinel也发现同样情况时,也对master打一个sdown状态,当这个sdown超过2的时候,sentinel集群就会failover初始化,并获取所有sentinel对master的评价进行投票,当这个集群中总sdown的个数超过3时,sentinel集群中的所有sentinel都会将这个master标记为odown(客观下线),然后由第一个收到odown通知的sentinel去执行failover。 - 结论:
sentinel集群中的个数不能少于 quorum个,否则,此sentinel集群已经失去failover的功能,而且能不能?正常对外提供服务
- 集群中至少有
-
sentinel <option_name> <master_name> <option_value>
optionname如下:- down-after-milliseconds
<ms>
//超过这个时间,sentinel将认为实例不可达 - parallel-syncs
<nums>
//出现故障,failover完成后,最多有多少个replica去从master同步 - failover-timeout
<ms>
// failover进程最长执行时间,超过时间将认定failover失败【TODO】这时集群的状态是ERROR吗?
- down-after-milliseconds
-
样例
bind
127.0.0.1 protected-mode no syslog-enabled no syslog-ident "redis-sentinel" syslog-facility local0 port 26379 dir /home/redis/data/conf maxclients 50000 sentinel monitor redis_sentinel_zhk022702 6379 2 sentinel down-after-milliseconds redis_sentinel_zhk022702 20000 sentinel parallel-syncs redis_sentinel_zhk022702 2
2.3 安全机制:
-
redis实例本身的认证,
- for replica的
masterauth <master-password>
, - for client的
requirepass <yourRequirePasswd>
- 如果redis集群配置了上述两个配置,那么sentinel实例也必须配置
sentinel auth-pass <master-group-name> <pass>
如sentinel auth-pass mymaster <yourRequirePasswd>
- for replica的
- sentinel认证
- sentinel认证配置——sentinel在5.0版本之后也支持client到sentinel自己的认证,只需要在sentinel配置
requirepass <yourSentinelPasswd>
, 这个指令将直接限制client --> sentinel的访问和sentinels集群间的认证
- sentinel认证配置——sentinel在5.0版本之后也支持client到sentinel自己的认证,只需要在sentinel配置
2.4 sentinel集群模型及其搭建步骤
# redis-server
# redis-server --port 6380
# redis-server --port 6381
# cat conf/sentinel*.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 3000
sentinel failover-timeout mymaster 40000
sentinel parallel-syncs mymaster 2
port 26380
...同上
port 26381
...同上
# redis-sentinel conf/sentinel1.conf
# redis-sentinel conf/sentinel2.conf
# redis-sentinel conf/sentinel3.conf
# cat conf/sentinel*.conf
port 26379
sentinel monitor mymaster 127.0.0.1 6379 2 #如果发生failover,本配置文件会被更改
sentinel down-after-milliseconds mymaster 3000
sentinel failover-timeout mymaster 40000
sentinel parallel-syncs mymaster 2
# Generated by CONFIG REWRITE
dir "/data"
sentinel config-epoch mymaster 0 ## 表示这两个自动添加的内容不知道意思
sentinel leader-epoch mymaster 0
sentinel known-sentinel mymaster 127.0.0.1 26380 119690834a6925435edeeccf6a98df1152d342a5
sentinel known-sentinel mymaster 127.0.0.1 26381 c75d2e225a353d23881d63e5a383cc620f0c1d44
sentinel current-epoch 0
port 26380
...与上类似
port 26381
...与上类似
2.5 常用sentinel相关命令
redis-cli -p 26379
localhost:26379> sentinel master mymaster # 用于显示 本sentinel所监控的master信息
SENTINEL slave mymaster # 查master的slaves
SENTINEL sentinels mymaster #查sentinel的其他sentinels
SENTINEL get-master-addr-by-name mymaster #获取master的
SENTINEL failover
SENTINEL reset
SENTINEL ckquorum
SENTINEL flushconfig
# 实时重配置sentinel
SENTINEL MONITOR
SENTINEL REMOVE
SENTINEL SET
2.6 客户端如何使用sentinel集群
在这个例子中, ForClient: 三个 < sentinelIP: sentinelPORT >
https://redis.io/topics/sentinel-clients
三、主从版sentinel总结
- sentinel集群配置同sentinel
- 对外服务,使用lbc --> masterIP:port, 暴露lbc vip:vport,
- sentinel vs 主从版
- lbc
- sentinel集群的sentinel和redis实例是在同一个主机内,也就是一个sentinel集群服务一个reidis实例
- 主从版的sentinel集群会监控多个redis实例,
- failover,当发生failover的时候,sentinel集群不仅会负责切换,而且会负责调用lbc接口,让lbc的realserver指向切换后新的master
四、cluster模式
4.1 What
- Automatically sharded data across multiple redis nodes
- Continue operations when a subset of nodes are failures
4.2 集群实现及其特征
- Redis cluster集群,是一个自识别的过程,通过cluster enabled的方式,激活redis-server的启动模式,再通过redis-cli —cluster模式,来让他自己完成master -slave的识别和nodes的创建
- 两个端口: 一个for client, 一个集群内nodes间通信,失败检测,配置更新,failover授权等
- client端口可开白,可开黑,cluster bus port 必须集群内互通
- redis cluster 和Docker(也是NAT环境问题[TODO])
- Cluster data sharding:没有使用一致性哈希,而是给对应的KEY的CRC16校验值给16384取模,比如一个三节点的cluster集群,三个节点就有三个对应的哈希槽位【TODO,具体算法可后续查看】
- 【redis clusterCAP评估】: 雷同于mongod集群,所有nodes作为cluster sharding, 单个节点使用replication模型提供master-slave高可用保障, 有关Consistency一致性,redis cluster不支持特别强的一致性,因为是异步复制,在一些情况下(如果client往Master上面写,但是master上还没有个其replica上告知数据write就挂了)
4.3 redis cluster配置, Jetis配置
cluster-enabled <yes/no>
cluster-config-file <filename>
# 这个配置不是由用户编辑,而是有集群生成,当启动时,cluster节点信息,状态,变量信息等就会记录在内cluster-node-timeout <ms>
# 类似于sentinel的down-after-, master超过多少毫秒不可达, 将触发改节点的主从切换cluster-slave-validity-factor <factor>
[TODO 待学习]- cluster-migration-barrier
[TODO 待学习] cluster-require-full-coverage <yes/no>
默认是yes,当一个key计算出的hash slot未被cluster集群覆盖时,该redis节点将不再提供查询服务,这时候异常的节点将会导致集群不可用,但是你又希望集群的其他正常的节点能够正常提供接受请求,这时候设置此项目为no- cluster-allow-reads-when-down
[TODO 待学习]
4.4 集群搭建
# redis.conf // 启动redis cluster实例 * 6
port 7000
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
port 7001-7005
或者这样: ../../src/redis-server --port 30009 --cluster-enabled yes --cluster-config-file nodes-30009.conf --cluster-node-timeout 2000 --appendonly yes --appendfilename appendonly-30009.aof --dbfilename dump-30009.rdb --logfile 30009.log --daemonize yes
…
# redis-cli --cluster create 127.0.0.1:7000 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 127.0.0.1:7004 127.0.0.1:7005 --cluster-replicas 1
// 6个redis instance, 按照master:slave = 1:1 ==> 组成nodes * 3,并且三个nodes参与sharding,并分配好三个nodes的hash slot
# 执行完成后,redis会自动将master-slave划分好,并提供对应关系
# > cluster nodes查看当前集群状态
# > cluster info查看集群信息
# > cluster failover做主从切换
4.5 集群搭建2
create-cluster start
create-cluster create
create-cluster stop
# 集群reshard
交互式:redis-cli --cluster reshard 127.0.0.1:30001 //如果不满意redis划分的shard落点,可以自行划分
脚本: redis-cli reshard : --cluster-from --cluster-to --cluster-slots --cluster-yes
状态查看: redis-cli --cluster check 127.0.0.1:30001 // 用于查看reshard之后集群的状态是否正常
# 手动主从切换(failover)
在slave上执行 cluster failover
# 添加节点
redis-cli --cluster add-node
redis-cli --cluster add-node 127.0.0.1:7006 127.0.0.1:7000
//这样添加的节点默认都是master节点,第一: 虽然是master节点,但是却没有对应的hashslots,二来,当其他slave想failover为master时,这些无slots的master不参与选举过程
# 添加replica
方法:1 这种类似上面,添加一个slave,但是默认将这个slave分配到master上对应slave较少的master上, 即便配置了master-slave1:1, 当有新的slave加入时,可能会变成1:2
redis-cli --cluster add-node --cluster-slave
方法:2 直接指定对应的master
redis-cli --cluster add-node --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
方法:3 链接到对应的节点,手动通过CLUSTER REPLICA
redis > cluster replicate 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e
# 删除replica
主机:端口这个是集群随意一个即可,后面是要删除的node_id
redis-cli --cluster del-node 127.0.0.1:7000 ``
注意:replica可以直接删除,但是如果要删除master,必须要保证master节点上无数据(使用reshard,将该节点的数据全都迁移到其他节点)
# replica迁移(暂未具体学习)
# nodes升级(暂未具体学习)
# cluster集群迁移(暂时未学习)
4.6 用户接口
[
{"host": "localhost", "port": "30001"},
{"host": "localhost", "port": "30002"},
{"host": "localhost", "port": "30003"},
{"host": "localhost", "port": "30004"},
{"host": "localhost", "port": "30005"},
{"host": "localhost", "port": "30006"},
]
五、扩缩容
- 普通redis节点的扩缩容
直接通过更改maxmemory即可,sentinel通过主从切换方式来解决本机mem上限问题 -
redis+shard
redis-cli --cluster add-node
// 加master redis-cli --cluster add-node --cluster-slave --cluster-master-id 3c3a0c74aae0b56170ccb03a76b60cfe7dc1912e // 加对应replica redis-cli reshard : //后面参数可选[--cluster-from --cluster-to --cluster-slots --cluster-yes], host:port为扩容前已存在的节点(existed_node) redis-cli --cluster check 127.0.0.1:30001 // 检查reshard的结果是否有异常
七、备份&&恢复
- 无aof: 不提供备份恢复,唯一触发方式为客户端自行触发的rdb
- 半aof: 当半aof的集群需要做数据恢复时,如果需要修复数据,只需要将replica上的修改后的aof文件转移到master上启动即可
- 全aof: 按需对aof进行修改,直接启动集群即可
- RDB:
- 默认都不打开,只有当有需要迁移,或者主动备份时,才会采用bgsave,或者redis-cli -h 10.160.167.5 -p 2004 –rdb mobile4_bak.rdb)的方式进行RDB备份
- 前者不占用大量网络io,后者会占用大量网络IO
- 可以借助外部工具协助恢复[待学习]https://github.com/alibaba/RedisShake
- 其他注意:
- 当down机的redis实例需要从rdb文件中恢复时,如果appendonly yes时,此时workdir不能有对应的aof文件,redis实例启动时的默认行为就是从aof文件中加载
八、附录
8.1. 附录1(我司cluster模式配置样例)
#common配置:
bind 127.0.0.1 // 绑定地址
daemonize no // 非daemon模式运行(也是默认)
pidfile /home/redis/var/run/redis.pid //当redis被启动为一个daemon的时候,需要一个pid文件
protected-mode no //保护模式:默认(yes),如果yes, 且没有指定bind,而且没有配置密码,那么本实例仅支持本地client接入,不支持remote client access
port 6379
tcp-backlog 511 // 在高QPS(requests-per-sec)环境中这个值会影响当前服务器能够处理的tcp链接请求的速率(rate), 参考http://dwz.date/Rsd和官方配置文档
timeout 0 // 客户端闲置N秒后,自动关闭,(0 to disable)
tcp-keepalive 300 // tcp长链接相关
loglevel notice // 日志通告级别
logfile "/home/redis/var/log/redis.log" // log path
databases 16 // 实例最大db数, default DB0, select # 进行切换
save 900000000 1 // RDB trigger on disk save , 表示 sec秒内(也就是过了sec秒后),如果有超过changes个keys发生改变,就主动落地一次, 本例表示9xxxx秒后,如果有1个key发生变更,就刷一次rdb,当然这里永远不可能触发,一般用bgsave执行, 他不会阻塞进程
stop-writes-on-bgsave-error yes // 如果rdb snapshots失败了,或者最近一次bgsave也失败了,redis默认会拒绝本实例的写操作,本设置为了警告用户当前实例的persistent已经失败了
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir /home/redis/data/db // workdir
slave-serve-stale-data yes // 用于处理slave和master链接丢失,或者replication还是正常服务,如果yes(default) --> 那slave仍然会响应client的请求,但是数据可能是过期的,或者是空的(第一次sync from master), 如果no,client在给slave发命令时,会直接给client反馈“SYNC with master in progress”,
slave-read-only yes
repl-diskless-sync no // replication的同步策略,无盘 or socket, 目前disk是实验性能,建议no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no // 有关同步之后套接字的TCP_NODELAY的禁用, TODO, 暂时不了解
repl-backlog-size 64mb // 当slave与master断开连接时的一个sync缓冲,积压缓冲区的大小,体积越大,能够容忍的disconnection时间越长
repl-timeout 600 // replication 超时定义,如果1. 站在repl角度,如果sync时bulk传输i/o超时,如果给masterping超过600s则认为超时,站在master角度,如果repl响应超时600s,则认定为超时 【TODO】这里可以了解了解bulk transfer
slave-priority 100 // 5.0中叫 replica-priority, 整型数值,用于sentinel模式中,当master异常时,replica需要晋升时的优先度,值越小,优先级越高,0默认不被选择,default 100
maxmemory 36gb // 内存管理: 当实例使用的内存数量超过时,将根据maxmemory-policy策略进行key的删除
maxmemory-policy noeviction // 有很多策略,根据使用场景,sa自行设定,这里默认不进行key的eviction,而是反馈writes error
maxclients 50000
## 备份相关
appendonly no //fsync是否开启,内存flush --> disk的性能 vs persistent
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no //暂未了解[TODO]
auto-aof-rewrite-percentage 100 //暂未了解[TODO]
auto-aof-rewrite-min-size 4gb //暂未了解[TODO]
aof-load-truncated yes
lua-time-limit 5000
## reids-cluster
cluster-enabled yes
cluster-config-file /home/redis/data/conf/nodes.conf
cluster-node-timeout 15000 ## 类似于sentinel的down-after- 每个nodes的master-slave探测时间为多长时,会触发主从切换
cluster-require-full-coverage no ## 默认是yes,当一个key计算出的hash slot未被cluster集群覆盖时,该redis节点将不再提供查询服务,这时候异常的节点将会导致集群不可用,但是你又希望集群的其他正常的节点能够正常提供接受请求,这时候设置此项目为no
slowlog-log-slower-than 100000
slowlog-max-len 128
latency-monitor-threshold 1000
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-entries 512
list-max-ziplist-value 64
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit slave 0 0 0
client-output-buffer-limit pubsub 512mb 256mb 60
hz 10
aof-rewrite-incremental-fsync yes