【软件系统架构】系列三:数据库系统之四-Redis数据库(1)

Redis数据库全面解析与应用

Redis(Remote Dictionary Server)是一个开源的内存数据库,主要用于高速存取数据,常用作缓存、消息队列、会话存储等。它支持键值对存储,并提供多种数据结构,如**字符串(String)、哈希(Hash)、列表(List)、集合(Set)、有序集合(Sorted Set)**等。

1.Redis 的基本数据结构类型

1.1 Redis 的五种基本数据类型

Redis的5中基本数据类型
Redis的5中基本数据类型

(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 是面向快速执行场景的数据库,所以要慎用如 smemberslrangehgetall 等命令。

  • 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

34号树洞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值