第四部分:分布式与微服务 第11章:常用中间件(纯小白版)
这部分内容将带您进入构建大型、高并发互联网应用的领域。当单个应用程序(“单体应用”)无法承载海量用户时,我们就需要将其拆分成多个协同工作的服务。而中间件 (Middleware),就是连接这些服务的“高速公路”、“中央邮局”和“超级数据库”,是构建大型系统的必备组件。本课程的所有示例都将在您的Linux系统上进行,我们会介绍如何在Linux环境下与这些中间件进行交互。
第四部分:分布式与微服务
第11章:常用中间件
11.1 缓存技术 (Redis)
1. 核心概念:为什么需要缓存?
想象一下,你的网站有一个非常热门的商品页面,每秒钟都有一千个人在访问。
-
问题:如果每次访问,你的Java程序都去MySQL数据库里查询一次商品信息,数据库很快就会不堪重负。因为数据库的数据主要存放在硬盘 (Disk)上,硬盘的读写速度相比于内存 (Memory) 要慢成千上万倍。这将成为整个系统的性能瓶颈。
-
解决方案:缓存 (Cache)。我们把这些被频繁访问的“热点”数据,在第一次查询后,就复制一份存放到一个读取速度极快的、基于内存的地方。后续的请求,就直接从这个“高速缓存”里读取数据,而无需再去访问缓慢的数据库。
好比说:
-
数据库:就像一座城市远郊的巨型图书总馆,藏书齐全,但取书(查数据)需要开车往返,很慢。
-
缓存:就像是在你家楼下的一个小型阅览室,里面只放了最近最火的几十本畅销书。你想看这些书时,下楼就取,速度飞快。
2. 什么是 Redis?
Redis 是目前最流行、性能最高的内存数据库之一。它的所有数据都存放在内存中,这使得它的读写速度快得惊人,非常适合用作缓存。
3. 一步一步在Linux上使用Redis
第一步:安装 Redis 在基于 Debian/Ubuntu 的 Linux 系统上,安装非常简单。
Bash
sudo apt update
sudo apt install redis-server
第二步:启动并测试 Redis 服务 安装后,服务通常会自动启动。我们可以用 Redis 的命令行客户端 redis-cli 来测试一下。
Bash
# 这个命令会向 Redis 服务器发送一个 PING 请求
redis-cli ping
如果服务器回应 PONG,就说明 Redis 已经成功运行了。
第三步:学习基本缓存操作命令
现在,我们来模拟一下缓存“图书”的过程。
Bash
# 进入 Redis 命令行
redis-cli
进入后,你会看到一个 127.0.0.1:6379> 这样的提示符。
-
SET:将数据放入缓存 我们把一本ID为book:101的热门书的信息存入缓存。SET book:101 "Java编程思想" -
GET:从缓存中读取数据GET book:101服务器会立刻返回
"Java编程思想"。 -
EXPIRE:设置过期时间(缓存的核心功能) 缓存里的数据不能永久存在,否则如果数据库里的原数据更新了,缓存里的还是旧数据。我们需要给缓存设置一个“保鲜期”。# 设置 book:101 这条缓存的有效期为 60 秒 EXPIRE book:101 6060秒后,这条缓存会自动被 Redis 删除。
-
DEL:手动删除缓存DEL book:101 -
exit: 退出redis-cli。
第四步:理解Java应用中的缓存逻辑
在你的Java代码中,读取数据的逻辑会变成这样:
Java
// 伪代码,演示逻辑
public Book findBookById(String id) {
// 1. 先去 Redis (高速阅览室) 里找
Book book = redis.get("book:" + id);
// 2. 如果找到了 (缓存命中 - Cache Hit)
if (book != null) {
System.out.println("从缓存中快速找到了书!");
return book; // 直接返回,速度极快
}
// 3. 如果没找到 (缓存未命中 - Cache Miss)
else {
System.out.println("缓存里没有,去数据库总馆慢慢找...");
// 去慢速的 MySQL 数据库里找
book = mysql.query("SELECT * FROM books WHERE id = " + id);
// 4. 找到后,放入缓存,并设置过期时间,方便下一个人
redis.set("book:" + id, book, 60); // 存入缓存,有效期60秒
return book;
}
}
11.2 消息队列 (Kafka / RocketMQ)
1. 核心概念:为什么需要消息队列?
在一个大型系统中,一个用户的操作可能会触发一系列后续任务。
-
问题场景(用户下单):
-
创建订单记录(快)
-
扣减商品库存(快)
-
通知仓库发货(可能慢)
-
给用户发短信通知(可能慢,且依赖第三方服务)
-
为用户增加积分(快)
如果把这些步骤串行地执行,用户点击“下单”后,需要等待所有步骤都完成才能收到“下单成功”的提示,体验很差。而且,如果第4步发短信的服务恰好坏了,整个下单过程都会失败,这非常不合理。
-
-
解决方案:消息队列 (Message Queue, 简称MQ)。它是一种用于异步和解耦的通信机制。
好比说:
-
没有MQ:你去餐厅吃饭,点完菜后,必须一直在座位上等着服务员去厨房下单、厨师炒菜、再上菜,这个过程你什么也干不了(同步阻塞)。
-
有了MQ:你去快餐店,在前台点完单(发送消息),拿到一个取餐号(消息ID),然后你就可以自由地去找座位、玩手机(异步非阻塞)。后厨(消费者)会按照订单顺序做餐,做好后会在屏幕上叫你的号。点餐(生产者)和做餐(消费者)两个环节被解耦了。
2. 消息队列带来的三大好处
-
异步 (Asynchronous):用户无需等待所有耗时操作完成,可以立即得到响应。
-
解耦 (Decoupling):系统的各个模块之间不直接调用,而是通过消息队列来通信。即使“发短信”服务暂时宕机,也不影响“下单”服务,消息会积压在队列里,等短信服务恢复后再处理。
-
削峰 (Peak Shaving):在搞促销活动时,瞬间可能有10万个下单请求涌入。如果没有MQ,系统可能会被直接压垮。MQ就像一个巨大的“蓄水池”,能瞬间吸收所有请求,然后让后端的服务按照自己的处理能力,平稳地、慢慢地从池子里取水处理,保证了系统的稳定。
3. 一步一步了解核心组件
-
第一步:生产者 (Producer)
-
负责创建和发送消息到消息队列的程序。在我们的例子里,就是“订单服务”。
-
-
第二步:消费者 (Consumer)
-
负责从消息队列中订阅和接收消息并进行处理的程序。在我们的例子里,“仓库服务”和“短信服务”都是消费者。
-
-
第三步:消息队列服务 (Broker)
-
消息队列软件本身,负责接收、存储和转发消息。Kafka和RocketMQ就是两种非常流行的Broker实现。
-
-
第四步:主题 (Topic)
-
消息的分类。生产者将消息发送到指定的主题,消费者订阅自己感兴趣的主题。
-
例如:一个叫
order_created的主题,一个叫user_registered的主题。
-
11.3 搜索引擎 (Elasticsearch)
1. 核心概念:为什么需要搜索引擎?
-
问题: 为什么我们不能直接用数据库的
LIKE '%关键词%'来做搜索?-
性能极差:
LIKE '%...%'无法使用索引,会导致全表扫描,在海量数据下是灾难性的。 -
功能有限: 它无法理解“相关性”。搜索“苹果手机”,它搜不出“iPhone”。它也无法实现复杂的筛选、排序和聚合分析。
-
-
解决方案: 使用专业的全文搜索引擎,例如 Elasticsearch。
好比说:
-
用数据库
LIKE搜索:就像在一座巨大的图书馆里,你想找所有关于“人工智能”的书。你只能一本一本地翻阅每一本书的每一页,效率极低。 -
用Elasticsearch搜索:就像这座图书馆有一套极其完善的“索引卡片系统”(技术上叫倒排索引)。图书管理员(Elasticsearch)早就把每一本书的内容都打碎成词语,并记录了每个词语出现在哪些书的哪些页码上。当你想找“人工智能”时,管理员只需要去索引卡片里找到“人工智能”这张卡,上面已经清清楚楚地列出了所有相关的书籍和位置,并且按相关度排好了序。
2. 什么是 Elasticsearch (ES)?
Elasticsearch 是一个基于 Lucene 库构建的、分布式的、开源的搜索和分析引擎。它使用 RESTful API 进行交互,非常易用和扩展。
3. 一步一步了解核心概念
-
第一步:文档 (Document)
-
ES中存储的基本信息单元,相当于数据库中的一行数据。它通常是一个JSON对象。
-
例如:
JSON{ "productId": 101, "productName": "华为 Mate 60 Pro 智能手机", "description": "超高速的5G网络体验,强大的拍照功能" }
-
-
第二步:索引 (Index)
-
一个索引是具有相似特征的文档的集合,相当于数据库中的一张表。
-
例如:一个
products索引,一个orders索引。
-
-
第三步:倒排索引 (Inverted Index)
-
这是ES实现秒级搜索的核心魔法。
-
传统的索引是“文档 -> 词语”,而倒排索引是“词语 -> 文档列表”。
-
示例:
-
文档1:
Java is the best language. -
文档2:
Python is a good language. -
ES创建的倒排索引 (简化版):
-
"Java":[文档1] -
"is":[文档1, 文档2] -
"language":[文档1, 文档2] -
"best":[文档1] -
"Python":[文档2]
-
-
-
当你搜索
Java时,ES只需要瞬间查到这个词,就能立刻知道它在“文档1”中。
-
4. 一步一步在Linux上与ES交互
ES提供的是HTTP API,我们可以用curl命令来和它对话。
第一步:索引一个文档(写入数据)
Bash
# 向名为 products 的索引中,添加一个ID为1的文档
curl -X PUT "http://localhost:9200/products/_doc/1" -H 'Content-Type: application/json' -d'
{
"name": "超快跑鞋",
"description": "专业的马拉松跑步运动鞋"
}'
第二步:搜索文档
Bash
# 在 products 索引中,搜索 description 字段包含 “跑步鞋” 的文档
curl -X GET "http://localhost:9200/products/_search" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"description": "跑步鞋"
}
}
}'
-
观察现象:即使我们搜索“跑步鞋”,ES也能智能地分析并匹配到包含“跑步运动鞋”的文档,并给出相关性评分。这就是全文搜索引擎的强大之处。
总结:Elasticsearch不仅用于网站和App的搜索功能,它也是ELK (Elasticsearch, Logstash, Kibana) 技术栈的核心,被广泛用于海量日志的实时分析和监控。

更多推荐


所有评论(0)