RabbitMQ 使用指南:从入门到实战

RabbitMQ 使用指南:从入门到实战 一、为什么选择 RabbitMQ? 在分布式系统中,服务之间的同步调用会带来三个棘手的问题:扩展性差、性能下降、级联失败。消息队列正是解决这些问题的良方,它的价值在于: 异步解耦:生产者发送消息后即可返回,无需等待消费者处理完成,降低了服务间的直接依赖。 流量削峰:消息队列作为缓冲层,可以将突增的请求暂存,让消费者按自己的节奏处理,保护下游系统。 可靠性保障:RabbitMQ 凭借其极高的消息可靠性和微秒级的低延迟,在微服务解耦、实时数据处理场景中表现出色。 与其他消息队列相比,RabbitMQ 的易用性和社区生态的综合分最均衡。据统计,它目前是国内消息队列使用量最大的产品。 特别说明:本文部分示例使用了 php 代码,但 RabbitMQ 的核心概念和配置逻辑是跨语言的。后文也会提供基于 PHP php-amqplib 的代码示例,方便 Hyperf 开发者参考。 二、核心概念:理解消息流转的“骨架” 要熟练使用 RabbitMQ,首先需要理清其核心组件的作用。 四大核心角色: 生产者(Producer):消息的发送方,负责创建消息并发送到交换机。例如电商系统中,“订单服务”就是生产者,它会发送“订单已创建”的消息。 交换机(Exchange):接收生产者发送的消息,并根据路由规则将消息分发到对应的队列。注意:交换机不存储消息,若没有匹配的队列,消息会被丢弃。 队列(Queue):消息的存储容器,用于暂存待消费的消息。队列是线程安全的,一条消息只能被一个消费者消费(默认情况下)。 消费者(Consumer):消息的接收方,负责从队列中获取消息并处理。例如“库存服务”监听订单队列,收到消息后执行库存扣减。 关键辅助概念: 绑定(Binding):建立交换机与队列之间的关联,并指定**路由键(Routing Key)**作为匹配规则。没有绑定的交换机无法将消息传递到队列。 虚拟主机(Virtual Host):RabbitMQ 的“命名空间”,用于隔离不同项目或环境的资源(交换机、队列、用户等)。每个虚拟主机都有独立的权限控制。 三、交换机类型:选择正确的路由策略 交换机是 RabbitMQ 路由消息的核心,不同类型的交换机对应不同的路由逻辑。RabbitMQ 支持 4 种交换机类型: 3.1 Direct 交换机:精确匹配 工作原理:Direct 交换机要求消息的**路由键(Routing Key)与绑定的绑定键(Binding Key)**完全一致,才会将消息路由到对应的队列。 适用场景:一对一的精确路由。例如“订单支付成功后,通知物流系统发货”。 示例:绑定 Q1 队列的绑定键为 order.pay.success,只有路由键完全匹配该值的消息才会进入 Q1。 3.2 Topic 交换机:模糊匹配 工作原理:Topic 交换机支持使用通配符进行模糊匹配: *:匹配一个单词(例如 user.* 可匹配 user.register,但不匹配 user.register.success) #:匹配零个或多个单词(例如 user.# 可匹配 user.register 和 user....

2024年08月08日 · 6 min · Leanku

MySQL 高并发场景下的性能优化

MySQL 高并发场景下的性能优化 MySQL 的性能优化并不是简单地给表增加几个索引。 在真实的高并发系统中,数据库性能通常受到多个因素共同影响: 应用请求 ↓ 数据库连接 ↓ SQL 执行 ↓ 索引 ↓ Buffer Pool ↓ 锁 / 事务 ↓ 磁盘 I/O 当并发量继续增加以后,还会遇到: 连接数过高 SQL 执行时间增加 锁竞争 事务堆积 Buffer Pool 压力 磁盘 I/O CPU 使用率 Redo Log 压力 因此,高并发 MySQL 优化应该从整个访问链路出发,而不是只盯着 SQL。 1. 高并发下 MySQL 为什么容易成为瓶颈 假设一个系统每秒有: 5000 QPS 其中: 80% 查询 20% 写入 那么数据库每秒需要处理: 4000 次查询 1000 次写入 如果单条 SQL 平均执行: 10 ms 看起来并不算慢。 但当大量请求同时进入数据库后,数据库真正面对的是: 大量连接 ↓ 大量 SQL ↓ 大量索引访问 ↓ 大量数据页 ↓ 大量事务 ↓ 锁竞争 ↓ 磁盘 / CPU / 内存压力 因此:...

