文章目录
一、淘汰策略
0. 技术背景
当redis管理的内存达到上限时,此时继续往数据库增加数据,会触发淘汰策略选择性淘汰老的数据。默认策略是禁止淘汰(redis返回错误码给server端)
- 淘汰策略:
LRU最近最长时间未使用、
LFU 最近最少使用次数
1. 过期指令(整个kv对淘汰)
//设置 key 在 seconds 秒后过期
expire [key] [time秒]
//设置 key 在 milliseconds 毫秒后过期
pexpire [key] [time毫秒]
//查看 key 剩余过期时间
TTL key / PTTL key
//移除 key 的过期时间,使其永久存在
PERSIST key
实操
2. 配置maxmemory
maxmemory:设置Redis最大可用内存限制
//单位支持: bytes,kb,mb,gb eg: maxmemory 4gb
maxmemory-policy
策略 含义 noeviction 不删除任何数据,写操作会报错 allkeys-lru 所有 key 中,淘汰最近最少使用的 key volatile-lru 仅在设置了过期时间的 key 中,淘汰最近最少使用的 allkeys-random 所有 key 中,随机选择 key 进行淘汰 volatile-random 仅在设置了过期时间的 key 中,随机淘汰 allkeys-lfu 所有 key 中,淘汰使用频率最低的 key volatile-lfu 仅在设置了过期时间的 key 中,淘汰使用频率最低的 volatile-ttl 仅在设置了过期时间的 key 中,淘汰即将过期的 key
注:volatile 策略只作用于设置了过期时间的键;
allkeys 策略作用于所有的键;maxmemory-samples
在执行策略时,从样本中采样,然后从中选出最符合淘汰机制的keyeg: 1.设置allkeys-lru, 2.并设定 maxmemory-samples 10 ---------------------------- Redis会从所有key中随机采样10个, 然后选出最近最少访问的那个key来淘汰;
二、持久化
1. 技术背景
redis的数据全部在内存中,如果突然宕机,数据就会全部丢失;因此需要持久化来保证Redis的数据不会因为故障而丢失,redis重启的时候可以重新加载持久化文件来恢复数据。
内存化数据读取到磁盘,重启时从磁盘读回,保持数据持久化
八股1:fopen\fwrite流程
- 机器断电 1、2数据丢失
打开某个文件,进程关闭 1数据丢失
八股2:fork调用- 写时复制原理
- 为了提高效率而采用的一种延迟复制优化策略
fork进程那一刻 相当于给父进程的内存打了一个快照
父子进程最初共享同一块物理内存,只有当任一方尝试修改内存时,发生写操作,才会复制对应页到新的物理内存,从而实现真正的“独立”
父进程对数据修改,触发写保护中断,从而进行物理内存的复制,父进程的页表指向新的物理内存(谁修改谁指向新的物理内存)
2. redis持久化方式(aof | rdb)
aof(Apped Only File)
AOF持久化通过记录服务器所执行的所有写操作命令来记录数据库状态。这些命令会被追加到AOF文件的末尾,支持:
- always:每次写命令都会同步(sync)写入到磁盘
- everysec:每秒将aof缓冲区内容同步到磁盘中(由后台线程执行,是默认的方式)
- no:Redis只负责写入aof 缓存,不主动同步到磁盘,由系统决定同步或手动同步
优点: 数据更安全; 命令可读,易于恢复/调试
缺点: 文件体积大,性能开销高于rdb; 数据存在一定冗余
aof-rewrite
处理 aof 文件过大,减少 aof 数据恢复速度过慢;
防止 AOF 文件无限膨胀,是后台异步进行的,不阻塞主线程;
工作原理:
fork进程,根据内存数据生成 aof 文件,避免同一个 key 历史冗余,在重写 aof 期间,对 redis 的写操作记录到重写缓存区,当重写 aof 结束后,附加到 aof 文件末尾。
rdb(Redis DataBase)
- 周期性将内存数据写入磁盘(.rdb 文件)
- 通过 fork 子进程来执行,不影响主线程
- rdb 存储的是经过压缩的二进制数据
优点: 文件小,恢复速度快; 适合备份、冷存储等场景
缺点: 有数据丢失风险(最近一次快照之后的修改会丢)
rdb-aof 混用
通过 fork 子进程,根据内存数据生成 rdb 文件,在rdb持久化期间,对redis 的写操作记录到重写缓冲区,当rdb 持久化结束后,附加到 aof 文件末尾
大Key对持久化的影响
大Key是指单个 key 对应的数据量非常大, 会导致重启时间变长,甚至服务阻塞.
- 对rdb:fork 期间,写时复制(COW)会导致 内存急剧增长
- 对aof:每次修改都写入完整命令,大key会让文件迅速膨胀,AOF重写成本高
- 两者持久化方案的优缺点对比【00:41:00】
aof (根据写请求记录当前内存数据,有3个策略,数据冗余aof-rewrite)
rdb(基于内存所有数据对象编码直接持久化)
- 配置
#Redis 的配置主要通过 redis.conf 文件来完成 #在 redis.conf 中找到以下配置项: appendonly yes # 开启 AOF 持久化 appendfsync always # 每次写入都 fsync(最安全但性能最低) # appendfsync everysec # 每秒 fsync 一次(默认值,推荐) # appendfsync no # 不主动 fsync,依赖系统调度(性能好,安全性低) #AOF 重写相关配置: auto-aof-rewrite-percentage 100 auto-aof-rewrite-min-size 64mb #意思是:当 AOF 文件大小是上一次 rewrite 后的 100%,且超过 64MB,就会自动触发重写(即瘦身优化) #RDB 持久化配置: save 900 1 # 900 秒内有 1 个 key 改变就触发快照 save 300 10 # 300 秒内有 10 个 key 改变就触发快照 save 60 10000 # 60 秒内有 10000 个 key 改变就触发快照 # 若不需要 RDB 持久化可注释所有 save 行 # stop-writes-on-bgsave-error yes # RDB 异常时是否停止写入 # 过期策略配置(maxmemory-policy) maxmemory 256mb # 设置内存上限,建议结合使用 maxmemory-policy allkeys-lru # 淘汰策略(默认是 noeviction) maxmemory-samples 5 # 随机选择几个 key 进行淘汰评估 #启动 Redis 并应用配置 redis-server /etc/redis/redis.conf
三、高可用
1. redis主从复制(解决单点故障)
主要用来实现redis数据的可靠性;防止主redis所在磁盘损坏,造成数据永久丢失;主从之间采用异步复制的方式(从数据库 主动向 主数据库建立连接)
- 异步复制:主节点将写操作同步到从节点,但不是实时同步(存在数据延迟)
- 环形缓冲区:主节点维护一个固定大小的缓冲区保存最近的写命令,用于断线后快速增量同步
- 复制偏移量:主从节点维护一个偏移量,表示同步的数据位置,用于比对是否需要全量(主从节点之间的数据全部重新同步的过程)或增量复制(主从节点之间同步断开期间 丢失的数据部分补充同步,无需全量)
- runid:每个 Redis 实例有唯一运行 ID,复制过程中标识主节点身份
作用: 解决了单点故障、高可用性的基础
数据同步: 全量数据同步 、 增量数据同步
2. redis哨兵模式(实现故障自动转移)
目的:实现 Redis 故障自动转移。仅仅保障了单节点的高可用(主节点宕机可自动切换,从节点提升为主)
原理图(知道怎么做可用性即可),缺点是不能进行横向扩展
[流程]
主观下线:
客观下线
烧饼选举
从库选主
故障转移
-----------------------
[如何使用]
一个 Redis 哨兵(Sentinel)模式的配置与使用示例,包含:
1 个主节点(master)
2 个从节点(slave)
3 个哨兵(sentinel)
1 个客户端访问配置方式
------------------------
[缺点]
主观宕机存在误判风险
部署麻烦
没有避免数据丢失问题
没有数据扩展
1.主从配置
#主节点 redis-master.conf(6379)
port 6379
dir /data/redis/master
appendonly yes
#从节点 redis-slave1.conf(6380)
port 6380
dir /data/redis/slave1
replicaof 127.0.0.1 6379
appendonly yes
#从节点 redis-slave2.conf(6381)
port 6381
dir /data/redis/slave2
replicaof 127.0.0.1 6379
appendonly yes
2.哨兵配置(sentinel.conf)
每个哨兵配置几乎一样,只需修改端口和自身 IP
#哨兵1 sentinel1.conf(26379)
port 26379
dir /data/redis/sentinel1
sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 10000
sentinel parallel-syncs mymaster 1
#其他两个哨兵只改端口和目录,比如:
sentinel2.conf: 端口 26380,目录 /data/redis/sentinel2
sentinel3.conf: 端口 26381,目录 /data/redis/sentinel3
3.启动
放到一个文件比如start下面,然后chmod +x,最后./start
# 启动主从
redis-server redis-master.conf
redis-server redis-slave1.conf
redis-server redis-slave2.conf
# 启动哨兵
redis-sentinel sentinel1.conf
redis-sentinel sentinel2.conf
redis-sentinel sentinel3.conf
3. cluster集群(去中心化)
去中心化结构,每个节点互相通信,无集中式主控节点
[特征]
1.客户端与服务端缓存槽位信息,以服务器为主,客户节点缓存主要为了避免连接切换
2.自动分片,16384(2^14)个哈希槽分配给不同节点
3.每个主节点可挂载一个或多个从节点实现高可用
--------------------------------
[流程]
1.客户端根据 key 计算哈希槽值
2.连接对应槽所属的主节点
3.若节点不对,返回 MOVED 重定向信息,客户端重新连接目标节点
--------------------------------
[缺点]
1.不支持多 key 操作跨槽执行(除非通过 hash tags)
2.集群节点间通讯复杂,部署维护成本高
3.客户端需支持 Redis Cluster 协议
- 实操集群配置【01:38:00】
跟视频实操一遍
#安装redis
#hiredis-cluster 安装编译
#准备节点目录
mkdir -p ~/redis-cluster/{7000,7001,7002,7003,7004,7005}
#配置每个节点的 redis.conf
for port in 7000 7001 7002 7003 7004 7005
do
cp /etc/redis/redis.conf ~/redis-cluster/$port/
done
#修改配置文件(每个节点都需要):以 7000 为例:~/redis-cluster/7000/redis.conf
port 7000
bind 127.0.0.1
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes
daemonize yes
dir ./
logfile "redis.log"
#启动所有 Redis 实例
for port in 7000 7001 7002 7003 7004 7005
do
redis-server ~/redis-cluster/$port/redis.conf
done
#查看是否启动:
ps -ef | grep redis
#redis-cli创建集群
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
#验证创建集群是否成功
redis-cli -c -p 7000
> cluster info
> cluster nodes
优秀笔记:
1. 主从同步与对象模型
2. Redis 主从同步与对象模型(四)
参考学习:https://github.com/0voice