开发常用 100 条 Linux 指令全解析

🐧 开发常用 100 条 Linux 指令全解析:从系统监控到性能调优 引言:为什么要掌握这些指令 在日常开发和运维工作中,服务器出现问题时的第一反应往往是 SSH 登录上去排查。能不能在最短的时间内定位到根本原因,取决于对 Linux 诊断指令的熟练程度。这些指令不仅是敲几个字母的组合,更重要的是—— 能看懂输出里每一个数字和字段代表什么 。 下图展示了从服务器出现异常到定位根因的完整诊断链路,以及各个环节对应的核心指令分类: flowchart TD PROBLEM([🚨 服务器异常]) --> CHECK_LOAD{"负载过高\n响应变慢?"} CHECK_LOAD -->|是| PATH_LOAD[📊 系统信息诊断] CHECK_LOAD -->|否| CHECK_MEM{"内存不足\nOOM ?"} CHECK_MEM -->|是| PATH_MEM[🧠 内存诊断] CHECK_MEM -->|否| CHECK_IO{"磁盘问题\nIO 等待?"} CHECK_IO -->|是| PATH_IO[💾 磁盘诊断] CHECK_IO -->|否| CHECK_NET{"网络异常\n连接失败?"} CHECK_NET -->|是| PATH_NET[🌐 网络诊断] CHECK_NET -->|否| CHECK_PROC[🔍 进程级排查] PATH_LOAD --> CMD1["uptime / top / vmstat"] PATH_MEM --> CMD2["free / sar / /proc/meminfo"] PATH_IO --> CMD3["iostat / iotop / df"] PATH_NET --> CMD4["ss / ping / tcpdump"] CHECK_PROC --> CMD5["ps / strace / lsof / journalctl"] style PROBLEM fill:#701a4c,stroke:#e11d48,stroke-width:2px,color:#ffffff,font-weight:bold style CHECK_LOAD fill:#2a1147,stroke:#a855f7,stroke-width:1.5px,color:#ffffff,font-weight:bold style CHECK_MEM fill:#2a1147,stroke:#a855f7,stroke-width:1.5px,color:#ffffff,font-weight:bold style CHECK_IO fill:#2a1147,stroke:#a855f7,stroke-width:1.5px,color:#ffffff,font-weight:bold style CHECK_NET fill:#2a1147,stroke:#a855f7,stroke-width:1.5px,color:#ffffff,font-weight:bold style PATH_LOAD fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#ffffff style PATH_MEM fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#ffffff style PATH_IO fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#ffffff style PATH_NET fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#ffffff style CHECK_PROC fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#ffffff style CMD1 fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#ffffff,font-weight:bold style CMD2 fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#ffffff,font-weight:bold style CMD3 fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#ffffff,font-weight:bold style CMD4 fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#ffffff,font-weight:bold style CMD5 fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#ffffff,font-weight:bold 本文按照 10 大分类 组织 100 条指令,每一条都包含常用选项、实际输出示例、输出参数逐列解读,以及能从这些数据中看出服务器的什么状态。 ...

十月 14, 2022 · 32 分钟 · 6673 字 · yaomingye

高并发企业自营电商小程序系统架构设计

