分布式微服务系统架构第133集:运维服务器6年经验,高并发,大数据量系统
加群联系作者vx:xiaoda0423
仓库地址:https://webvueblog.github.io/JavaPlusDoc/
https://1024bat.cn/
https://github.com/webVueBlog/fastapi_plus
https://webvueblog.github.io/JavaPlusDoc/
✅ 一、常用 Linux 命令分类(重点常见):
🔹 系统资源监控
命令
作用
top实时查看 CPU、内存、进程占用等
htoptop
的增强版,图形化显示
ps查看当前系统进程状态
uptime查看系统运行时长与负载情况
vmstat查看内存、CPU、IO 等系统性能
iostat查看磁盘 IO 使用率(来自 sysstat 包)
free查看内存使用情况
sar收集系统性能历史(需安装 sysstat)
🔹 网络相关
命令
作用
netstat查看网络连接、端口监听等(建议用 ss 替代)
ss更快更准确的替代 netstat
ping测试网络连通性
traceroute路由追踪
dig/nslookup域名解析工具
curl/wget网络请求测试
tcpdump抓包工具
iftop实时网络带宽监控
🔹 磁盘与文件系统
命令
作用
df查看磁盘挂载与剩余空间
du查看目录/文件占用大小
lsblk查看磁盘挂载结构
mount/umount挂载/卸载磁盘
🔹 文件与系统操作
命令
作用
ls
, cd, cat, cp, mv, rm
文件操作
find
, grep, awk, sed
查找与文本处理
chmod
, chown
修改权限与所有者
tar
, zip, unzip
压缩解压
systemctl
, service
服务管理
journalctl查看系统日志
crontab定时任务
kill
, killall, xargs
杀进程
✅ 二、你提到的命令详解
命令
用途说明
top实时查看 CPU、内存占用、各进程运行状态,常用于排查系统负载高的问题
ps aux快照方式查看所有进程状态,可结合 grep 找关键进程
netstat -tulnp查看监听端口与绑定服务(被 ss 取代)
df -h查看各挂载分区的剩余空间、使用率,判断磁盘是否满
du -sh *查看当前目录下各子目录/文件大小,定位“谁占满了磁盘”
iostat -x 1查看磁盘读写速率、IO 等待情况,分析 IO 瓶颈问题(需安装 sysstat)
✅ 一、Linux 运维排查命令速查表(分类 + 场景)
分类
命令示例
使用场景说明
🔧 CPU/内存排查
top
, htop, ps aux --sort=-%cpu
查看高负载进程、内存泄漏、进程异常
🔧 磁盘排查
df -h
, du -sh *, lsof, ncdu
查看磁盘是否满、哪些文件占用最大空间
🔧 IO 排查
iostat -x 1
, iotop, vmstat 1
判断磁盘 IO 是否瓶颈、IO 等待高
🔧 网络排查
netstat -tulnp
, ss -lntp, lsof -i:端口
查看端口监听情况、网络连接状态
🌐 连通性测试
ping
, traceroute, curl, dig, telnet
网络是否通,DNS 解析是否正常
📂 文件定位
find . -type f -name \"*.log\"
, `du -ah
sort -rh`
🔍 日志查看
tail -f /var/log/messages
, journalctl -xe
实时查看系统/服务日志,查启动失败
🔐 权限排查
ls -l
, chmod, chown
文件/目录权限错误导致无法访问
⚙️ 进程控制
ps
, kill, killall, xargs
查找并终止异常进程
📆 定时任务
crontab -l
, systemctl list-timers
定时脚本未触发或配置错误
CPU 飙高排查
有一次线上系统 CPU 飙到 100%,我使用
top查看是某个 Java 进程占满 CPU,再结合ps -ef确认 PID,之后用jstackdump 栈分析是某个线程死循环。修复后 CPU 降回正常。
磁盘打满导致服务挂掉
某次服务突然挂掉,
df -h一看/var分区 100%,du -sh *逐级定位,发现是日志文件打满了。用logrotate加了压缩与清理策略,避免再次发生。
数据库连接失败排查
应用连不上 MySQL,先用
ping确认网络通,再telnet host 3306发现端口不通,用ss -lntp查服务未监听,原来是数据库未启动,systemctl start mysql后恢复正常。
Redis 多实例端口冲突
多 Redis 实例启动失败,
netstat -tulnp显示端口已被占用,ps aux | grep redis查出是老进程未关闭,kill后再重启成功。
磁盘 IO 性能瓶颈
某服务响应慢但 CPU 占用低,用
iostat -x 1查看发现磁盘util长时间接近 100%,排查是频繁写入日志导致 IO 拥塞,优化后日志按级别写入,响应恢复。
命令
面试中简洁描述
top实时监控进程 CPU、内存使用情况
ps aux查看所有进程的静态快照
netstat
/ss
查看端口监听与网络连接
df -h查看磁盘分区使用情况
du -sh *查看目录大小,排查大文件
iostat查看磁盘 IO 使用与瓶颈
tail -f实时查看日志输出
ping
, curl
检查网络连通性与服务是否在线
kill -9强制结束进程
一键安装工具建议(运维必备)
# IO 和网络工具合集(Debian/Ubuntu)sudo apt install sysstat iotop iftop net-tools lsof# CentOS/RHELsudo yum install sysstat iotop iftop net-tools lsof
排查场景
使用命令
目的
实际作用 / 结果
Java 进程 CPU 飙升
topps aux --sort=-%cpujstack PID找出高 CPU 占用进程,并用 jstack 抓线程堆栈
确认是某线程死循环导致 CPU 占满,分析定位业务逻辑问题
磁盘写入异常
df -h查看分区是否已满
/var
分区 100%,服务日志无法写入,导致接口报错
大文件定位
du -sh *
`du -sh ./*
sort -rh
head`
磁盘 IO 性能瓶颈
iostat -x 1查看 IO 利用率、等待时间
util
长期 90%+,await 时间高,确认写入瓶颈在磁盘
端口冲突 / Redis 未监听
netstat -tulnpss -lntp查看端口占用情况
发现 Redis 配置监听端口未启动或端口被其他进程占用
进程是否存在 / 多开
`ps aux
grep redispgrep -f redis`
确认进程是否已运行、是否重复启动
有次线上系统响应变慢,我用 top 查到 Java 进程 CPU 99%,结合 jstack 抓取线程栈,确认某死循环逻辑导致占用;也遇到磁盘异常,df 发现 /var 分区满了,用 du 快速找到是日志爆量;另外还用 iostat 定位 IO 等待高,结合日志改写策略缓解了瓶颈。
在 MongoDB 中,我们不会说“库”和“表”,而是使用以下术语:
通用数据库术语
MongoDB 中的术语
数据库(Database)
数据库(Database) ✅
表(Table)
集合(Collection) ✅
行(Row)
文档(Document) ✅
列(Column)
字段(Field) ✅
✅ MongoDB 的基本结构:
MongoDB Server └── Database(数据库) └── Collection(集合,相当于表) └── Document(文档,相当于行) └── Field(字段,相当于列)
✅ 举例说明
创建数据库和集合(相当于“建库建表”):
use mydb // 选择或创建数据库db.createCollection(\"users\") // 创建集合,相当于创建表
插入文档(相当于插入一行):
db.users.insertOne({ name: \"张三\", age: 28, email: \"zhangsan@example.com\"})
查询文档:
db.users.find({ age: { $gt: 25 } })
✅ MongoDB 特点 vs 关系型数据库
MongoDB(文档型)
MySQL / PostgreSQL(关系型)
无固定表结构
表结构需提前定义字段类型
支持嵌套文档、数组字段
不支持嵌套对象
灵活写入,字段可不同
每行字段一致,强类型约束
使用 JSON/BSON 存储文档
使用行列式存储
如果你想查看 Mongo 当前所有库/表(集合):
查看所有数据库:
show dbs
查看当前数据库所有集合(表):
show collections
下面是一个完整的 MongoDB 示例项目结构,模拟常见的 用户(users)+ 订单(orders) 模型,适合实际开发用作项目初始化:
✅ 项目结构说明
-
数据库:
demo_app -
集合:
-
-
users:用户信息 -
orders:用户订单(包含用户 ID 作为外键)
-
✅ 初始化脚本(Mongo Shell 语法)
你可以复制粘贴到 Mongo Shell / mongosh 中运行:
// 1. 切换或创建数据库use demo_app// 2. 创建 users 集合并插入示例文档db.createCollection(\"users\")db.users.insertMany([ { _id: ObjectId(), username: \"alice\", email: \"alice@example.com\", phone: \"1234567890\", createdAt: new Date() }, { _id: ObjectId(), username: \"bob\", email: \"bob@example.com\", phone: \"9876543210\", createdAt: new Date() }])// 3. 创建 orders 集合并插入示例文档db.createCollection(\"orders\")db.orders.insertMany([ { _id: ObjectId(), userId: db.users.findOne({username: \"alice\"})._id, item: \"iPhone 15\", price: 7999, status: \"PAID\", createdAt: new Date() }, { _id: ObjectId(), userId: db.users.findOne({username: \"bob\"})._id, item: \"MacBook Air\", price: 9999, status: \"SHIPPED\", createdAt: new Date() }])// 4. 建立索引(如用户邮箱唯一)db.users.createIndex({ email: 1 }, { unique: true })db.orders.createIndex({ userId: 1 })
✅ 查询示例
查找某用户的订单:
const user = db.users.findOne({ username: \"alice\" })db.orders.find({ userId: user._id })
查询所有订单并带上用户信息(关联查询):
db.orders.aggregate([ { $lookup: { from: \"users\", localField: \"userId\", foreignField: \"_id\", as: \"userInfo\" } }, { $unwind: \"$userInfo\" }, { $project: { item: 1, price: 1, status: 1, \"userInfo.username\": 1, \"userInfo.email\": 1 } }])
如果 MongoDB 中的订单集合(orders)超过 1000 万条数据,想要维持查询性能和系统可扩展性,必须从多个维度进行优化:
✅ 一、索引优化(最关键)
1️⃣ 建立高命中率的组合索引
例如常见查询条件:
db.orders.find({ userId: xxx, status: \"PAID\" })
应建立:
db.orders.createIndex({ userId: 1, status: 1 })
2️⃣ 常用字段如 createdAt 用于分页/范围查询:
db.orders.find({ createdAt: { $gte: ISODate(\'2024-01-01\') } }).sort({ createdAt: -1 }).limit(50)
应建立:
db.orders.createIndex({ createdAt: -1 })
3️⃣ 查询慢时,用 explain() 分析索引命中:
db.orders.find({ userId: xxx }).explain(\"executionStats\")
✅ 二、分页优化(避免深度 skip)
不要使用
skip深分页,性能会指数下降。
❌ 不推荐:
db.orders.find().skip(1000000).limit(10)
✅ 推荐:
使用 createdAt 或 _id 做游标分页(基于“上次最后一条”):
db.orders.find({ createdAt: { $lt: 上一页最后时间 } }).sort({ createdAt: -1 }).limit(10)
✅ 三、冷热分离 / 分表策略
🔹 1)冷热数据拆分
-
最近 6 个月的数据保留在主
orders表中 -
历史订单归档到
orders_history表(或另一个库)
使用脚本定期归档:
db.orders.aggregate([ { $match: { createdAt: { $lt: ISODate(\'2024-01-01\') } } }, { $merge: { into: \"orders_history\" } }])
然后在 orders 中删除老数据。
🔹 2)按时间/用户 ID 分表
-
orders_2024,orders_2023 -
orders_user_0,orders_user_1(按 userId hash)
缺点:应用层需要动态路由查询逻辑。
✅ 四、压缩与数据精简
🔸 1)字段压缩(精简文档结构)
-
避免冗余嵌套字段
-
字段名用短名(如
uid替代userId)
🔸 2)关闭不必要字段索引
-
不查询的字段不要建索引(浪费写入性能 + 空间)
✅ 五、写入优化
批量写入:
db.orders.insertMany([...])
合理设置 _id
使用自定义顺序生成 _id,可避免默认 ObjectId 带来的分布写入放大问题(但通常影响不大)。
✅ 六、监控与性能分析工具
-
db.orders.stats()查看集合大小 -
db.orders.totalIndexSize()查看索引空间 -
mongotop,mongostat,Atlas Profiler实时监控 -
explain()定位慢查询
✅ 七、架构层扩展(极端高并发)
如果数据量和并发再提升,可考虑:
-
MongoDB 分片集群(Sharding)
-
热数据使用 Redis 缓存
-
历史数据归档到 ElasticSearch 用于检索
✅ 最终建议小结
优化方向
建议
索引
组合索引 + 创建时间索引
分页
游标分页代替 skip
分表
热/冷数据分离或按时间分表
结构优化
字段精简、去冗余、文档大小控制
查询优化
使用 explain 分析索引使用情况
扩展方案
数据分片 + Redis 缓存 + ES 检索
你提到的三种架构优化策略是构建高并发 + 大数据量系统的核心方式,适用于订单类系统、日志系统、交易系统等场景。下面是对:
-
MongoDB 分片集群(Sharding)
-
Redis 缓存热数据
-
ElasticSearch 归档历史数据
三者的 作用、原理、实现方式 的详解:
✅ 一、MongoDB 分片集群(Sharding)
📌 作用:
将 海量数据水平拆分 到多个分片节点(shard)上,实现 读写负载均衡 + 无限扩展容量。
🧠 原理:
-
按照
shard key将数据分发到不同分片 -
查询由 Mongos(路由器)根据 key 定向到正确 shard
📦 架构组成:
客户端 │ ┌─▼─┐ │mongos 路由器│← 多个,可横向扩展 └─▲─┘ │ ┌─┴────────────┐ │ Config Servers │ ← 配置元数据,3 个或以上 └───────────────┘ │ ┌──────────────┬──────────────┐ │ Shard1 │ Shard2 │ ... 可扩展 └──────────────┴──────────────┘
🔧 示例配置步骤(简略):
-
配置分片集群:
mongod --shardsvr -
配置 router:
mongos --configdb -
添加分片:
sh.addShard(\"shard1/host1:27017\")sh.addShard(\"shard2/host2:27017\")
-
启用分片:
sh.enableSharding(\"demo_app\")sh.shardCollection(\"demo_app.orders\", { userId: 1 }) // 或 createdAt
✅ 二、Redis 缓存热数据(读多写少)
📌 作用:
将高频读的数据(如用户最新订单、订单状态)缓存到 Redis,避免 MongoDB 频繁查询。
🧠 适合数据:
-
最近 24 小时的订单状态
-
用户常访问的订单详情
-
查询结果缓存(防止重复分页)
🛠️ 缓存策略建议:
项目
说明
Key 设计
order:{orderId}
或 user:{id}:orders
失效策略
热点数据设定 1h~12h TTL 或 LRU
一致性策略
写入 Mongo 后立即写入 Redis,或延迟一致性同步
使用方式
先查 Redis,无数据再查 Mongo
// 伪代码let data = redis.get(`order:${orderId}`)if (!data) { data = db.orders.findOne({ _id: orderId }) redis.set(`order:${orderId}`, JSON.stringify(data), \"EX\", 3600)}
✅ 三、ElasticSearch 归档历史数据(全文检索 + 聚合)
📌 作用:
将 老订单数据(如 6 个月前) 导入到 ES,支持快速搜索、分页、复杂统计分析,而不影响 Mongo 的读写压力。
🧠 为什么用 ES:
-
快速全文搜索(支持模糊匹配)
-
支持复杂聚合查询(如订单金额统计)
-
自带倒排索引,适合海量数据
🔧 实现方式:
-
使用同步工具导入数据,如:
-
mongo-connector(已过时) -
自建同步程序
-
Logstash + MongoDB input plugin
-
示例数据结构:
-
{ \"orderId\": \"abc123\", \"userId\": \"u001\", \"item\": \"MacBook Air\", \"status\": \"PAID\", \"createdAt\": \"2023-05-01T12:00:00\"}-
查询示例(DSL):
{ \"query\": { \"bool\": { \"must\": [ { \"match\": { \"status\": \"PAID\" } }, { \"range\": { \"createdAt\": { \"lt\": \"2024-01-01\" } } } ] } }}
✅ 架构协同使用建议(生产实践)
场景
使用方案
实时写入、读写分布式扩展
MongoDB 分片集群
高频访问订单状态或最近列表
Redis 缓存
历史订单模糊搜索、统计分析
ElasticSearch 存档+查询
✅ 一张图总结:
+------------------------+ | 前端 / 接口 | +------------------------+ | +------------+------------+ | | +--------▼--------+ +--------▼--------+ | Redis 缓存 | | MongoDB | | 热点订单/状态 | | 分片订单主库 | +--------+--------+ +--------+--------+ | | +--------▼--------+ +--------▼--------+ | ElasticSearch | | Mongo Archive | | 历史订单检索/统计 | | 历史数据冷存储 | +------------------+ +------------------+
你想要的 Java 实现方案,其目标是:
构建一个系统:使用 MongoDB 分片集群保存订单数据,Redis 缓存热数据,Elasticsearch 存储历史数据,并通过 Java 服务读写协调。
✅ 目录结构概览
我们将从以下 3 个核心点实现:
目标模块
技术方案
🔹 MongoDB 分片读写
使用
MongoTemplate或Spring Data Mongo🔹 Redis 缓存加速
使用
Spring Cache或Redisson🔹 ElasticSearch 查询
使用
Spring Data Elasticsearch或RestHighLevelClient
✅ 一、MongoDB 分片集群连接与操作
📦 Maven 依赖(MongoDB):
org.springframework.boot spring-boot-starter-data-mongodb⚙️ application.yml 配置连接(可带副本集)
spring: data: mongodb: uri: mongodb://shard1:27017,shard2:27017,shard3:27017/demo_app?replicaSet=rs0✅ 使用
MongoTemplate操作:@Servicepublic class OrderService { @Autowired private MongoTemplate mongoTemplate; public void saveOrder(Order order) { mongoTemplate.save(order, \"orders\"); } public List findOrdersByUser(String userId) { Query query = new Query(Criteria.where(\"userId\").is(userId)); return mongoTemplate.find(query, Order.class, \"orders\"); }}
✅ 二、Redis 缓存热点订单数据
📦 Maven 依赖:
org.springframework.boot spring-boot-starter-data-redis⚙️ application.yml 配置:
spring: redis: host: localhost port: 6379✅ 使用 RedisTemplate:
@Autowiredprivate StringRedisTemplate redisTemplate;public Order getOrderWithCache(String orderId) { String cacheKey = \"order:\" + orderId; String cached = redisTemplate.opsForValue().get(cacheKey); if (cached != null) { return JSON.parseObject(cached, Order.class); } // 查询 MongoDB Order order = mongoTemplate.findById(orderId, Order.class); if (order != null) { redisTemplate.opsForValue().set(cacheKey, JSON.toJSONString(order), Duration.ofHours(1)); } return order;}
✅ 三、Elasticsearch 查询历史订单
📦 Maven 依赖(Spring Boot 3 推荐用新客户端):
co.elastic.clients elasticsearch-java 8.11.3✅ 初始化 ES 客户端:
@Configurationpublic class EsConfig { @Bean public ElasticsearchClient elasticsearchClient() { RestClient restClient = RestClient.builder( new HttpHost(\"localhost\", 9200)).build(); ElasticsearchTransport transport = new RestClientTransport( restClient, new JacksonJsonpMapper()); return new ElasticsearchClient(transport); }}✅ 查询历史订单(createdAt < 某时间):
public List searchOldOrders(String userId) throws IOException { LocalDateTime sixMonthsAgo = LocalDateTime.now().minusMonths(6); ElasticsearchClient client = elasticsearchClient; SearchResponse response = client.search(s -> s .index(\"orders\") .query(q -> q .bool(b -> b .must(m -> m.term(t -> t.field(\"userId\").value(userId))) .must(m -> m.range(r -> r.field(\"createdAt\").lt(JsonData.of(sixMonthsAgo.toString())))) ) ), Order.class); return response.hits().hits().stream().map(Hit::source).toList();}
✅ 四、调度归档:Mongo → ElasticSearch
你可以在定时任务中,定期将 Mongo 中的老订单迁移到 ES:
@Scheduled(cron = \"0 0 2 * * ?\")public void archiveOldOrdersToES() { Query query = new Query(Criteria.where(\"createdAt\").lt(LocalDateTime.now().minusMonths(6))); List oldOrders = mongoTemplate.find(query, Order.class, \"orders\"); oldOrders.forEach(order -> { try { elasticsearchClient.index(i -> i .index(\"orders\") .id(order.getId()) .document(order)); } catch (Exception e) { log.error(\"归档失败:{}\", e.getMessage()); } });}
✅ 五、整体架构回顾
+---------------------+ | Java SpringBoot | +---------------------+ | | | Redis (缓存) | | | MongoDB (分片主库) 热点订单 | | | 实时读写 ▼ ▼ ▼ Elasticsearch (归档) 6月前老订单搜索、统计分析 -


