Redis 要点
Redis 要点
- 资料来源于网络。
- Redis是一个开源的、由C语言编写的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。
- 常用数据类型有hash、string、list、set、sortedset,Key-Value形式,其中Key一定是string。
数据类型底层
string -> SDS -> set,get,decr,incr,mget
hash -> ziplist/hashtable -> hget,hset,hgetall
list -> ziplist/linkedlist -> lpush,rpush,lpop,rpop,lrange
set -> intset/hashtable -> sadd,spop,smembers,sunion
zset -> ziplist/skiplist -> zadd,zrange,zrem,zcard
简单动态字符串 SDS
char buf[]; //字节数组
int len; //字符串长度
int free; //未使用长度
哈希表 hashtable
- dict 结构内部包含两个 hashtable,通常情况下只有一个 hashtable 是有值的,数据结构类似于Java的hashmap。
- 但是在 dict 扩容缩容时,需要分配新的 hashtable,然后进行渐进式搬迁/渐进式rehash,这时候两个 hashtable 存储的分别是旧的 hashtable 和新的 hashtable。待搬迁结束后,旧的 hashtable 被删除,新的 hashtable 取而代之。
- Redis 的字典默认的 hash 函数是 siphash。
压缩列表 ziplist
- 压缩列表是一块连续的内存空间,元素之间紧挨着存储,没有任何冗余空隙。
- hash中K、V紧挨着排列。
- zset中V、score紧挨着排列。
双向链表 linkedlist
- 普通的双向链表。
小整数集合 intset
- intset始终保持从小到大有序。
跳跃链表 skiplist
- 拔高某一部分,形成一个新的链表结构,便于查找。
优点
- 纯内存操作。
- 单线程,避免了上下文切换。
- 非阻塞I/O多路复用机制/事件驱动。
问题
缓存雪崩
缓存数据设置的过期时间相同,且Redis将这部分数据全部删光了。这就会导致在这段时间内,这些缓存同时失效,全部请求到数据库中。
缓存穿透
缓存穿透是指查询一个一定不存在的数据。由于缓存不命中,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。
缓存、数据库双写一致
- 先更新数据库 再删除缓存
- 先删除缓存 再更新数据库
过期策略
- 定时删除
- 到时间点上就把所有过期的键删除了。
- 惰性删除 - Redis使用
- 每次从键空间取键的时候,判断一下该键是否过期了,如果过期了就删除。
- 定期删除 - Redis使用
- 每隔一段时间去删除过期键,限制删除的执行时长和频率。
持久化方式
- RDB(基于快照),将某一时刻的所有数据保存到一个RDB文件中。
- AOF(append-only-file 文件追加),当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。
RDB
- SAVE会阻塞Redis服务器进程,服务器不能接收任何请求,直到RDB文件创建完毕为止。
- BGSAVE创建出一个子进程负责创建RDB文件,已过期的键不会保存在RDB文件中。
AOF重写
- AOF重写由Redis自行触发,在后台子进程进行。
- AOF重写不需要读取现有的AOF文件,AOF重写是通过读取服务器当前数据库的数据来实现的。
内存淘汰机制
机制名称 | 挑选集合 | 挑选策略 |
---|---|---|
volatile-lru | 从已设置过期时间数据集中 | 最近最少使用 |
volatile-ttl | 从已设置过期时间数据集中 | 最接近过期时间 |
volatile-random | 从已设置过期时间数据集中 | 随机 |
allkeys-lru | 从所有数据集中 | 最近最少使用 |
allkeys-random | 从所有数据集中 | 随机 |
noeviction | 禁止淘汰数据 | 禁止淘汰数据 |
Redis 集群
主从架构
特点
- 主服务器负责接收写请求
- 从服务器负责接收读请求
- 从服务器的数据由主服务器复制过去。主从服务器的数据是一致的
优势
- 读写分离(主服务器负责写,从服务器负责读)
- 高可用(某一台从服务器挂了,其他从服务器还能继续接收请求,不影响服务)
- 处理更多的并发量(每台从服务器都可以接收读请求,读QPS就上去了)
主从复制
同步(sync)
- 将从服务器的数据库状态更新至主服务器的数据库状态
命令传播(command propagate)
- 主服务器的数据库状态被修改,导致主从服务器的数据库状态不一致,让主从服务器的数据库状态重新回到一致状态。
哨兵机制(Sentinel)
- 如果主服务器挂了,我们可以将从服务器升级为主服务器,等到旧的主服务器重连上来,会将它变成从服务器。
- 过程称为主备切换/故障转移,用于实现Redis的高可用性。