🏗️ 高并发企业自营电商小程序系统架构设计:从需求分析到部署监控的全链路方案 从一个真实的架构评审说起 某团队接到一个需求:为公司开发一款自营电商小程序,C 端消费者可以在小程序上购买公司产品。预估用户量 5 万 ~ 10 万,产品部门希望赶在活动上线前交付。 架构师在评审会上画出了第一版方案:Spring Boot 单体应用 + MySQL + Redis 缓存。评审进行到一半,有人提出了一个问题:“如果 1 万个用户同时抢一个秒杀商品,这套架构能撑住吗?” 这个问题让团队陷入了沉默。单体应用的库存扣减在数据库层面是一条 UPDATE ... SET stock = stock - 1 WHERE stock > 0,在高并发下这条 SQL 会成为瓶颈——数据库行锁(InnoDB 行级锁,对某一行数据的排他锁定)会让所有请求串行化,QPS(Queries Per Second,每秒请求数)直接降到数据库单行更新的极限:约 500 ~ 1000。 ⚠️ 新手提示:数据库行锁串行化的意思是,当 1000 个请求同时更新同一行数据(比如同一商品的库存),InnoDB 会让它们排队执行,每个请求必须等前一个提交后才能继续。这不是"慢",而是"一个一个来"——1000 个请求就是 1000 次串行操作。 这就是本文要解决的核心问题: 如何设计一套能支撑 2 万 QPS 的企业自营电商系统,同时保证库存不超卖、订单不丢失、支付不重复。 📌 前置知识:阅读本文需要了解 Spring Boot 基础、Redis 基本操作、MySQL 基本用法、消息队列(RocketMQ/Kafka)的基本概念。如果对微服务架构不熟悉,建议先了解服务注册与发现(Nacos)的基本概念。 🏗️ 一、需求分析与业务建模 🎯 1.1 业务范围界定 在设计任何系统之前,第一步是明确边界——知道什么要做什么不做。 维度 内容 业务形态 企业自营 B2C 电商小程序,企业是唯一商家,面向 C 端消费者 用户规模 预估 1 万 ~ 10 万注册用户 峰值 QPS 预估 1000 ~ 5000(设计目标:支撑 2 万 QPS) 核心功能 商品浏览、下单、支付、退款、物流查询 这里有一个关键决策: 设计目标(2 万 QPS)远大于预估峰值(5000 QPS) 。这不是过度设计,而是为以下场景预留缓冲: ...

十月 13, 2022 · 14 分钟 · 2934 字 · yaomingye

Spring Cloud Alibaba 微服务中间件体系概念解析