2024年07月19日 · 4 min · Leanku

一个 HTTP 请求的并发链路:从 Web Server 到 MySQL

一个 HTTP 请求的并发链路:从 Web Server 到 MySQL 前面的文章分别讨论了并发是什么、进程线程协程如何执行请求、IO 多路复用如何管理大量连接,以及如何用 QPS、并发数和响应时间衡量系统。 但这些概念真正进入后端系统之后,会形成一条完整的链路: Client ↓ Web Server / Nginx ↓ Application ↓ Process / Thread / Coroutine ↓ Redis / RPC / MySQL ↓ Response ↓ Client 真正的高并发问题,通常也不是发生在某一个组件上,而是发生在整个链路的容量不匹配上。 例如: Web Server 可以接收 10000 个连接,应用可以运行 1000 个协程,但 MySQL 连接池只有 50 个连接。 这并不意味着系统只能处理 50 个 HTTP 请求,但意味着同时进行数据库操作的请求最多受到这 50 个连接的约束。 因此,理解高并发,不能只看 Web Server 或应用服务器,而要沿着一次请求完整地看下去。 1. 一个 HTTP 请求到底经过哪些组件? 假设用户访问: GET /api/orders/10001 一个典型后端系统可能经过: ┌──────────┐ │ Client │ └────┬─────┘ │ HTTP ▼ ┌──────────────┐ │ Nginx / Web │ │ Server │ └──────┬───────┘ │ ▼ ┌──────────────────┐ │ Application │ │ Hyperf / Java....

2024年07月10日 · 5 min · Leanku

高并发到底是什么?从 QPS、并发数到响应时间

高并发到底是什么?从 QPS、并发数到响应时间 什么才叫高并发? 很多时候我们会看到: 支持 1000 并发 支持 10000 QPS 支持百万级并发 这些数字看起来很直观,但实际上: 1000 并发 1000 QPS 1000 个连接 1000 TPS 完全不是同一个概念。 如果不区分这些指标,就很容易在性能测试和系统设计中得出错误结论。 1. “高并发”到底是什么意思? “高并发”并不是一个严格固定的数字。 例如: 1000 QPS 对于一个简单的内部管理系统,可能已经非常高。 但对于大型互联网服务,这个数字可能非常普通。 因此: 高并发是相对于系统规模、业务模型和资源能力而言的概念,而不是一个固定阈值。 更准确地说,高并发关注的是: 大量请求 ↓ 在较短时间内 ↓ 同时进入系统 ↓ 系统仍然能够稳定处理 这里至少涉及三个维度: 请求到达速度 请求同时存在的数量 请求完成速度 对应到性能指标,就是: QPS / RPS 并发数 响应时间 / 吞吐量 因此,讨论高并发时,不能只说: “我们的系统能扛 10 万并发。” 还应该继续问: 什么类型的请求? 多少 QPS? 平均 RT 多少? P99 多少? 请求是否访问 MySQL? 数据库连接池多大? CPU 利用率多少? 内存多少? 否则这个“10 万并发”几乎没有实际意义。...

2024年07月03日 · 5 min · Leanku

MySQL Redo Log、Undo Log 与 Binlog

MySQL Redo Log、Undo Log 与 Binlog 在学习 MySQL InnoDB 时,经常会遇到三个日志: Redo Log Undo Log Binlog 它们名字相似,但解决的问题完全不同。 简单来说: Redo Log → 数据库崩溃后,恢复已经发生的修改 Undo Log → 事务回滚、MVCC Binlog → 记录数据库逻辑变更,用于复制、恢复等 其中最容易混淆的是: 为什么 InnoDB 已经有 Redo Log 了,MySQL 还需要 Binlog? 原因在于 Redo Log 和 Binlog 所处的层次、记录内容和设计目标并不相同。 理解三者的关系,也是理解 MySQL 事务提交和主从复制的基础。 1. 为什么数据库需要日志 假设执行: UPDATE users SET balance = balance - 100 WHERE id = 1; 最简单的想法是: 修改内存 ↓ 直接把数据写入磁盘 ↓ 完成 但真实数据库不能简单这样做。 原因是磁盘 I/O 成本较高,而且一次事务可能修改很多数据页。...

2024年06月23日 · 4 min · Leanku

MySQL InnoDB 存储引擎详解

