当前位置: 首页 > news >正文

Java常用中间件整理讲解——Redis,RabbitMQ

整理Java后端常用的中间件,描述使用及其思想。

1:Redis

Redis是一个开源的键值存储系统,常用于缓存、消息队列等场景。Redis快的原因是内存操作、非阻塞I/O多路复用,避免了线程切换和竞争。

Redis还提供持久化的方式,以及后续版本的多线程处理IO。Redis的高可用也是重要的技术点。

1:数据结构与类型

支持多种数据结构,以及一些扩展的类型,简单介绍使用和场景,以及底层。后几种是扩展,大致描述下。

1:String

字符串,最常用的数据结构,底层是通过SDS动态字符串存储数据,自动扩容。

直接使用set,get命令默认操作的是字符串,设置键及对应的值,并可设置过期时间。

SET key value [EX seconds] [PX milliseconds]  # 设置值(支持过期时间)
GET key                                      # 获取值
INCR key                                     # 自增计数器
APPEND key value                             # 追加内容
MSET key1 val1 key2 val2                     # 批量设置

适用场景:缓存、计数器、分布式锁等。

分布式锁‌:SET lock_key uuid NX PX 10000(NX:不存在才设置,PX:过期时间)。

2:Hash

哈希,注意不要和Java的哈希搞混了,Redis默认就是键值存储,这里的Hash就是值对应多组,类似Java的Map里面套一个Map。

底层结构是压缩列表(zipList)哈希表(dict),小数据时适用压缩列表。

使用:在语句的操作前面添加一个 H,例如HSet。

HSET key field value       # 设置字段值
HGET key field             # 获取字段值
HGETALL key                # 获取所有字段和值
HDEL key field             # 删除字段
HINCRBY key field 1        # 字段自增

适用场景:对象信息存储,或多个商品详情。

例如:HSET user:1001 name "Alice" age 30

3:List

列表,元素有序,按元素顺序排列。

底层是快速链表(压缩列表加双向链表),支持头尾高效操作。

双向链表结构,可以从两端操作数据。操作左边数据称为栈,添加L。操作右边数据称为队列,添加R。并且支持弹出和阻塞弹出。

LPUSH key value1 value2    # 左端插入(栈)
RPUSH key value1 value2    # 右端插入(队列)
LPOP key                   # 左端弹出
BLPOP key timeout          # 阻塞式左端弹出(用于消息队列)
LRANGE key 0 -1            # 获取全部元素

可以实现消息队列场景,左端插入,右端阻塞式消费数据。以及实现朋友圈最新列表场景。

4:Set

集合,无序‌,元素存储顺序不固定,且元素唯一(不可重复)。

底层结构是整数集合(元素全为整数时),或哈希表。

使用:在语句前面添加 S。

SADD key member1 member2    # 添加元素
SREM key member             # 删除元素
SMEMBERS key                # 获取所有元素(慎用,可能阻塞)
SINTER key1 key2            # 求交集(共同好友)
SUNIONSTORE dest key1 key2  # 并集存储到新集合

可用于统计用户兴趣标签,或去重取交集并集等。

需注意交集/并集操作复杂度高(O(n)),需控制集合大小。

5:ZSet

有序集合,根据元素的 score(分值)排序,score 相同时按字典序排序。

元素唯一,但 score 可重复,支持范围查询和排行榜等。底层是通过跳跃表和哈希表实现高效排序。

使用:在Set命令的基础上,为每个键设置分值,即可实现排序功能。

ZADD key score1 member1 score2 member2  # 添加元素
ZRANGE key 0 -1 WITHSCORES              # 按分值升序获取
ZREVRANGE key 0 9                       # 降序取Top10
ZRANK key member                        # 获取排名
ZRANGEBYSCORE key min max               # 按分值范围查询

是作为Set无序集合的补充,适用于不可重复但有序场景,例如用户排行榜等。

跳跃表查询时间复杂度为O(log n),适合高频读场景。

6:位图

本质上是字符串的二进制位操作。使用命令为 set/getbit,后面用法一样,指定键和值。