Spring Cloud Alibaba 微服务中间件体系概念解析:从单体拆分到组件选型的避坑指南 📖 一、开篇:一个电商系统的"拆服务"血泪史 某人接手了一个电商项目。最开始就一个 Spring Boot 单体,订单、库存、支付、物流全塞在一起。单机跑得飞快,部署就一个 jar 包,轻松得很。 然后业务起来了。 大促期间,用户疯狂下单,库存扣减开始排队。支付回调偶尔超时,整个服务直接 502。最要命的是改一行订单逻辑,得把整个项目重新部署一遍。一次发布,全员瑟瑟发抖。 于是开始拆微服务。 📌 前置知识:微服务(Microservice)是一种架构风格,把一个大应用拆成多个独立部署的小服务,每个服务有自己的数据库和业务边界,服务之间通过网络(HTTP/RPC/MQ)通信。 拆完之后,新问题来了——不是技术的,是运维的。服务之间怎么发现对方?怎么保证不出错?出错了怎么处理? 以前一个方法调用 orderService.deduct() 就行,现在得想:库存服务在哪台机器上?万一它挂了怎么办?万一它响应太慢拖死订单服务怎么办? 这些问题,每一家互联网公司都会遇到。阿里巴巴把自己踩过的坑、写的解决方案打包开源,就是今天的 Spring Cloud Alibaba(一套与 Spring Cloud 生态集成的微服务中间件集合,由阿里巴巴开源)。 这篇博客不是教你写代码的。是让你看完之后,能跟同事说清楚:“网关是用来干什么的?Sentinel 和 Hystrix 选哪个?Nacos 和 Eureka 有什么区别?什么时候该用 Seata,什么时候千万别用?” ⚠️ 新手提示:如果你刚接触微服务,先记住一句话——微服务不是银弹。如果你系统 QPS(每秒请求数)不到 100,用微服务是给自己找麻烦。 单体 + Nginx 负载均衡,能解决你 90% 的问题。 🗺️ 二、总览图:六大组件,一张图看清 先把全景图画出来。一个标准的微服务架构,从上到下由这几个关键组件拼成: flowchart LR classDef entry fill:#701a4c,stroke:#e11d48,stroke-width:2px,color:#fce7f3,font-weight:bold; classDef gateway fill:#2d1a05,stroke:#f59e0b,stroke-width:2px,color:#fde68a,font-weight:bold; classDef protect fill:#2a1147,stroke:#a855f7,stroke-width:1.5px,color:#ede9fe,font-weight:bold; classDef rpc fill:#052e16,stroke:#16a34a,stroke-width:1.5px,color:#bbf7d0,font-weight:bold; classDef registry fill:#0f172a,stroke:#3b82f6,stroke-width:1.5px,color:#bfdbfe,font-weight:bold; classDef mq fill:#450a0a,stroke:#dc2626,stroke-width:1.5px,color:#fecaca,font-weight:bold; classDef tx fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#e5e7eb; subgraph ACCESS_LAYER["接入层"] USER[用户/客户端] GW["Gateway 网关\n路由 + 限流 + 鉴权"] end subgraph SERVICE_LAYER["服务层"] ORDER[订单服务] STOCK[库存服务] PAY[支付服务] end subgraph MIDDLEWARE["中间件层"] NACOS["Nacos\n注册中心 + 配置中心"] SENTINEL["Sentinel\n流量控制 + 熔断降级"] ROCKETMQ["RocketMQ\n异步消息"] SEATA["Seata\n分布式事务"] end USER --> GW GW --> ORDER GW --> STOCK GW --> PAY ORDER -->|RPC调用| STOCK ORDER -->|RPC调用| PAY STOCK -->|RPC调用| PAY ORDER -.->|注册/发现| NACOS STOCK -.->|注册/发现| NACOS PAY -.->|注册/发现| NACOS SENTINEL -.->|保护| ORDER SENTINEL -.->|保护| STOCK SENTINEL -.->|保护| PAY ORDER -->|发送消息| ROCKETMQ ROCKETMQ -->|消费消息| STOCK SEATA -.->|协调事务| ORDER SEATA -.->|协调事务| STOCK SEATA -.->|协调事务| PAY class USER entry; class GW gateway; class SENTINEL protect; class ORDER,STOCK,PAY rpc; class NACOS registry; class ROCKETMQ mq; class SEATA tx; 是不是有点懵?没关系,拆开看。每一层就干一件事: ...

十月 11, 2022 · 5 分钟 · 948 字 · yaomingye

WSL2 Docker 数据持久化

☸️ WSL2 Docker 数据持久化:docker-desktop-data 缺失导致容器丢失的诊断与修复 📌 一、问题场景 在日常开发中,使用 Docker Desktop + WSL2 后端是一个常见组合。然而部分开发者在执行 wsl --shutdown 后,重新打开终端时发现一个严重问题: 之前创建的所有容器、镜像、数据卷全部消失 。 以下是一个典型的问题复现过程: # 1. 正常使用 Docker,创建测试容器 $ docker run -d --name my-app -p 8080:80 nginx Unable to find image 'nginx:latest' locally latest: Pulling from library/nginx ... cc3c2e0be814: Pull complete Status: Downloaded newer image for nginx:latest a1b2c3d4e5f6... # 容器启动成功 # 2. 确认容器正在运行 $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a1b2c3d4e5f6 nginx "/docker-entrypoint.…" 5 seconds ago Up 5 seconds 0.0.0.0:8080->80/tcp my-app # 3. 手动执行 WSL 关闭(或系统重启触发) $ wsl --shutdown # 4. 重新打开终端,检查容器 $ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES # 输出为空 —— 所有容器消失! 这个场景的核心问题在于:Docker Desktop 在 WSL2 中的持久化数据没有被正确保存,导致 wsl --shutdown 后所有状态丢失。本文将深入分析根因并提供完整的修复方案。 ...

十月 10, 2022 · 7 分钟 · 1291 字 · yaomingye

一次性讲明白 Filter、Interceptor、RequestAdvice、ResponseAdvice

