Redis(Remote Dictionary Server)是一个开源的内存数据库,主要用于高速存取数据,常用作缓存、消息队列、会话存储等。它支持键值对存储,并提供多种数据结构,如**字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)**等。
1.Redis 的基本数据结构类型
1.1 Redis 的五种基本数据类型
(1)String(字符串)
-
概述:Redis 最基本的数据类型,存储单个键值对,值可以是字符串、数字。
-
命令:
-
SET key value—— 设置值 -
GET key—— 获取值 -
INCR key/DECR key—— 递增/递减(适用于计数) -
APPEND key value—— 追加字符串
-
-
应用场景:
-
缓存用户信息(如
SET user:1:name "Alice") -
计数(如
INCR views:page1记录页面浏览量)
-
(2)Hash(哈希)
-
概述:类似于 Python 的字典,一个键值对可以包含多个字段,每个字段存储一个值。
-
命令:
-
HSET key field value—— 设置字段值 -
HGET key field—— 获取字段值 -
HGETALL key—— 获取所有字段和值
-
-
应用场景:
-
存储用户信息,如:
-
shell
-
CopyEdit
-
HSET user:1 name "Alice" age "25" -
适用于对象存储,节省空间(相比多个
String结构)
-
(3) List(列表)
-
概述:双向链表,可以用作队列(FIFO) 或 栈(LIFO) 结构。
-
命令:
-
LPUSH key value—— 左侧插入(类似栈) -
RPUSH key value—— 右侧插入(类似队列) -
LPOP key/RPOP key—— 弹出左/右端的元素 -
LRANGE key start stop—— 获取指定范围的元素
-
-
应用场景:
-
消息队列(生产者
RPUSH,消费者LPOP) -
任务列表(如异步任务处理)
-
(4) Set(集合)
-
概述:无序、不重复集合,适用于去重和求交/并/差集运算。
-
命令:
-
SADD key value—— 添加元素 -
SMEMBERS key—— 获取集合中的所有元素 -
SISMEMBER key value—— 判断某元素是否存在 -
SINTER key1 key2/SUNION key1 key2/SDIFF key1 key2—— 交集/并集/差集
-
-
应用场景:
-
社交网络好友列表(如
SINTER user:1:friends user:2:friends获取共同好友) -
防止重复(如
SADD ip_blacklist "192.168.1.1")
-
(5) Sorted Set(有序集合)
-
概述:类似
Set,但每个元素都有一个分数(score),支持排序。 -
命令:
-
ZADD key score value—— 添加元素并指定分数 -
ZRANGE key start stop [WITHSCORES]—— 按分数排序后取值 -
ZREVRANGE key start stop—— 逆序获取 -
ZRANK key value—— 获取某元素的排名
-
-
应用场景:
-
排行榜(如存储游戏分数
ZADD leaderboard 100 "Alice") -
限流(记录最近访问的用户)
-
1.2 Redis 的三种特殊数据类型
(1)HyperLogLog(基数统计)
-
概述:用于基数统计(近似去重),比
Set更节省内存,但不是 100% 精确。 -
命令:
-
PFADD key value—— 添加元素 -
PFCOUNT key—— 获取基数
-
-
应用场景:
-
统计 UV(Unique Visitor)(如
PFADD uv_counter user1)
-
(2)Bitmaps(二进制位图)
-
概述:用于存储二进制数据,可实现布隆过滤器等功能。
-
命令:
-
SETBIT key offset value—— 设置某个位 -
GETBIT key offset—— 获取某个位
-
-
应用场景:
-
签到系统(如
SETBIT sign:20250301 user1 1记录用户是否签到) -
大规模用户状态跟踪
-
(3) Streams(流数据)
-
概述:Redis 5.0 引入的新数据结构,适用于消息队列和日志系统。
-
命令:
-
XADD key * field value—— 添加消息 -
XRANGE key start end—— 读取消息 -
XREAD COUNT count STREAMS key start_id—— 读取最新消息
-
-
应用场景:
-
日志存储
-
实时数据分析
-
异步任务处理
-
| 数据结构 | 主要特点 | 典型应用 |
| String | 单值存储 | 缓存、计数 |
| Hash | 键值对集合 | 对象存储 |
| List | 有序列表 | 消息队列、任务调度 |
| Set | 无序唯一元素 | 去重、交集并集计算 |
| Sorted Set | 带排序的集合 | 排行榜、限流 |
| HyperLogLog | 近似去重 | 统计 UV |
| Bitmaps | 位存储 | 用户状态、签到 |
| Streams | 消息流 | 日志、数据流处理 |
2.Redis 为什么这么快?
2.1 基于内存存储实现
2.2 高效的数据结构:跳表等数据结构。
2.3 合理的数据编码
Redis 支持多种数据类型,每种基本类型,可能对应多种数据结构。什么时候、使用什么样数据结构,使用什么样编码,是 Redis 设计者总结优化的结果。
2.4 合理的线程模型
-
IO 多路复用:其实就是一种同步 IO 模型,它实现了一个线程可以监视多个文件句柄;一旦某个文件句柄就绪,就能通知应用程序进行相应的读写操作;而没有文件句柄就绪时,就会阻塞应用程序,交出 CPU。
-
单线程模型:Redis 是单线程模型的,而单线程避免了 CPU 不必要的上下文切换和竞争锁的消耗。也正因为是单线程,如果某个命令执行过长(如
hgetall命令),会造成阻塞。Redis 是面向快速执行场景的数据库,所以要慎用如smembers、lrange、hgetall等命令。 -
Redis 6.0 引入了多线程提速,它的执行命令操作内存的仍然是个单线程。
2.5 虚拟内存机制
Redis 直接自己构建了 VM 机制,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求。
3.什么是缓存击穿、缓存穿透、缓存雪崩?
3.1 缓存穿透问题
先来看一个常见的缓存使用方式:请求来了,先查缓存,缓存有值命中,就直接返回;缓存没有值,就去数据库查询,然后把数据的值更新到缓存,再返回。
缓存穿透:指查询一个一定不存在的数据,由于缓存是不会命中而需要从数据库查询,若查询的数据同样不存在,这将导致这个不存在的数据每次请求都需要到数据库去查询,进而给数据库带来压力。
通常来说,缓存访问时,缓存和数据库都没有这个值,这种情况会导致每次这个值的查询请求都会到数据库,形成缓存穿透。
缓存穿透的典型例子:查询一个数据库中本身不存在的 ID。
一般来说,缓存的 key 是有较多的字段进行保护的,但是你的这个请求命中缓存,查询这个 userid 查询有没有存护。
业务/运维/开发误的操作,比如缓存和数据库的数据都被误删除了。
黑客非法请求攻击,比如黑客故意造大量非法请求,以读取不存在的业务数据。
如何避免缓存穿透呢? 一般有三种方法:
如果是黑非法请求,我们在 API 入口,对参数进行校验,过滤非法值。
-
如果查询的数据为空,我们可以给缓存一个空值,或者默认值。但是只有写请求进来的话,需要更新缓存, 以保证缓存一致性,同时,最后给缓存设置 适当的过期时间。(业务上比较常用,简单有效)
-
使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
3.2 缓存雪崩问题
缓存雪崩:指缓存中数据大批量过期时间,查询数据量巨大,请求都直接查询数据库,引起数据库压力太大甚至 down 机。
缓存雪崩一般是由于 大量数据同时过期 造成的,对于这个问题,可以 均匀设置过期时间 解决,即让数据的过期时间相对离散一点。
另一种情况可能引起缓存雪崩,这就需要构造 Redis 高可用集群。
3.3 缓存击穿问题
缓存击穿:指热点 key 在某个时间点过期的时候,而恰好在这个时间点对这个 key 有大量的并发请求过来,从而大量的请求打到数据库。
缓存击穿看着有点像服务器雪崩,其实它有两个区别是,服务器雪崩是指数据库压力过大甚至宕机,服务器击穿只是大量并发请求到了DB数据库面积。可以认为击穿是服务器雪崩的一个子集吧。
解决方案有两种:
1.使用互斥锁方案。服务器失效时,不是立即去加载数据库数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载数据库数据并设置服务器。否则就去重试获取服务器。
2.“永不过期”,是指不设置过期时间,但数据热点要快过期时间,异步线程去更新并设置过期时间。
4.什么是热点关键问题,如何解决热点关键问题
4.1 何为热点问题?
在Redis等服务器系统中,热点Key是指形成被集群访问的按键(Key)。当大量请求集中访问一个或少数几个Key时,就会出现热点Key。这种情况可能会导致:
-
服务器资源耗尽:由于请求量过大,导致Redis服务器的CPU、内存或网络带宽被大量消耗,甚至出现宕机。
-
性能瓶颈:热点Key所在的Redis节点成为性能瓶颈,影响整个系统的响应速度。
4.2 热点关键问题的产生原因:
-
读多写一些场景:例如,电商秒杀活动、热门新闻、明星事件等,这些场景下面,大量用户集中采集大量数据。
-
请求分片不均:如果请求分片策略导致大量请求集中到同一个Redis节点,同样会产生热点关键问题。
4.3 如何解决热点关键问题?
针对关键热点问题,可以采取以下几种解决方案:
-
Redis 服务器扩展功能:
-
通过增加Redis集群的分片副本,将读取请求分散到多个节点,实现负载均衡。
-
-
热键分散:
-
将热Key的数据分散存储到不同的Redis节点,例如,通过在Key中添加随机后缀,将请求分散到不同的分片。
-
-
缓存:
-
在应用程序本地(例如,JVM内存)设置缓存,将热键的数据缓存放在本地,减少对Redis的访问。
-
-
热点数据预热:
-
在热点事件发生前,提前将热点数据加载到Redis存储中,避免大量请求同时访问数据库。
-
-
流量限制:
-
通过限流措施,限制对热点关键的访问频率,防止过多的请求压垮Redis服务器。
-
5.Redis 过期策略和内存淘汰策略
5.1 Redis 过期策略
-
作用:
-
Redis 过渡用于策略删除已经过渡的键值对,释放内存空间。
-
它确保过期的数据不会一直占用内存,保持Redis的高效运行。
-
-
策略:
-
提名人:
-
当客户端尝试访问一个已过期的键时,Redis 会检查该键是否过期。
-
如果边界,则删除该键,并返回空值。
-
该策略的优点是节省CPU资源,缺点是可能存在大量的过渡但配备访问的键,占用内存。
-
-
定期休假:
-
Redis会默认定期(每秒10次)随机回收一些设置了过期时间的键,检查它们是否过期。
-
如果边界,则删除这些键。
-
策略可以弥补删除的不足,但不能保证所有过渡键都被及时删除。
-
-
5.2 Redis 内存淘汰策略
-
作用:
-
Redis内存限制淘汰策略用于在Redis内存达到最大时,删除部分键值对,释放内存空间。
-
它保证Redis在内存不足时,能够继续正常运行。
-
-
策略:
-
禁止驱逐:
-
当内存不足时,不删除任何键,所有写操作都会返回错误。
-
-
allkeys-lru:
-
删除最近最少使用的键。
-
-
allkeys-lfu:
-
删除最不经常使用的键。
-
-
allkeys-随机:
-
随机删除一些键。
-
-
挥发性-lru:
-
删除设置了中间时间的键中,最近最少使用的键。
-
-
挥发性-lfu:
-
删除设置了中间时间的键中,最不经常使用的键。
-
-
挥发性TTL:
-
删除设置了中间时间的键中,剩余时间最短的键。
-
-
挥发性随机:
-
随机删除设置了中间时间的键。
-
-
6.Redis的常用应用场景
6.1 缓存
-
网页索引:
-
将常用的网页内容缓存到Redis中,减少数据库的访问次数,提高网页的响应速度。
-
-
API缓存:
-
缓存 API 的响应结果,减少服务的压力。
-
-
对象索引:
-
存储常用的Java对象、Python对象等,提高应用程序的性能。
-
6.2 会话管理
-
网站会话:
-
将的用户会话信息(如登录状态、购物车内容等)存储在Redis中,实现会话共享和持久化。
-
-
议题讨论:
-
在各地系统中,利用Redis集中管理会话信息,实现跨服务器的会话共享。
-
6.3 计数器
-
网页版本:
-
统计网页的访问次数、点赞数、评论数等。
-
-
API查询:
-
限制API的调用次数,防止恶意攻击。
-
-
秒杀计数器:
-
在秒杀活动中,统计商品的剩余数量。
-
6.4 排行榜
-
热门排行榜:
-
根据用户的点击量、评论量等,生成热门排行榜。
-
-
游戏排行榜:
-
记录游戏玩家的得分、排名等。
-
-
社交排行榜:
-
显示用户粉丝数、关注数等。
-
6.5 分布式锁
-
实现互斥:
-
在多个系统中,使用Redis实现互斥锁,保证同一只有一个线程或进程时刻可以访问共享资源。
-
-
防止重复提交:
-
在处理用户提交的请求时,使用Redis锁防止重复提交。
-
6.7 消息排队
-
异步处理:
-
将一些运行的任务放入Redis队列中,异步处理,提高系统的响应速度。
-
-
发布/订阅:
-
实现消息的发布和订阅,用于实时消息主体、事件通知等。
-
6.8 社交网络
-
用户关系:
-
存储用户的关注关系、好友关系等。
-
-
时间线:
-
显示发布用户的内容、好友的动态等。
-
6.9 地理空间数据
-
附近地点搜索:
-
搜索附近的用户、商家、地点等。
-
-
地理围栏:
-
监控用户或设备的断路,触发相应的事件。
-
7.Redis的持久化机制有哪些优点?
Redis 是基于内存的非类型 KV 数据库,既然它是基于内存的,如果 Redis 服务器关系挂了,数据就会丢失。为了避免数据丢失,Redis 提供了持久化,即把数据保存到磁盘上。Redis 提供了 RDB 和 AOF 两种持久化机制。
7.1 RDB(Redis DataBase)持久化
-
优点:
-
适合大规模数据恢复: RDB文件是紧凑的二进制快照,适合用于备份和全数据量恢复。
-
恢复速度快:相对于AOF,RDB恢复速度更快,因为它是数据的二进制快照,直接加载到内存中。
-
对性能影响较小: Redis可以通过创建子进程(bgsave)来进行RDB持久化,对主进程的影响较小。
-
-
缺点:
-
数据丢失风险: RDB是定时快照,如果在两次快照之间Redis发生故障,则丢失这段时间的数据。
-
实时性差: RDB无法实现实时持久化,只能按照预设的时间间隔进行。
-
新旧版本存在RDB格式兼容问题:在不同的Redis版本中,RDB文件的格式可能会存在差异,这会导致在不同版本之间进行数据迁移或恢复时出现兼容性问题。
-
7.2 AOF(Append Only File)持久化
-
优点:
-
数据安全性高: AOF记录了每次写操作,可以实现更细粒度的数据恢复,减少数据丢失的风险。
-
数据一致性好: AOF记录了所有的写操作,可以保证数据的一致性。
-
可以配置不同的同步策略:可以根据需要配置不同的同步策略,如每秒同步、每次写操作同步等。
-
-
缺点:
-
文件体积大: AOF文件会随着写入操作的增加而增大,占用更多的磁盘空间。
-
恢复速度慢:相对于RDB,AOF恢复速度较慢,因为需要重新执行所有写操作。
-
AOF文件过大时,数据恢复变慢:当AOF文件特别大时,redis服务在启动时,需要花费相当长的时间才能完成数据恢复。
-
8.如何实现Redis的高可用性
8.1.主从复制(Master-Slave Replication)
-
原理:
-
主节点(Master)负责处理写操作,将数据同步到从节点(Slave)。
-
从节点负责处理读操作,可以分担主节点的读压力。
-
当主节点发生故障时,可以手动将一个从节点提升为主节点。
-
-
优点:
-
实现读写分离,提高阅读性能。
-
提供数据备份,防止数据丢失。
-
-
缺点:
-
当主节点发生故障时,需要手动进行故障转移。
-
可能存在数据延迟,来自节点的数据可能不是最新的。
-
8.2 哨兵模式(Sentinel)
-
原理:
-
哨兵(Sentinel)是一个独立的进程,用于监控Redis集群的状态。
-
当主节点发生故障时,哨兵会自动将一个从节点提升为主节点。
-
哨兵可以监控多个Redis集群。
-
-
优点:
-
实现故障自动转移,提高可用性。
-
重新導入人工干预。
-
-
缺点:
-
哨兵本身也可能发生故障,需要部署多个哨兵。
-
故障转移需要一定的时间。
-
8.3 集群模式:
-
原理:
-
Redis 集群将数据分片存储在多个节点上。
-
每个节点负责一部分数据的读写。
-
当某个节点发生故障时,集群会自动转向节点的数据迁移到其他节点。
-
-
优点:
-
实现水平扩展,提高性能和容量。
-
提供高可用性和内容错误性。
-
-
缺点:
-
配置和管理相对复杂。
-
总结:
-
对于读多写少的场景,可以使用主从复制。
-
对于需要自动故障转移的场景,可以使用哨兵模式。
-
对于数据量增大、需要水平扩展的场景,可以使用集群模式。
【软件系统架构】系列
| 系统架构设计教程简介 | 【软件系统架构】系列简介-CSDN博客 |
| 【软件系统架构】系列三:数据库系统之一 | 【软件系统架构】系列三:数据库系统之一_内模式映像-CSDN博客 |
| 【软件系统架构】系列三:数据库系统之二 | 【软件系统架构】系列三:数据库系统之二-CSDN博客 |
| 【软件系统架构】系列三:数据库系统之三 | 【软件系统架构】系列三:数据库系统之三-CSDN博客 |
| 【软件系统架构】系列三:数据库系统之四-Redis数据库(1) | https://blog.csdn.net/moton2017/article/details/145990776 |
Redis数据库全面解析与应用

被折叠的 条评论
为什么被折叠?



