定义
Redis是一个开源的,基于内存的数据结构存储系统,可以用作数据库、缓存和消息中间件。
特征
- 高性能
- 支持丰富的数据结构
- 丰富的操作类型,操作是原子性的
- 支持周期性持久化
- 分布式
- 开源免费,社区活跃
数据类型
string -字符串
hash-哈希
list-列表
set-集合
zset-有序集
Stream-流
Bitmap-位图
Bitfield-位域支持获取任意位长度的整数值
Geospatial-地理空间索引
过期策略
惰性删除:查询key的时候才对key进行检测。若key已经过期删除,若key没有过期则返回。缺点是如果过期的key一直没有被访问,则会一直无法被删除,存在于内存中。
定期删除:redis每隔一段时间对数据库做一次检查,删除里面过期的key,由于不可能对所有key做轮询,所以redis会每次随机选取一些key做检查和删除
内存淘汰机制
volatile-lru:针对设置了过期时间的key,使用lru(最近很少使用)算法进行淘汰
allkeys-lru:针对所有key使用lru算法进行淘汰
volatile-lfu:针对设置了过期时间的key,使用lfu(最近不经常使用)算法进行淘汰
allkeys-lfu:针对所有key使用lfu算法进行淘汰
volatile-ramdon:从所有设置了过期时间的key中使用随机淘汰方法进行淘汰
allkeys-ramdon:针对所有的key使用随机淘汰机制进行淘汰
volatile-ttl:针对设置了过期时间的key,越早过期的越先被淘汰
noeviction:不会淘汰任何数据,当使用的内存空间超过maxmemory时,再有写请求来时返回错误。
持久化方案
RDB(Redis数据库):RDB持久性会按照指定的时间间隔对数据集执行时间点快照。把当前内存中的数据集快照写入磁盘,恢复时将快照文件直接读到内存里。
AOF(仅追加文件):AOF持久性记录服务器收到的每个写入操作。然后就可以在服务器启动时再次重放这些操作,重建原始数据集。命令使用与Redis协议本身相同的格式进行记录
无持久性:完全禁止持久性,在仅缓存时使用
RDB+AOF:可以在同一个实例中结合使用AOF和RDB
分布式方案
客户端分片:将分片工作放在业务程序端,不依赖第三方分布式中间件,实现方法和代码可控,对开发人员要求高。
代理分片:将分片工作交给专门的代理程序来做,运维方案。如Twemproxy,Codis
服务器分片:Redis Cluster将所有key映射到16384个slot(插槽)中,集群中每个redis实例负责一部分,业务程序通过集成的redis cluster客户端进行操作。
主从复制
主从复制是Redis最基本、最常用的同步方式。
原理:将主节点的数据复制到从节点,使得从节点的数据与主节点保持一致。主从复制是异步的,从节点与主节点的数据不是实时同步的。如果主节点发生故障,从节点可能会因为数据延迟而出现数据丢失的情况。
集群模式
集群是Redis提供的分布式数据库方案,它将数据分散在多个节点上,每个节点都包含整个数据集的一部分。Redis集群通过分片来分布数据,每个节点负责数据集的一个片段。集群中每个分片都可以由一个或多个从节点,用于故障转移和高可用。
哨兵模式
除了主从复制外,Redis还提供了哨兵模式作为高可用性解决方案。哨兵模式可以自动检测主节点的状态。当主节点发生故障时,会自动将一个从节点转换为主节点。切换过程中,从节点会先将自己的数据与主节点保持一致,然后才能成为新的主节点。因此,在哨兵模式下,数据同步的过程与主从复制类似,但是其实现方式更加自动化。
缓存方案
Redis用作缓存组件时,其基于内存的读写图形,比基于磁盘读写的数据库性能要高,适合缓存高频热点的数据,来提高读性能。这样可以降低对数据库服务器的查询请求,提高系统性能。
数据一致性
读写步骤
在使用缓存与数据库保持一致性的场景中,通常遵循以下读写步骤来确保数据一致性。
读取操作:
检查缓存:客户端发起读取请求时,首先在缓存中查找所需数据。
缓存命中:如果缓存中有数据,则直接返回缓存中的数据给客户端。
缓存未命中:
如果缓存中没有对应数据,则从数据库中读取数据。
将从数据库中读取的数据写入缓存,以便下次可以直接从缓存中读取。
返回数据库中的数据给客户端。
写入操作:
更新数据库:客户端发起写入请求时,首先更新数据库中的数据。
失效缓存:在数据库更新成功后,立即使缓存中的相关数据失效或更新缓存中的数据。这样可以确保下次读取操作时,客户端能够从数据库中获取最新的数据。
分布式锁
使用分布式锁来保证在更新数据库和失效缓存的过程中,不会有其他并发操作干扰。
写串行化
通过队列等机制,确保对同一数据的读写操作不会并发执行。
订阅数据库变更
通过订阅数据库的变更日志(如MySQL的Binlog),在数据变更时自动更新或失效缓存。
缓存异常
缓存穿透
定义:缓存穿透是指查询一个一定不存在的数据,由于缓存中不存在该数据,每次请求都会落到数据库上,从而可能导致数据库压力过大甚至崩溃。
造成原因:恶意攻击,造成大量访问不存咋的key
解决方案:
缓存空对象-对于查询结果为空的键,也将其存入缓存,并设置一个较短的过期时间。这样,即使是不存在的数据也会被缓存,从而避免频繁查询数据库。
布隆过滤器-在访问缓存之前,使用布隆过滤器检查数据是否可能存在。如果布隆过滤器判断数据不存在,则直接返回,不查询缓存和数据库
接口限流-对于访问频率极高的请求,可以使用接口限流来放置恶意攻击
安全性检查-应用程序检查key的合法性,提前拒绝不合法请求;检查请求来源IP,限制访问次数,或设置黑名单
缓存雪崩
定义:缓存雪崩是指缓存中大量数据同时过期或者缓存服务器突然宕机,导致大量请求直接落到数据库上,引起数据库压力骤增,甚至导致数据库崩溃
造成原因:Redis故障-如Redis宕机、网络抖动
解决方案:
设置不同的过期时间:为缓存数据设置不同的过期时间,避免大量数据同时过期
使用持久化缓存:如果RDB或AOF,即使服务重启,也能快速回复缓存数据
服务熔断和限流:在缓存失效或者服务故障时,通过服务熔断和限流来保护后端系统
多级缓存:构件多级缓存架构,例如本地缓存+分布式缓存,即使分布式缓存出现问题,本地缓存仍能提供一定的保护
缓存击穿
定义:缓存击穿是指某个热点数据在缓存中过期,而因此大量并发请求访问数据,导致这些数据都落到数据库上,从而可能引起数据库压力过大。
造成原因:热点key设置了太短的过期时间
解决方案
热点数据永不过期:对于热点数据,可以设置永不过期或者过期时间非常长
互斥锁:在缓存失效时,通过互斥锁来保证同一时间只有一个请求去查询数据库,并更新缓存,其他请求等待缓存更新完成后再返回数据
数据热加载:使用后台线程或者定时任务,预先加载热点数据至缓存中