一次性讲明白 Filter、Interceptor、RequestAdvice、ResponseAdvice:执行顺序与实际应用 一、从一个常见需求说起 开发一个 Web 接口,通常需要处理以下事情: 记录每个请求的耗时日志 校验登录态,未登录拒绝访问 对请求参数做预处理(比如解密、格式转换) 对响应结果做统一封装(比如统一返回 {code, msg, data} 格式) 这四个需求对应的正是四个组件: 需求 对应组件 执行位置 记录请求日志 Filter Servlet 容器层(最外层) 登录校验 Interceptor Spring MVC 层(Controller 前后) 请求参数预处理 RequestAdvice Controller 方法执行前 响应统一封装 ResponseAdvice Controller 方法执行后 这四个组件在一条请求链路中各自负责不同的阶段。先看一张总览图,建立位置感: flowchart TD %% 半暗底色 + 高亮描边:完美适配博客深色/浅色双主题 %% classDef process fill:#1e1e24,stroke:#6b7280,stroke-width:2px,color:#e5e7eb; classDef data fill:#052e16,stroke:#16a34a,stroke-width:2px,color:#bbf7d0,font-weight:bold; classDef startEnd fill:#701a4c,stroke:#e11d48,stroke-width:2.5px,color:#fce7f3,font-weight:bold; A[客户端请求] --> B[Filter] B --> C[DispatcherServlet] C --> D[Interceptor.preHandle] D --> E[RequestAdvice] E --> F[Controller] F --> G[ResponseAdvice] G --> H[Interceptor.postHandle] H --> I[Interceptor.afterCompletion] I --> J[Filter 返回] J --> K[客户端响应] class E,G data; class A,B,C,D,F,H,I,K process; class J startEnd; 这张图只需要记住一个核心原则: Filter 在最外层,Interceptor 在中间层,Advice 在最内层(紧贴 Controller)。 请求进来从外到内,响应出去从内到外。 ...

十月 9, 2022 · 7 分钟 · 1426 字 · yaomingye

学会够用就行