MySQL InnoDB 存储引擎详解 InnoDB 是 MySQL 8 默认的存储引擎,也是绝大多数业务系统使用的核心存储引擎。 前面介绍索引、事务、锁和死锁时,很多机制实际上都建立在 InnoDB 的内部结构之上。 例如: 为什么 InnoDB 的索引查询通常很快? 为什么主键设计会影响二级索引大小? 为什么更新数据不一定立即写入磁盘? Buffer Pool 到底有什么作用? Redo Log 为什么能够提高写入性能? InnoDB 为什么能够支持事务和崩溃恢复? 要理解这些问题,需要从 InnoDB 的存储结构开始。 1. InnoDB 是什么 MySQL 本身并不负责所有数据存储工作。 可以简单理解为: MySQL Server ↓ SQL 解析 / 优化 / 执行 ↓ Storage Engine ↓ InnoDB ↓ 数据文件 / 日志文件 存储引擎负责真正的数据存储和访问。 早期 MySQL 中存在多种存储引擎,例如: InnoDB MyISAM Memory Archive 现代 OLTP 系统中,InnoDB 是最重要的选择。 InnoDB 提供了关系型业务系统通常需要的核心能力: 事务 行级锁 MVCC 崩溃恢复...

2024年06月21日 · 5 min · Leanku

IO 多路复用:一个线程为什么可以同时处理大量 HTTP 请求?

IO 多路复用:一个线程为什么可以同时处理大量 HTTP 请求? 我们知道,一个 Web 服务同时面对大量 HTTP 请求时,并不一定需要: 1000 个请求 ↓ 1000 个线程 对于 IO 密集型服务,更常见的做法是让执行单元在等待网络 IO 时不要一直阻塞,然后利用事件机制处理其他连接。 这就引出了一个非常重要的概念: IO 多路复用(I/O Multiplexing)。 它是理解 Linux 网络服务器、Nginx、Node.js、Swoole、Hyperf 等高并发网络程序的基础。 1. 先从一个 Socket 开始 一个 HTTP 服务器,本质上需要处理大量网络连接。 例如服务器监听: 0.0.0.0:80 客户端建立 TCP 连接后,操作系统会为连接提供对应的 Socket。 可以简单理解为: Client A ─── Socket A ──┐ Client B ─── Socket B ──┤ Client C ─── Socket C ──┤ Client D ─── Socket D ──┤ ▼ Web Server 假设现在有: 10000 个 TCP 连接 服务器需要解决一个问题:...

2024年06月20日 · 6 min · Leanku

进程、线程、协程:后端服务到底是怎么处理并发请求的?

进程、线程、协程:后端服务到底是怎么处理并发请求的? 在上一篇 《理解并发:一个 HTTP 请求到后端到底发生了什么?》 我们从一个 HTTP 请求出发,理解了并发最基本的概念: HTTP 请求 ↓ Web Server ↓ 后端服务 ↓ CPU / IO ↓ MySQL / Redis / RPC ↓ HTTP 响应 但这里留下了一个非常重要的问题: 后端服务到底由谁来执行这些请求? 如果同时来了 1000 个 HTTP 请求,服务器是不是创建 1000 个进程? 如果不是,是不是创建 1000 个线程? 如果也不是,那么一个线程又是怎么处理大量请求的? 要回答这些问题,就必须理解后端程序最核心的三个执行概念: 进程 线程 协程 1. 先建立一个整体认识 可以先把三者理解成三个不同层次的概念: 进程 │ ├── 线程 │ │ │ ├── 协程 │ ├── 协程 │ └── 协程 │ └── 线程 但这里有一个需要特别注意的地方: 协程并不是操作系统进程或线程的同级概念。 进程和线程主要属于操作系统调度与资源管理层面;协程通常是由运行时、语言、框架或用户态库提供的更轻量级执行机制。 因此:...

2024年06月17日 · 5 min · Leanku

关于分布式

