1. Redis与Memcache能力对比
工作 | MemCache | Redis |
---|---|---|
数据类型 | 简单 key/value 结构 | 丰富的数据结构 |
持久性 | 不支持 | 支持 |
分布式存储 | 客户端哈希分片/一致性哈希 | 多种方式,主从、Sentinel、Cluster 等 |
多线程支持 | 支持 | 支持(Redis5.0及以前版本不支持) |
内存管理 | 私有内存池/内存池 | 无 |
事务支持 | 不支持 | 有限支持 |
数据容灾 | 不支持,不能做数据恢复 | 支持,可以在灾难发生时,恢复数据 |
2. Redis集群切片的常见方式
集群切片方式 | 核心特点 |
---|---|
客户端分片 | 在客户端通过key的hash 值对应到不同的服务器。 |
中间件实现分片 | 在应用软件和 Redis 中间,例如:Twemproxy、Codis 等,由中间件实现服务到后台Redis节点的路由分派。 |
客户端服务端协作分片 | 客户端与服务端协作完成分片处理。 |
3. Redis分布式存储方案
分布式存储方案 | 核心特点 |
---|---|
主从(Master/Slave)模式 | 一主多从,故障时手动切换。 |
哨兵(Sentinel)模式 | 有哨兵的一主多从,主节点故障自动选择新的主节点。 |
集群(Cluster)模式 | 分节点对等集群,分slots,不同slots的信息存储到不同节点。 |
4. Redis数据分片方案
分片方案 | 分片方式 | 说明 |
---|---|---|
范围分片 | 按数据范围值来做分 | 例:按用户编号分片,0-999999 映射到实例A;1000000-1999999映射到实例 B。 |
哈希分片 | 通过对key进行hash运算分片 | 可以把数据分配到不同实例,这类似于取余操作,余数相同的,放在一个实例上。 |
一致性哈希分片 | 哈希分片的改进 | 可以有效解决重新分配节点带来的无法命中问题。 |
5. Redis持久化
对比维度 | RDB持久化 | AOF 持久化 |
---|---|---|
备份量 | 重量级的全量备份,保存整个数据库 | 轻量级增量备份,一次只保存一个修改命令 |
保存间隔时间 | 保存间隔时间长 | 保存间隔时间短,默认1秒 |
还原速度 | 数据还原速度快 | 数据还原速度慢 |
阻塞情况 | save会阻塞,但bgsave 或者自动不会阻塞 | 无论是平时还是AOF重写,都不会阻塞 |
数据体积 | 同等数据体积:小 | 同等数据体积:大 |
安全性 | 数据安全性:低,容易丢数据 | 数据安全性:高,根据策略决定 |
6. Redis常用的数据类型
数据类型 | 说明 |
---|---|
string(字符串) | 基本的数据存储单元,可以存储字符串、整数或者浮点数。 |
hash(哈希) | 一个键值对集合,可以存储多个字段。 |
list(列表) | 一个简单的列表,可以存储一系列的字符串元素。 |
set(集合) | 一个无序集合,可以存储不重复的字符串元素。 |
zset(sorted set:有序集合) | 类似于集合,但是每个元素都有一个分数(score)与之关联。 |
位图(Bitmaps) | 基于字符串类型,可以对每个位进行操作。 |
超日志(HyperLogLogs) | 用于基数统计,可以估算集合中的唯一元素数量。 |
地理空间(Geospatial) | 用于存储地理位置信息。 |
发布/订阅(Pub/Sub) | 一种消息通信模式,允许客户端订阅消息通道,并接收发布到该通道的消息。 |
流(Streams) | 用于消息队列和日志存储,支持消息的持久化和时间排序。 |
模块(Modules) | Redis 支持动态加载模块,可以扩展 Redis 的功能。 |
7. Redis常用命令
String常用命令
最大能存储512MB
SET key value:设置键的值。
GET key:获取键的值。
INCR key:将键的值加 1。
DECR key:将键的值减 1。
APPEND key value:将值追加到键的值之后。
Hash
多可以存储 2^32 – 1 个键值对
HSET key field value:设置哈希表中字段的值。
HGET key field:获取哈希表中字段的值。
HGETALL key:获取哈希表中所有字段和值。
HDEL key field:删除哈希表中的一个或多个字段。
List
最多可以存储 2^32 – 1 个元素
LPUSH key value:将值插入到列表头部。
RPUSH key value:将值插入到列表尾部。
LPOP key:移出并获取列表的第一个元素。
RPOP key:移出并获取列表的最后一个元素。
LRANGE key start stop:获取列表在指定范围内的元素。
Set
添加,删除,查找的复杂度都是 O(1)。
SADD key value:向集合添加一个或多个成员。
SREM key value:移除集合中的一个或多个成员。
SMEMBERS key:返回集合中的所有成员。
SISMEMBER key value:判断值是否是集合的成员。
ZSet
Double类型,从小到大的排序。
ZADD key score value:向有序集合添加一个或多个成员,或更新已存在成员的分数。
ZRANGE key start stop [WITHSCORES]:返回指定范围内的成员。
ZREM key value:移除有序集合中的一个或多个成员。
ZSCORE key value:返回有序集合中,成员的分数值。
8. Redis和数据库之间数据同步方案(一致性)
1、读取数据时,先读取redis中的数据,如果redis没有,则从原数据库中读取,并同步更新redis中的数据。写回时,写入到原数据库中,并同步更新到redis中
2、异步队列方式实现同步,可采用消息中间件处理
3、通过数据库插件完成数据同步
4、利用触发器进行缓存同步
9. Redis的数据淘汰算法
1、不淘汰:noeviction,当空间不足时就报错,是系统的默认淘汰策略。
2、设置过期时间的键空间:
2.1、volatile-random:随机移除某个key
2.2、volatile-lru:移除最近没有使用的
2.3、volatile-ttl:ttl值小的key优先淘汰
3、全键空间:
3.1、allkey-random:随机移除某个key
3.2、allkey-lru:移除最近没有使用的
10. Redis过期key的删除策略
1、定时删除:设置过期时间同时,为key创建一个定时器(内存友好,cpu不友好)
2、惰性删除:对输入键进行检查是否过期;如果已经过期,则删除键(内存不友好,cpu友好)
3、定期删除:定时和惰性的折中;规定时间内,分多次遍历服务器各个数据库,从过期字典中随机检查一部分键的过期时间,并删除其中的过期键(减少对CPU的影响,减少内存浪费;操作时间频繁或过长,会退化成定时删除策略;操作次数太少获时间过短,会退化成惰性策略)
Redis是key-value型数据库,可以设置key的过期时间。在Redis中的过期策略有以下三种:
①定时删除: 每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。
优点:保证内存被尽快释放;
缺点:若过期key很多,会需要占用大量CPU资源去处理过期数据,从而影响读取缓存的响应时间。
②惰性删除: 只有当访问这个key的时候,才会判断key是否过期,过期就删除。
优点:节省CPU资源;
缺点:若出现大量过期的key没有被访问,会占用大量内存;
③定期删除: 每隔一段时间,扫描一定数量设置了过期时间的key,并清除其中过期的key。
定期删除的性能介于定时删除和惰性删除之间。在内存占用方面,定期删除不如定时删除好;在CPU占用方面,定期删除不如惰性删除好。
为啥不扫描全部设置了过期时间的key呢?
假如Redis里面所有的key都有过期时间,都扫描一遍?那太恐怖了,而且我们线上基本上也都是会设置一定的过期时间的。全扫描跟你去查数据库不带where条件不走索引全表扫描一样,100s一次,Redis累都累死了。
Redis采用的key过期策略:
11. Redis常见问题
一、缓存雪崩
(一)是什么
一段时间内本应在redis缓存中处理的大量请求,都发送到了数据库进行处理,导致对数据库的压力迅速增大,严重时甚至可能导致数据库崩溃,从而导致整个系统崩溃,就像雪崩一样,引发连锁效应,所以叫缓存雪崩。
(二)为什么
出现上述情况的常见原因主要有以下两点:
1、大量缓存数据同时过期,导致本应请求到缓存的需重新从数据库中获取数据。
2、redis本身出现故障,无法处理请求,那自然会再请求到数据库那里。
(三)怎么办
针对大量缓存数据同时过期的情况:
实际设置过期时间时,应当尽量避免大量key同时过期的场景,如果真的有,那就通过随机、微调、均匀设置等方式设置过期时间,从而避免同一时间过期。
1、添加互斥锁,使得构建缓存的操作不会在同一时间进行。
2、双key策略,主key是原始缓存,备key为拷贝缓存,主key失效时,可以访问备key,主key缓存失效时间设置为短期,备key设置为长期。
3、后台更新缓存策略,采用定时任务或者消息队列的方式进行redis缓存更新或移除等。
针对redis本身出现故障的情况:
在预防层面,可以通过主从节点的方式构建高可用的集群,也就是实现主Redis实例挂掉后,能有其他从库快速切换为主库,继续提供服务。
如果事情已经发生了,那就要为了防止数据库被大量的请求搞崩溃,可以采用服务熔断或者请求限流的方法。当然服务熔断相对粗暴一些,停止服务直到redis服务恢复,请求限流相对温和一些,保证一些请求可以处理,不是一刀切,不过还是看具体业务情况选择合适的处理方案。
二、缓存击穿
(一)是什么
缓存击穿一般出现在高并发系统中,是大量并发用户同时请求到缓存中没有但数据库中有的数据,也就是同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大。和缓存雪崩不同的是,缓存击穿指并发查同一条数据,缓存雪崩是不同数据都过期了,很多数据都查不到从而查数据库。
(二)为什么
这种情况其实一般出现的原因就是某个热点数据缓存过期,由于是热点数据,请求并发量又大,所以过期的时候还是会有大量请求同时过来,来不及更新缓存就全部打到数据库那边了。
(三)怎么办
针对这种情况有两种常见的处理方案:
1、简单粗暴的对热点数据不设置过期时间,这样不会过期,自然也就不会出现上述情况了,如果后续想清理,可以通过后台进行清理。
2、添加互斥锁,即当过期之后,除了请求过来的第一个查询的请求可以获取到锁请求到数据库,并再次更新到缓存中,其他的会被阻塞住,直到锁被释放,同时新的缓存也被更新上去了,后续请求又会请求到缓存上,这样就不会出现缓存击穿了。
三、缓存穿透
(一)是什么
缓存穿透是指数据既不在redis中,也不在数据库中,这样就导致每次请求过来的时候,在缓存中找不到对应key之后,每次都还要去数据库再查询一遍,发现数据库也没有,相当于进行了两次无用的查询。这样请求就可以绕过缓存直接查数据库,如果这个时候有人想恶意攻击系统,就可以故意使用空值或者其他不存在的值进行频繁请求,那么就会对数据库造成比较大的压力。
(二)为什么
这种现象的原因其实很好理解,业务逻辑里面如果用户对某些信息还没有进行相应的操作或者处理,那对应的存放信息的数据库或者缓存中自然也就没有相应的数据,也就容易出现上述问题。
(三)怎么办
针对缓存穿透,一般有以下三种处理方案:
1、非法请求的限制,主要是指参数校验、鉴权校验等,从而一开始就把大量的非法请求拦截在外,这在实际业务开发中是必要的手段。
2、缓存空值或者默认值,如果从缓存取不到的数据,在数据库中也没有取到,那我们仍然把这个空结果进行缓存,同时设置一个较短的过期时间。通过这个设置的默认值存放到缓存,这样第二次到缓存中获取就有值了,而不会继续访问数据库,可以防止有大量恶意请求是反复用同一个key进行攻击。
3、使用布隆过滤器快速判断数据是否存在。那什么是布隆过滤器呢,简单来说,就是可以引入了多个相互独立的哈希函数,保证在给定的空间和误判率下,完成元素判重。因为我们知道,存在hash碰撞这样一种情况,那如果只使用一个hash函数,则碰撞冲突的概率明显会变大,那为了减少这种冲突,我们可以多引入几个hash函数,而布隆过滤器算法的核心思想就是利用多个不同的hash函数来解决这样一种冲突。它的优点是空间效率高,查询时间短,远超其他算法,而它的缺点就是会存在一定的误识别率,它不能完全保证请求过来的key,通过布隆过滤器的校验,就一定有这个数据,毕竟理论上还是会存在冲突情况,无论概率多小。但是,只要没有通过布隆过滤器的校验,那么这个key就一定不存在,只要利用这一点其实就已经可以过滤掉大部分不存在的key的请求了,在正常场景下已然足够了。
四、缓存预热和缓存降级
除了上述三种常见的Redis缓存异常问题之外,还经常听到的有缓存预热和缓存降级两个名词,与其说是异常问题,不如说是两种的优化处理方法。
(一)缓存预热
缓存预热就是系统上线前后,将相关的缓存数据直接加载到缓存系统中去,而不依赖用户。这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题。用户直接查询事先被预热的缓存数据,这样可以避免那么系统上线初期,对于高并发的流量,都会访问到数据库中, 对数据库造成流量的压力。根据数据不同量级,可以有以下几种做法:
数据量不大:项目启动的时候自动进行加载。
数据量较大:后台定时刷新缓存。
数据量极大:只针对热点数据进行预加载缓存操作。
(二)缓存降级
缓存降级是指当缓存失效或缓存服务出现问题时,为了防止缓存服务故障,导致数据库跟着一起发生雪崩问题,所以也不去访问数据库,但因为一些原因,仍然想要保证服务还是基本可用的,虽然肯定会是有损服务。因此,对于不重要的缓存数据,我们可以采取服务降级策略。一般做法有以下两种:
直接访问内存部分的数据缓存。
直接返回系统设置的默认值。
![图片[1]-软考系统架构师之案例分析篇(Redis相关概念)-IT谷](http://itgu.com/wp-content/uploads/2025/05/de180266d77fd873512bf8671c83217b-1024x576.png)
2 以上提供的代码或者素材均为作者提供和网友推荐收集整理而来,仅供学习和研究使用;
3 若作商业用途,请联系原作者授权,若本站侵犯了您的权益请 联系站长 进行删除处理;
暂无评论内容