💼 学会够用就行:一个后端开发的技术学习反思 📌 一、让人崩溃的瞬间 一个典型的微服务项目,技术栈清单:注册中心、配置中心、网关、RPC 框架、熔断降级、消息队列、链路追踪、分布式事务——光把这些组件的名字列出来就能占满一页文档 📋。 很多开发者的第一反应不是"每个组件解决什么问题",而是"每个组件的底层原理是什么" 🔬。因为有一个根深蒂固的观念:只会用,就是调参工程师;看不懂源码,就永远停留在表面。 于是开始列学习计划 📝。每个组件背后对应一个庞大的知识体系——光是其中一个,就涉及网络协议、数据一致性、故障转移、存储引擎。密密麻麻的学习大纲列出来了,以为只要按计划来,半年后就能"通吃"。 结果可想而知。三个月过去,没有一个组件真正学完 ⏰。每次深入到一个点,就会牵出另外三个不熟悉的概念,每一个又对应着新的源码、新的论文、新的文档。计划不断膨胀,焦虑不断积累 😰,而真正沉淀下来的知识少得可怜。 更典型的反应是:每次看到新的技术文章、新的开源项目、新的最佳实践,第一反应不是"学到了新东西",而是"我又落后了" 📉。这种"松鼠病" 🐿️(不断囤积学习资料,却从不真正消化)带来的不是进步,是持续的自我怀疑。 🔍 二、试图"全部精通"的失败模式 这种失败的学习尝试有清晰的模式: 选定一个组件,找到官方文档和源码 从入口类开始,顺着调用链往下读 读到一个关键分支时,发现它又依赖另一个不熟悉的领域 于是开一个新坑,转弯去研究那个依赖 笔记越记越多,分支越开越散,但没有一个能完整收尾 这种"递归式深挖" 🔁 的学习方式,表面上看是在追求深度,实际上只是在不同的表层之间跳转——每一层都浅尝辄止,因为时间根本不够。 后果也很直接: 工作效率下降 :写简单功能时总觉得"还没彻底搞懂",犹豫不决,原本一小时能完成的拖了一下午 面试暴露出知识表面化 :简历上写了"熟悉 XX 原理",遇到追问细节时就露馅——因为每个都只看了一部分,没有形成体系 反馈循环崩溃 :投入了大量时间却没有可验证的产出,越学越不知道自己学了什么,越不知道就越焦虑 这就是"全部精通"的悖论 ⚡:越想全部搞懂,越是什么都搞不懂;越努力,越焦虑。 ⚙️ 三、转折点:接受一个现实 这个现实很简单,但接受它需要时间 ⏳: 一个人不可能精通所有东西。 微服务生态不是某一个公司设计的统一框架,它是几十个开源项目各自演进、互相适配之后形成的一张网 🕸️。每个项目背后都有几个全职维护者,他们花了几万小时才做到今天的程度。指望一个人在业余时间把这些都"深入掌握",这本身就是不切实际的。 关键认知转变在这里: “会用就行"不是放弃学习 ——它是把有限的精力从"全面深挖"转移到"按需深入"上 “会用就行"不是不追求原理 ——它是在遇到问题、需要答案的时候才去追求原理,而不是在不理解问题之前就试图背下所有实现细节 “会用就行"的核心是聚焦 ——你不可能在所有方向上都跑赢所有人,但可以在一个方向上走得更远 用一个表格来对比这两种状态: 维度 试图全部精通 接受"够用就行” 学习驱动力 焦虑(怕落后) 需求(解决问题) 学习范围 所有组件,全面铺开 按项目需要,按兴趣聚焦 深度标准 “源码每一行都看懂” “能定位问题、能做出决策” 时间投入 所有业余时间 有重点的投入 心理状态 持续焦虑、自我怀疑 可控、可持续 实际产出 一堆半成品笔记 能落地的方案和代码 真正让人内化这个认知的,不是某篇文章或某本书,而是一次又一次的实际工作经历 💼——大部分线上问题,需要的不是"精通源码”,而是"知道该去哪里查” 🔍。 ...

十月 8, 2022 · 1 分钟 · 191 字 · yaomingye

Spring Boot 开发中的上下文