SETBIT key offset 1        # 设置二进制位(0或1)
GETBIT key offset          # 获取位值
BITCOUNT key               # 统计1的个数(日活统计)
BITOP OR dest key1 key2    # 位运算(用户行为分析)

适用于用户的签到,以及唯一状态标记等场景。

7:地理空间

基于ZSet实现,存储经纬度。使用为 GEO 开头的命令。

GEOADD key longitude latitude member  # 添加地理位置
GEODIST key member1 member2           # 计算距离
GEORADIUS key lon lat radius unit     # 查询附近的人

可实现附近商家,打车距离等运算,但一般会在代码中做。

8:流

Stream,特点是支持多消费者组的消息队列,类似MQ。使用为X开头的命令。

XADD key * field1 value1      # 添加消息(*自动生成ID)
XREAD COUNT 10 STREAMS key 0  # 读取消息
XGROUP CREATE key group1 0     # 创建消费者组
XACK key group1 id            # 确认消息处理

可在Redis实现消息的收发机制,异步队列的处理,日志收集等。

2:持久化机制

Redis的持久化是保障数据安全的核心功能,提供了RDB(快照)AOF(日志追加)混合持久化三种方式,各有其不同的设计理念。

1:RDB

Redis Database,快照机制,核心原理是通过 fork 子线程生成内存数据的二进制压缩快照。

简单来说就是,将某个时间点的所有数据都存放在硬盘上,可以将快照(文件)复制到其他服务器,从而创建副本,恢复数据。如果系统故障,会丢失最后一次创建快照之后的数据。

有两种方式方式:

  1. 手动触发:通过 SAVE(生产禁用,阻塞主线程)命令,或 BGSAVE(后台异步生成)。
  2. 自动触发:通过配置文件自动触发,例如save 900 1,表示900秒内至少修改一次则触发。

其还有一个关键特点:写时复制,父进程与子进程共享内存页,仅当数据修改时复制内存页,避免全量内存拷贝。

优点:

  1. 二进制文件直接加载到内存,恢复速度快。
  2. 文件体积小,适合全量备份与灾难恢复。
  3. 后台异步生成快照,主线程仅在 fork 时有短暂阻塞,性能和体验较好。

缺点:

  1. 两次快照之间的内容可能丢失,依赖于触发频率。
  2. 会有大内存问题(写时复制通病),fork子线程时内存占用翻倍,对硬件有要求。

2:AOF

Append-Only File,日志追加机制,核心原理是记录所有‌写操作命令‌(如SET、HSET),以文本协议格式追加到AOF文件末尾,通过策略控制数据写入磁盘,同步数据。

首先,对文件进行写入会先存储进缓冲区,然后根据策略 appendfsync 决定同步磁盘的时机。提供了三个同步选项:

  1. always:每次写命令后同步(数据安全,性能最低),严重降低服务器性能。
  2. everysec(默认):每秒批量同步(折中方案),保证崩溃时丢失一秒左右的数据,且性能几乎无影响。
  3. no:由操作系统决定(性能最高,可能丢失约30秒数据),一般在AOF关闭或Redis关闭时执行。

AOF还提供了一个重写机制,目的是解决AOF文件膨胀问题,同样可通过手动触发和自动触发的方式实现。

实现原理为:fork子线程遍历内存数据,生成新的紧凑AOF文件。重写期间的新命令写入‌AOF重写缓冲区‌,重写完成后追加到新AOF文件。

重写期间的新命令同时写入‌AOF缓冲区‌和‌AOF重写缓冲区‌。若重写失败,原始AOF文件仍完整。

AOF的优点:安全性高,默认最多丢失一秒数据,并且文本可读性强,便于维护和扩展。

缺点:相同数据集下,AOF文件通常比RDB文件大数倍。且需要逐行执行命令,耗时较长。

3:混合持久化

Redis 4.0+引入,结合RDB快照与AOF增量日志的方式实现。

通过命令 aof-use-rdb-preamble yes 开启:AOF重写时先生成RDB快照,再追加重写期间的AOF日志。

文件结构为:[RDB快照数据] + [AOF增量命令],恢复数据时,优先加载RDB快照恢复基础数据,再通过AOF日志恢复增量数据。

