Redis的原理及应用
Redis的数据类型
Redis支持String、Hash、List、Set、ZSet、Bitmap、HyperLogLog、Geospatial等8种数据类型。
- String: String是Redis基本的数据类型,一个key对应一个value。String类型的值最大能存储512MB。
- Hash: Redis Hash是一个键值(key -> value)对集合。
- List: Redis List是简单的字符串列表,按照插入顺序排序。可以添加一个元素到列表的头部(左边)或者尾部(右边)。
最多可存储2^31-1(4亿多)个元素。 - Set: Set是String类型的无序集合。集合是通过散列表实现的,所以添加、删除、查找的复杂度都是O(1)。
- ZSet: Redis ZSet和Set一样也是String类型元素的集合,且不允许有重复的成员,不同的是,每个元素都会关联一个double类型
的分数。Redis正是通过分数来为集合中的成员进行从小到大的排序的。 - Bitmap: 通过操作二进制位记录数据。
- HyperLogLog: 用于估计一个Set中元素数量的概率性的数据结构。
- Geospatial: 用于地理空间关系计算。
Redis的发布和订阅
Redis发布、订阅是一种消息通信模式:发送者(pub)向频道(channel)发送消息,订阅者(sub)接收频道上的消息。Redis客户端可以
订阅任意数量的频道,发送者也可以向任意频道发送数据。
Redis的持久化
Redis的持久化分为RDB和AOF。
- RDB(Redis DataBase): RDB在指定的时间间隔内对数据进行快照存储。
- RDB文件格式紧凑,方便数据传输和数据恢复。
- 在保存.rdb快照文件时,父进程会fork出一个子进程,由子进程完成具体的持久化操作。
- bgsave与save的区别:save会阻塞Redis服务器,直到RDB完成。bgsave是fork子线程,持久化由子线程完成,阻塞只发生在fork子线程的阶段。
- 全量复制。
- AOF(Append Of File): AOF记录对服务器的每次写操作,在Redis重启会重放这些命令来恢复数据
- AOF命令以Redis协议追加和保存每次写操作。
- 支持对AOF文件进行重写,使得AOF文件的体积不至于过大。
- 不同的fsync策略(无fsync,每秒fsync,每次写fsync)。
- AOF文件是日志格式,容易被操作。
- 实时复制。
Redis集群数据复制原理
Redis提供了复制功能,可以实现主数据库(Master)中的数据更新后,自动将更新的数据同步到从数据库(Slave)。
- 一个从数据库在启动后,会向主数据库发送SYNC命令
- 主数据库在接收到SYNC命令后,会开始在后台保存快照(RDB持久化过程),并将保存快照期间接收到的命令缓存起来,生成.rdb快照文件。
- 在主数据库快照执行完成后,Redis会将快照文件和所有缓存的命令以.rdb快照文件的形式发送给从数据库。
- 从数据库收到主数据库的.rdb快照文件后,载入该快照文件到本地。
- 从数据库执行载入后的.rdb快照文件,将数据写入内存中。
- 1~5过程,称之为复制初始化。
- 在复制初始化结束后,主数据库在每次收到写命令时,都会将命令同步给从数据库,从而保证主从数据库的数据一致。
Redis集群模式及工作原理
Redis有三种集群模式:主从模式、哨兵模式、Redis Cluster。
主从模式
主从模式:所有的写请求都被发送到主数据库上,再由主数据库将数据同步到从数据库上。主数据库主要用于执行写操作和数据同步,从数据库主要用于读操作。
哨兵模式
哨兵模式:在主从模式上添加一个哨兵的角色来监控集群的运行状态。哨兵通过发送命令让Redis服务器返回其运行状态。哨兵是一个独立运行的进程,在检测到Master宕机时会自动
将Slave切换成Master,然后通过pub/sub模式通知其他服务修改配置文件,完成主备热切。
Redis-Cluster
Redis-Cluster:Redis-Cluster实现了在多个redis节点之间进行数据分片和数据复制。基于Redis集群的数据自动分片能力,可方便地对Redis集群进行横向扩展,以提高Redis集群的
吞吐量。基于redis集群的数据复制能力,在集群中的一部分节点失效或者无法进行通信时,Redis仍然可以基于副本数据对外提供服务,这提高了集群的可用性。
以下命令是redis 5.x及后续版本创建集群的命令。
1 | 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 |
–cluster-replicas 参数为数字,1表示每个主节点需要1个从节点
Redis-Cluster有以下特点:
- 所有Redis节点彼此通过PING-PONG机制互联,内部使用二进制协议优化传输速度和带宽。
- 在集群中超过半数的节点检测到某个节点Fail后,将该节点值为Fail状态。
- 客户端连接集群中的任何一个节点即可对集群进行操作。
- Redis-Cluster把所有的物理节点都映射到0~16383的slot上,cluster负责维护每个节点上数据槽的分配。
- Redis的数据分配策略:Redis首先对Key使用CRC16算法算出一个结果,然后把结果对16384取余,这样每个key
都会对应一个编号为0~16383的slot。 - slot可以理解为是Redis节点的别名,比如key1和key2经过分配策略取值都是6000,那这连个key就在包含slot=6000的节点上,
此时恰好是节点C,那么节点C就保存了key1和key2。 - Redis会根据节点的数量大致均匀地将slot映射到不同的节点。
分布式缓存设计的核心问题
缓存淘汰策略
- FIFO(先进先出):判断被存储的时间,离目前最远的数据优先淘汰。
- LRU(最近最少使用):判断缓存最近被使用的时间,距离当前最远的数据优先被淘汰。
- LFU(最不经常使用):在一段时间内,被使用次数最少的缓存优先被淘汰。
- TTL(过期时间):设置过期时间,时间到期后,缓存淘汰。
缓存雪崩
缓存雪崩:在同一时刻由于大量缓存失效,导致大量查询缓存的请求都去查询数据库,对数据库造成巨大压力。
- 设置不同的失效时间
缓存穿透
缓存穿透:缓存系统故障或者用户频繁查询系统中不存在的数据,这时请求会传过缓存不断被发送到数据库,导致数据库负载过重。
- 布隆过滤器
- cache null:在缓存中记录一个短暂的(数据过期时间内)数据在系统中是否存在的状态,如果不存在,直接返回null。
布隆过滤器
- 首先需要k个hash函数,每个函数可以把key散列成为1个整数
- 初始化时,需要一个长度为n比特的数组,每个比特位初始化为0
- 某个key加入集合时,用k个hash函数计算出k个散列值,并把数组中对应的比特位置为1
- 判断某个key是否存在,用k个hash函数计算出k个散列值,并查询数组中对应的比特位,如果所有的比特位都是1,认为存在。
优点:不需要存储key,节省空间
缺点:
- 算法判断key在集合中时,有一定的概率key其实不在集合中
- 无法删除
缓存更新
策略:延迟双删
- 删除redis缓存
- 更新数据库
- 更新成功后,通过延迟队列,进行二次删除