Spring Boot 开发必知:那些高频使用的核心上下文类 🐛 从一个 NPE 说起 同事在 IdUtils 工具类里写了一个生成订单号的方法,需要调用数据库序列服务。代码部署到生产环境后,每隔几天就会抛出一个 NullPointerException,而且总是在凌晨 2 点左右。 排查后发现问题:生成订单号的逻辑需要从 Spring 容器中获取 SequenceService,但 IdUtils 是一个纯静态工具类,不归 Spring 管理。同事的写法是: public class IdUtils { // 这样永远拿不到 Bean——IdUtils 自己都没被 Spring 管理,谁来注入? @Autowired private static SequenceService sequenceService; public static String genOrderId() { return sequenceService.nextVal("order"); // NPE! sequenceService == null } } 这是一个典型场景: 需要在不受 Spring 管理的类中获取 Spring Bean 。解决它的钥匙就是本篇要讲的"上下文类"(Context Classes)——Spring 框架提供的一系列能让你在任何位置获取框架运行时状态的工具。 flowchart LR classDef root fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#bfdbfe,font-weight:bold; classDef branch fill:#2d1a05,stroke:#f59e0b,stroke-width:2px,color:#fde68a,font-weight:bold; classDef leaf fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#e5e7eb; classDef highlight fill:#450a0a,stroke:#dc2626,stroke-width:1.5px,color:#fecaca,font-weight:bold; ROOT[Spring Boot 核心上下文类] ROOT --> B1(1. Web 请求上下文) B1 --> L1["RequestContextHolder\n持有当前请求的 ThreadLocal"] B1 --> L2["ServletRequestAttributes\n封装 HttpServletRequest/Response"] B1 --> L3["RequestContextUtils\nLocale / FlashMap / 输入输出流"] ROOT --> B2(2. Security 安全上下文) B2 --> L4["SecurityContextHolder\n持有当前认证信息的 ThreadLocal"] B2 --> L5["Authentication\nPrincipal / Credentials / Authorities"] ROOT --> B3(3. 事务上下文) B3 --> L6["TransactionSynchronizationManager\n事务状态判断 / 回调注册\n事务资源绑定"] ROOT --> B4(4. 容器上下文) B4 --> L7["ApplicationContext\nSpring 容器本身"] B4 --> L8["ApplicationContextAware\n回调注入容器引用"] B4 --> L9["Environment\n配置属性 / Profile"] ROOT --> B5(5. 其他) B5 --> L10["LocaleContextHolder\n国际化语言上下文"] B5 --> L11["BeanFactory\n底层 IoC 容器"] class ROOT root; class B1,B2,B3,B4,B5 branch; class L1,L2,L3,L4,L5,L6,L7,L8,L9,L10,L11 leaf; class L1,L4,L7 highlight; 🌐 一、Web 请求上下文 ⚙️ 1.1 核心类与底层原理 RequestContextHolder(请求上下文持有者)通过 ThreadLocal(线程局部变量)将当前请求的 ServletRequestAttributes 绑定到当前线程。DispatcherServlet(Spring MVC 的前端控制器)在处理每个请求时,会自动调用 RequestContextHolder.setRequestAttributes() 将请求对象"挂"到当前线程上。 ...

十月 7, 2022 · 12 分钟 · 2418 字 · yaomingye

数据库迁移实战

🗄️ 数据库迁移实战:不停机迁移方案、数据一致性保障与工具选型全解析 从一个凌晨 3 点的故障说起 某电商平台的订单表 orders 有 2.3 亿行数据,运行在 MySQL 5.7 上,单表体积接近 400GB。团队计划将这张表迁移到 TiDB 分布式数据库,以应对即将到来的双十一流量峰值。 DBA 团队的迁移方案是: 凌晨 2 点,停止所有写入服务 用 mysqldump 导出全量数据(耗时 1 小时 20 分钟) 将 dump 文件导入 TiDB(耗时 3 小时) 凌晨 6 点 20 分,恢复写入服务 结果:凌晨 4 点 30 分,dump 文件导入到一半时报错——导出文件中有 3 行数据包含 MySQL 5.7 特有的 utf8mb4_general_ci 排序规则下的隐藏字符,TiDB 解析失败。此时 MySQL 5.7 已被设置为只读,TiDB 导入中断, 整个订单系统处于不可用状态 。 最终临时回滚 MySQL 只读限制,恢复业务。迁移失败,双十一扩容计划延期。 这次故障暴露了数据库迁移中的核心难题:如何在保证数据一致性的前提下,尽可能缩短甚至消除停机时间,并且始终保留可靠的回滚路径。 数据库迁移策略总览 数据库迁移不是单一操作,而是一整套工程方法论。先通过思维导图建立全局认知: flowchart LR classDef root fill:#0f172a,stroke:#3b82f6,stroke-width:2px,color:#bfdbfe,font-weight:bold; classDef branch fill:#2d1a05,stroke:#f59e0b,stroke-width:2px,color:#fde68a,font-weight:bold; classDef leaf fill:#1e1e24,stroke:#6b7280,stroke-width:1.5px,color:#e5e7eb; classDef highlight fill:#450a0a,stroke:#dc2626,stroke-width:1.5px,color:#fecaca,font-weight:bold; ROOT[数据库迁移策略体系] ROOT --> B1(1. 按停机时间分类) B1 --> L1["🛑 停机迁移\n• 停服→导出→导入→恢复\n• 停机: 小时至天级\n• 风险: 业务中断"] B1 --> L2["⚡ 零停机迁移\n• 双写/CDC/灰度切换\n• 停机: 秒级切换\n• 风险: 数据不一致"] B1 --> L3["🔄 滚动迁移\n• 按分片/租户逐批切\n• 停机: 每批秒级\n• 风险: 跨片依赖"] ROOT --> B2(2. 按数据同步方式分类) B2 --> L4["📦 全量+增量\n• 全量快照 + binlog 追赶\n• 代表: DTS/Canal/Debezium"] B2 --> L5["✍️ 双写\n• 应用层同时写新旧库\n• 全量回溯 + 双写 + 校验"] B2 --> L6["🔁 主从复制\n• 新库作为旧库的从库\n• 追平后切换"] ROOT --> B3(3. 按迁移目标分类) B3 --> L7["🏗️ 同构迁移\n• MySQL→MySQL 版本升级\n• 工具: gh-ost/pt-osc"] B3 --> L8["🔀 异构迁移\n• MySQL→TiDB/PostgreSQL\n• 需处理类型/SQL差异"] B3 --> L9["☁️ 上云迁移\n• 自建→RDS/云原生DB\n• 工具: DTS/DataX"] class ROOT root; class B1,B2,B3 branch; class L1,L2,L3,L4,L5,L6,L7,L8,L9 leaf; class L2,L4 highlight; 三类策略并非互斥——零停机迁移通常是"双写 + 全量快照 + 增量追赶 + 灰度切换"的组合。 ...

十月 6, 2022 · 9 分钟 · 1821 字 · yaomingye

CoAP 受限应用协议

📡 CoAP 受限应用协议:报文格式、通信模型与物联网实战全解析 从一个智能灯控场景说起 假设你正在开发一套智能路灯系统。每个路灯上有一颗低功耗 MCU(微控制器),通过 NB-IoT(窄带物联网)蜂窝网络上报状态、接收开关指令。MCU 的 RAM 只有 64KB,Flash 只有 256KB,网络带宽不到 100kbps,每月流量限额 30MB。 你能在这颗 MCU 上跑 HTTP 吗? 不能。 原因有三: HTTP 基于 TCP,TCP 三次握手 + TLS 握手需要至少 5 ~ 7 个往返(RTT),在 100kbps 窄带网络上耗时数秒 HTTP 头部是纯文本,一个 GET /status HTTP/1.1\r\nHost: ... 请求头轻松超过 200 字节,而传感器上报的有效数据可能只有 4 字节(一个温度值) TCP 连接要保持状态,MCU 内存不足以维护大量连接 CoAP (Constrained Application Protocol,受限应用协议)就是为这种场景设计的。它用 UDP 替代 TCP、用 4 字节定长二进制头部替代 HTTP 的文本头、用简单的重传机制替代 TCP 的复杂拥塞控制,让一颗 64KB RAM 的 MCU 也能参与到互联网架构中。 下面先用一段概念性代码感受 CoAP 的编程模型: ...

十月 5, 2022 · 11 分钟 · 2332 字 · yaomingye

从 Docker Compose 到 Kind

☸️ 从 Docker Compose 到 Kind:在 WSL 上用 Kind 入门 Kubernetes 全指南 📌 一、问题切入:你已经会用 Docker Compose,然后呢 假设你在 WSL(Windows Subsystem for Linux,Windows 内置的 Linux 子系统)上维护着一个项目, docker-compose.yml 里定义了 nginx、应用服务、Redis、MySQL 四个容器: version: "3.8" services: nginx: image: nginx:1.25 ports: ["80:80"] volumes: ["./nginx.conf:/etc/nginx/nginx.conf:ro"] app: build: ./app ports: ["5000:5000"] environment: REDIS_HOST: redis MYSQL_HOST: mysql depends_on: [redis, mysql] redis: image: redis:7-alpine mysql: image: mysql:8 environment: MYSQL_ROOT_PASSWORD: secret docker compose up -d 一键启动。但当你需要面对以下需求时,Compose 开始显得吃力: ...

十月 4, 2022 · 18 分钟 · 3803 字 · yaomingye
Cat Radio