优点:

  1. 兼顾RDB的快速恢复与AOF的数据安全性。
  2. 文件体积比纯AOF更小,恢复速度比纯AOF更快。
  3. 生产环境推荐方案,尤其对数据安全与恢复速度均有要求的场景。

生产上可通过监控 fork 耗时,进行持久化优化,以及定时备份文件到异地,测试宕机恢复等。

3:三大问题

缓存使用中的三个问题,场景描述及解决方式。

1:缓存穿透

这个问题和另外两个不属于同一类,可以先描述。

定义:当一个请求从缓存中取数据时,如果请求的key在缓存中不存在,就会绕过缓存,直接请求数据库。如果数据库返回null,又不会写入缓存。

这样会导致多次请求反复查询数据库,引发数据库压力。

解决:

1:使用布隆过滤器,查询前先通过布隆过滤器检查,如果返回不存在则直接拒绝请求,返回可能存在(可能误判)时,再查缓存或数据库。

2:将查询结果为空的键也缓存起来,并设置较短的过期时间。但是需避免空值过多占用内存。

3:对接口增加校验、限流等,对请求参数检验过滤。

2:缓存击穿

定义:某个‌热点Key‌在高并发场景下突然过期,大量请求直接穿透到数据库,导致数据库瞬时压力激增。

与穿透的区别是,发生问题前,缓存中有键值数据。

解决:

1:热点key设置为永不过期,在业务代码中判断是否更新时间。

2:实现互斥锁,只允许一个线程重建缓存,其他线程阻塞等待,需避免死锁。

3:热点数据预加载,监控热点key(如Redis的hotkeys),在即将过期时,主动刷新缓存避免击穿。

3:缓存雪崩

定义:大量缓存数据‌同时过期‌或缓存服务宕机,导致所有请求直接访问数据库,引发数据库崩溃。

注意与击穿的区别是:大量 Key 同时失效。

原因可能是同一时间给多个key设置相同过期时间,或集群宕机、网络中断等。

解决:

1:分散设置过期时间,例如在同一时间,给多个key设置指定范围随机数过期时间。

2:同样的将缓存设置永不过期,在业务代码中更新缓存。

3:接口处添加熔断降级配置,数据库压力过大时,直接返回提示或错误页面。

4:高可用架构

高可用是指Redis在生产环境,保证程序的稳定和正确性,其实这个思想和Mysql这些都是一样的。

1:主从复制

主从复制是 Redis 高可用的基础,通过数据冗余实现读写分离和故障恢复,说白了就是启动多个Redis不同端口服务,指定服务分别干哪些事情。

1:定义主节点( Master)和从节点(Slave)。

  • 主节点负责写操作,并异步同步数据到从节点。
  • 从节点负责读操作,接收主节点同步的数据。

2:全量同步,首次连接会触发。

  • 从节点发送 PSYNC 命令请求同步。
  • 主节点执行 BGSAVE 生成RDB快照,发送给从节点。
  • 从节点清空旧数据,加载RDB文件。
  • 最后,主节点会将同步期间的命令存入缓冲区,RDB传输完成后发送缓冲区命令。

3:增量同步,断线重连等场景。

  • 从节点发送PSYNC命令并携带复制偏移量(offset)。
  • 主节点检查复制缓冲区是否包含该偏移量之后的命令,如果存在,则只传输缓冲区命令。如果不存在,则触发全量同步。

‌优点‌:简单易用,支持读写分离,提升读性能。

缺点‌:主节点单点故障,需配合哨兵或集群实现高可用。

2:哨兵机制

哨兵是 Redis 官方推荐的‌故障自动转移系统‌,用于监控主从节点并实现主节点故障转移。

核心特性是定期监控主从节点健康状态,主节点宕机时选举新的主节点,客户端通过哨兵获取到最新的主节点地址。

注意哨兵可以配置多个,并且可指定几个哨兵控制选举,称为主观下线和客观下线

转移流程:

1:先触发主观下线,即单个哨兵认为主节点不可用。

2:进一步触发客观下线,超过半数哨兵确认主节点不可用。

3:通过 Raft 算法选举 Leader 哨兵。