关于分布式 一、什么是分布式? 一个系统,各组件分别部署在不同服务器。彼此通过网络通信和协调的系统。 可以指多个不同组件分布在网络上互相协作 也可以一个组件的多个副本组成集群,互相协作如同一个组件,比如数据存储服务中心为了数据不丢失而采取的多个服务备份冗余 分布式最早出现的目的首先是解决单点问题,避免单点故障,然后解决了性能问题 二、分布式和微服务的区别? 微服务并不一定是分布式系统(微服务中多个服务不一定部署在不同服务器,单机部署情况则不算是分布式) 分布式一定不是微服务 (分布式祖耀侧重服务的部署方式,微服务则是针对应用的一种服务拆分的架构) 三、分布式CAP原则 在设计一个分布式项目的时候会遇到三个特性: 一致性(Consistency):所有节点数据实时同步,读取始终返回最新值 可用性(Availability):每个请求必须得到响应(无论数据是否最新),高可用 分区容错(Partition Tolerance):分布式最基本也是必需要有的特性,系统在遇到某个节点或网络分区故障时,仍然能够对外提供服务 三者无法同时满足,最多只能实现其中两个,网络分区发生时,必须牺牲C或A ‌CP(牺牲可用性)‌:如ZooKeeper,确保数据强一致性但可能拒绝请求 ‌AP(牺牲一致性)‌:如Eureka,保证服务可用但允许数据短暂不一致 三、 BASE理论 BASE理论是分布式系统设计原则,BASE 是指基本可用(Basically Available)、软状态( Soft State)、最终一致性( Eventual Consistency),核心思想是即使无法做到强一致性(CAP 的一致性就是强一致性),但应用可以采用适合的方式达到最终一致性。 基本可用(Basically Available):分布式系统,在出现故障的时候,允许损失部分可用性。类似服务降级 软状态(Soft State):允许系统存在中间状态,而该中间状态不会影响系统整体可用性。这里的中间状态就是 CAP 理论中的数据不一致。 最终一致性(Eventual Consistency):系统中的所有数据副本经过一定时间后,最终能够达到一致的状态。 四、分布式事务及解决方案 分布式事务 本地事务依赖数据库本身提供的事务特性来实现, 但是在分布式环境下,可能会出现需要远程调用,比如: begin transaction; //1.本地数据库操作:张三减少金额 //2.远程调用:让李四增加金额 commit transation; 张三和李四的账户不在一个数据库中甚至不在一个应用系统里,实现转账事务需要通过远程调用,由于网络问题就会导致分布式事务问题。 分布式事务解决方案 2PC 2PC 即两阶段提交协议,是将整个事务流程分为两个阶段,准备阶段(Prepare phase)、提交阶段(commit phase),2 是指两个阶段,P 是指准备阶段,C 是指提交阶段。偏向数据库 TCC TCC 是 Try、Confirm、Cancel 三个词语的缩写,TCC 要求每个分支事务实现三个操作:预处理 Try、确认 Confirm、撤销 Cancel。Try 操作做业务检查及资源预留,Confirm 做业务确认操作,Cancel 实现一个与 Try 相反的操作即回滚操作。TM 首先发起所有的分支事务的 Try 操作,任何一个分支事务的Try操作执行失败,TM 将会发起所有分支事务的 Cancel 操作,若 Try 操作全部成功,TM 将会发起所有分支事务的 Confirm 操作,其中 Confirm/Cancel 操作若执行失败,TM 会进行重试。偏向代码

2024年06月11日 · 1 min · Leanku

理解并发:一个 HTTP 请求到后端到底发生了什么?

理解并发:一个 HTTP 请求到后端到底发生了什么? 在开发后端系统时,我们经常会看到这样的描述: “这个接口支持 1000 并发。” 但“1000 并发”到底意味着什么? 是不是意味着服务器同时启动 1000 个线程? 是不是意味着 CPU 同时执行 1000 个请求? 如果一个请求正在等待 MySQL,CPU 又在做什么? 一个 PHP/Hyperf 服务为什么可以同时处理大量 HTTP 请求? 要真正理解高并发,不能一开始就从 QPS、限流、缓存这些概念入手,而应该先理解一个最基本的问题: 一个 HTTP 请求进入后端以后,到底发生了什么? 1. 先理解什么是并发 并发(Concurrency)描述的是: 多个任务在同一个时间段内处于进行状态,并且它们的执行过程存在交错。 并发和并行(Parallelism)不是同一个概念。 例如: 任务 A:████████ 任务 B: ████████ 两个任务都在进行,但可能只有一个 CPU 核心。 CPU 可以先执行 A: A A A A 然后因为 A 正在等待 IO,转而执行 B: A A → 等待 ↓ B B B B 这属于并发。 如果机器有多个 CPU 核心: CPU Core 1:A A A A CPU Core 2:B B B B 两个任务可以在同一时刻真正执行,这才是并行。...

2024年06月10日 · 5 min · Leanku