深入学习Redis_(一)五种基本数据类型、RedisTemplate、RedisCache、缓存雪崩等
LRU 算法实现:
1.通过双向链表来实现,新数据插入到链表头部;
2.每当缓存命中(即缓存 数据被访问),则将数据移到链表头部;
3.当链表满的时候,将链表尾部的数据丢弃。
Redis 4.0 加入了 LFU(least frequency use)淘汰策略,包括 volatile-lfu 和 allkeys-lfu,通过统计访问频率,将访问频率最少,即最不经常使用的 KV 淘汰。
Redis 为了保证效率,数据缓存在了内存中,但是会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件中,以保证数据的持久化。
Redis 的持久化策略有两种:
RDB:快照形式是直接把内存中的数据保存到一个 dump 的文件中,定时保存,保存策略。
默认 Redis 是会以快照"RDB"的形式将数据持久化到磁盘的一个二进制文件 dump.rdb。
RDB(快照持久化)是Redis默认采用的持久化方式,在redis.conf配置文件中默认有此下配置:
#在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 900 1
#在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 300 10
#在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发BGSAVE命令创建快照。
save 60 10000
当 Redis 需要做持久化时,Redis 会 fork 一个子进程,子进程将数据写到磁盘上一个临时 RDB 文件中。当子进程完成写临时文件后,将原来的 RDB 替换掉,这样的好处是可以 copy-on-write。
文件体积小,数据恢复速度也快
丢失数据
AOF:把所有的对 Redis 的服务器进行修改的命令都存到一个文件里,命令的集合。Redis 默认是快照 RDB 的持久化方式。
当 Redis 重启的时候,它会优先使用 AOF 文件来还原数据集,因为 AOF 文件保存的数据集通常比 RDB 文件所保存的数据集更完整。你甚至可以关闭持久化功能,让数据只在服务器运行时存。
使用 AOF 做持久化,每一个写命令都通过 write 函数追加到 appendonly.aof 中,配置方式如下:
# appendfsync always #每次有数据修改发生时都会写入AOF文件。
appendfsync everysec #每秒钟同步一次,显示地将多个写命令同步到硬盘 默认
# appendfsync no #让操作系统决定何时进行同步
AOF 可以做到全程持久化,通过appendonly
参数开启。
这样 Redis 每执行一个修改数据的命令,都会把它添加到 AOF 文件中,当 Redis 重启时,将会读取 AOF 文件进行重放,恢复到 Redis 关闭前的最后时刻。
数据最全
文件体积大,数据恢复速度慢
如果你的业务对于数据丢失不敏感,采用 RDB 方案持久化数据
如果你的业务对数据完整性要求比较高,采用 AOF 方案持久化数据
由于 AOF 文件中记录的都是每一次写操作,但对于同一个 key 可能会发生多次修改,我们只保留最后一次被修改的值,是不是也可以?
是的,这就是我们经常听到的「AOF rewrite」,你也可以把它理解为 AOF 「瘦身」。
当AOF文件随着写命令的运行膨胀时,当文件大小触碰到临界时,rewrite会被运行。
rewrite机制:aof里存放了所有的redis 操作指令,当aof文件达到一定条件或者手动bgrewriteaof
命令都可以触发rewrite
。
rewrite
之后aof文件会保存keys的最后的状态,清除掉之前冗余的,来缩小这个文件。
自动触发的条件:
long long growth =(server.appendonly_current_size*100/base) - 100;
if (growth >=server.auto_aofrewrite_perc)
在配置文件里设置过:
auto-aof-rewrite-percentage 100 (当前写入日志文件的大小超过上一次rewrite之后的文件大小的百分之100时就是2倍时触发Rewrite)
具体来说,当 AOF rewrite 时,Redis 先以 RDB 格式在 AOF 文件中写入一个数据快照,再把在这期间产生的每一个写命令,追加到 AOF 文件中。因为 RDB 是二进制压缩写入的,这样 AOF 文件体积就变得更小了。
(Redis 4.0 以上版本才支持混合持久化。)
修改redis.conf配置文件
aof-use-rdb-preamble yes
或者使用命令行的方式:
redis-cli
config set aof-use-rdb-preamble yes
Redis 单节点存在单点故障问题,为了解决单点问题,一般都需要对 Redis 配置从节点,然后使用哨兵来监听主节点的存活状态,如果主节点挂掉,从节点能继续提供缓存功能。
主从配置结合哨兵模式能解决单点故障问题,提高 Redis 可用性。
Redis 服务器分为两类:一类是主数据库(Master
),另一类是从数据库(Slave
)。
主数据库可以进行读写操作,当写操作导致数据变化时会自动将数据同步给从数据库。
从数据库一般是只读的,并接受主数据库同步过来的数据。一个主数据库可以拥有多个从数据库, 而一个从数据库只能拥有一个主数据库。
从节点执行 slaveof[masterIP][masterPort]
,保存主节点信息。
从节点中的定时任务发现主节点信息,建立和主节点的 Socket 连接。
从节点发送 Ping 信号,主节点返回 Pong,两边能互相通信。
连接建立后,主节点将所有数据发送给从节点(数据同步)。
主节点把当前的数据同步给从节点后,便完成了复制的建立过程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。
一旦主节点宕机,从节点晋升为主节点,同时需要修改应用方的主节点地址,还需要命令所有从节点去复制新的主节点,整个过程需要人工干预。
主节点的写能力受到单机的限制。
主节点的存储能力受到单机的限制。
原生复制的弊端在早期的版本中也会比较突出,比如:Redis 复制中断后,从节点会发起 psync。
此时如果同步不成功,则会进行全量同步,主库执行全量备份的同时,可能会造成毫秒或秒级的卡顿。
解决方案:哨兵模式
Redis Sentinel(哨兵)主要功能包括主节点存活检测、主从运行情况检测、自动故障转移、主从切换
Redis Sentinel(哨兵) 最小配置是一主一从。Redis 的 Sentinel 系统可以用来管理多个 Redis 服务器。
该系统可以执行以下四个任务:
监控
:不断检查主服务器和从服务器是否正常运行。
通知
:当被监控的某个 Redis 服务器出现问题,Sentinel 通过 API 脚本向管理员或者其他应用程序发出通知。
自动故障转移
:哨兵每间隔一段时间,询问 master 是否正常,master 正常回复,表示状态正常,回复超时表示异常,哨兵发现异常,发起主从切换。
它会将与失效主节点是主从关系的其中一个从节点升级为新的主节点,并且将其他的从节点指向新的主节点,这样人工干预就可以免了。
配置提供者
:在 Redis Sentinel 模式下,客户端应用在初始化时连接的是 Sentinel 节点集合,从中获取主节点的信息。
主服务器
、从服务器
以及其他的 Sentinel 实例
发送一个 PING 命令。down-after-milliseconds
所指定的值,那么这个实例会被 Sentinel 标记为主观下线。主观下线
状态。客观下线
。自动选出新的主节点
,将剩余从节点指向新的主节点进行数据复制
。如果 master 状态正常,但这个哨兵在询问 master 时,它们之间的网络发生了问题,那这个哨兵可能会误判。
我们可以部署多个哨兵,让它们分布在不同的机器上,它们一起监测 master 的状态,流程就变成了这样:
哨兵协商判定 master 异常后,这里还有一个问题:由哪个哨兵来发起主从切换呢?
答案是,选出一个哨兵「领导者」,由这个领导者进行主从切换。
在选举哨兵领导者时,我们可以制定这样一个选举规则:
每个哨兵都询问其它哨兵,请求对方为自己投票
每个哨兵只投票给第一个请求投票的哨兵,且只能投票一次
首先拿到超过半数投票的哨兵,当选为领导者,发起主从切换。
这个选举的过程就是我们经常听到的:分布式系统领域中的「共识算法」
。
这个算法还规定节点的数量必须是奇数
个,这样可以保证系统中即使有节点发生了故障,剩余超过「半数」的节点状态正常,依旧可以提供正确的结果,也就是说,这个算法还兼容了存在故障节点的情况。
深入学习Redis_(三)事务、分布式锁、消息队列、延时队列等