4:选择新的主节点,会先过滤掉已下线的从节点,进一步选择优先级高、偏移量小、ID小的从节点。

5:进入切换流程,将选中的从节点升级为主节点,向其他从节点发送REPLICAOF命令,指向新主节点。并通知客户端更新主节点地址。


‌优点‌:自动故障转移,客户端透明切换。

‌缺点‌:写操作仍集中在单主节点,无法水平扩展写性能(类似MySQL的水平分表,治标不治本)。

3:集群架构

Redis 集群是分布式解决方案,通过分片(Sharding)实现数据水平拆分和负载均衡。即部署多个Redis服务。

核心特性:

  • 哈希槽:集群将数据划分为 16384 个槽,每个节点负责部分槽(好类似G1垃圾回收)。key通过公式计算所属槽。
  • 节点角色优化,主节点处理槽数据读写,从节点复制主节点数据,故障时替代主节点。

类似公司的分片机制,客户端缓存槽与节点(Redis服务)映射关系,直接请求目标节点。

故障转移需要与哨兵协作,当主节点下线时,从节点自动晋升为主节点(需多数主节点确认)。而当半数主节点或某一个槽下的主从节点均下线时,表示当前集群不可用。

扩容与缩容‌:

扩容流程:添加新节点,然后执行 CLUSTER MEET加入集群,再通过命令迁移槽数据。

‌缩容流程‌:迁移待下线节点的槽到其他节点,执行CLUSTER FORGET移除节点。


‌优点‌:数据分片、负载均衡、高可用性(无需额外哨兵)。

‌缺点‌:配置复杂,跨槽操作不支持(需使用Hash Tag)。

集群模式下数据一致性问题:

异步复制下可能丢失数据,需权衡一致性与性能。
同步写入(WAIT命令)强制等待从节点确认,但牺牲性能。

使用建议:数据量 < 单机内存时,选择主从+哨兵。数据量 > 单机内存时,考虑集群。

5:高级特性

1:LUA脚本 。。。

http://www.dtcms.com/a/523746.html

相关文章:

  • JavaEE初阶7.0
  • 从“天书”到源码:HarmonyOS NEXT 崩溃堆栈解析实战指南
  • 个人网站收款google play 应用商店
  • _撸猫websocket服务器端,手机远程服务端
  • 【论文精读】FDGaussian:基于几何感知扩散模型的单图快速高斯溅射 3D 重建
  • 功防世界-Web-bug
  • 做网站能拿多少钱平面设计 网站推荐
  • REST介绍,实质,六大约束,优缺点(数据冗余问题,身份验证困难(解决方式 -- JWT+集中式认证服务,使用代理))
  • Snapchat Data Scientist 面试经验分享|从 OA 到 Final Round 全流程复盘
  • 消息队列集群——RabbitMQ
  • 初识C语言14.动态内存管理
  • ks2e做网站高端品牌设计
  • 华为od-22届考研-C++面经
  • Win10 系统构建仿真 NVIDIA Jetson Orin Nano 环境部署 YOLOv8 模型
  • 英文网站开发付费下插件wordpress
  • 【面板数据】汽车之家及懂车帝汽车配置信息数据集(1999-2025.4)
  • Slotted Aloha
  • 「赤兔」Chitu 框架深度解读(六):剖析 Attention 机制后端实
  • 嵌入式开发中为啥常用do{}while(0)进行宏定义
  • 第六部分:VTK进阶(第172章 vtk-m加速器管线)
  • 矽塔 SA8207 36V输入耐压 高精度可调过流保护与集成智能故障管理 过压过流保护芯片
  • 关键词优化公司网站怎么做网站后台界面
  • 从「Bug 制造机」到「问题解决者」的进化之路
  • 华为新一代鸿蒙操作系统实现与苹果互联
  • 常用 apt 命令及语法(Ubuntu)
  • 华为 AI,建造中的全景图
  • 第二十九篇:动态规划(一):基础与背包问题
  • 深度学习中的训练流程:从输入到权重更新的完整旅程
  • QT------QPainter::save() 和 QPainter::restore() 的使用方法和作用。
  • http trailer 与 http2