Logo
Sep 29, 2022

Redis

Redis 是什么?

Redis 本质上是一个 Key-Value 类型的内存数据库,很像 memcached,整个数据库统统加载在内存当中进行操作。

因为是纯内存操作,Redis 的性能非常出色,每秒可以处理超过 10 万次读写操作,是已知性能最快的 Key-Value DB。

Redis 可以用来实现很多有用的功能:

  1. 用它的 List 来做 FIFO 双向链表,实现一个轻量级的高性能消息队列服务

  2. 用它的 Set 可以做高性能的 tag 系统

  3. Redis 也可以对存入的 Key-Value 设置 expire 时间,因此也可以被当作一 个功能加强版的 memcached 来用

使用 redis 有哪些好处?

速度快,因为数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是 O (1)

支持丰富数据类型,支持 string,list,set,zset,hash

支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行

丰富的特性:可用于缓存,消息,按 key 设置过期时间,过期后将会自动删除

Memcached 与 Redis 的区别都有哪些?

  1. 存储方式: Memcached 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis 有部份存在硬盘上,这样能保证数据的持久性。

  2. 数据支持类型: Memcached 对数据类型支持相对简单。 Redis 有复杂的数据类型。

redis 相比 memcached 有哪些优势?

  1. memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型

  2. redis 的速度比 memcached 快很多

  3. redis 可以持久化其数据

为什么用 redis

假如用户第一次访问数据库中的某些数据。这个过程会比较慢,因为是从硬盘上读取的。将该用户访问的数据存在数缓存中,这样下一次再访问这些数据的时候就可以直接从缓存中获取了。操作缓存就是直接操作内存,所以速度相当快。如果数据库中的对应数据改变的之后,同步改变缓存中相应的数据即可!

直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据库中的部分数据转移到缓存中去,这样用户的一部分请求会直接到缓存这里而不用经过数据库。

Redis 的持久化机制是什么?各自的优缺点?

RDB:是 Redis DataBase 缩写快照

RDB 是 Redis 默认的持久化方式。按照一定的时间将内存的数据以快照的形式保存到硬盘中,对应产生的数据文件为 dump.rdb。通过配置文件中的 save 参数来定义快照的周期。

  1. 只有一个文件 dump.rdb,方便持久化。

  2. 容灾性好,一个文件可以保存到安全的磁盘

AOF:持久化:

AOF 持久化 (即 Append Only File 持久化),则是将 Redis 执行的每次写命令记录到单独的日志文件中,当重启 Redis 会重新将持久化的日志中文件恢复数据。

Redis 的过期策略和内存淘汰机制

过期策略

redis 采用的是定期删除 + 惰性删除策略

定期删除,redis 默认每个 100ms 检查,是否有过期的 key, 有过期 key 则删除。需要说明的是,redis 不是每个 100ms 将所有的 key 检查一次,而是随机抽取进行检查 (如果每隔 100ms, 全部 key 进行检查,redis 岂不是卡死)。因此,如果只采用定期删除策略,会导致很多 key 到时间没有删除。

于是,惰性删除派上用场。也就是说在你获取某个 key 的时候,redis 会检查一下,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除。

内存淘汰机制

如果定期删除没删除 key。然后你也没即时去请求 key,也就是说惰性删除也没生效。这样,redis 的内存会越来越高。那么就应该采用内存淘汰机制。 在 redis.conf 中有一行配置

# maxmemory-policy volatile-lru

该配置就是配内存淘汰策略的

  1. noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。应该没人用吧。

  2. allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 key。推荐使用,目前项目在用这种。

  3. allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 key。应该也没人用吧,你不删最少使用 Key, 去随机删。

  4. volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 key。这种情况一般是把 redis 既当缓存,又做持久化存储的时候才用。不推荐

  5. volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 key。依然不推荐

  6. volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key 优先移除。不推荐

Redis 主要消耗什么物理资源?

内存

Redis 的内存用完了会发生什么?

如果达到设置的上限,Redis 的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以配置内存淘汰机制,当 Redis 达到内存上限时会冲刷掉旧的内容。

缓存穿透和缓存雪崩

缓存穿透

缓存穿透,即黑客故意去请求缓存中不存在的数据,导致所有的请求都怼到数据库上,从而数据库连接异常。

缓存雪崩

即缓存同一时间大面积的失效,这个时候又来了一波请求,结果请求都怼到数据库上,从而导致数据库连接异常。 使缓存集中失效的原因:

  1. redis服务器挂掉了。

  2. 对缓存数据设置了相同的过期时间,导致某时间段内缓存集中失效。

如何解决缓存集中失效:

  1. 针对原因1,可以实现redis的高可用,Redis Cluster 或者 Redis Sentinel(哨兵) 等方案。

  2. 针对原因2,设置缓存过期时间时加上一个随机值,避免缓存在同一时间过期。

  3. 使用双缓存策略,设置两个缓存,原始缓存和备用缓存,原始缓存失效时,访问备用缓存,备用缓存失效时间设置长点。

MySQL 里有 2000w 数据,Redis 中只存 20w 的数据,如何保证 Redis 中的数据都是热点数据

redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略(回收策略)。 可以设置成最近最少使用的数据淘汰。