-
灰度发布与蓝绿部署:流量切分的工程实现
发布本身不是难点,难点是新版本有问题时能在多大范围快速止损。滚动发布逐个替换实例,回滚要数十分钟,这段时间全部用户都在受影响面。蓝绿和灰度解决的都是这件事:把"回滚"换成"切流",把止损时间从重建实例的量级压缩到改一次路由配置的量级。 蓝绿与灰度的差异 蓝绿部署 维护两套完整环境。当前流量全走绿环境,新版本部署到蓝环境完成自检验证,通过后一次性从绿切到蓝,原绿环境保留一段时间作为回滚目标——回退就
Riven
-
一个桌面工具箱的架构取舍:C++/Qt 客户端 + Go 服务端
做桌面工具这类软件,技术选型的讨论往往陷入"哪个语言更好"的口水仗,但真正决定成败的是 职责怎么划分 。我参与开发的 7AA7工具箱是一套 C++/Qt 客户端加 Go 服务端的组合,这篇文章把当年几个关键取舍的思考过程摊开,不讲结论的正确性,讲推理的过程。 一、桌面端:为什么是 C++/Qt 桌面端的候选当时有几条路:Electron/Web 技术栈、C#/.NET、Qt/C++、Rust 新兴
HexCreek
-
分布式事务:2PC、TCC、Saga 与本地消息表
下单要扣库存、创建订单、冻结优惠券,三个动作跨了三个库。单机事务保证的同生共死在这里失效。所有分布式事务方案处理的其实是同一个困境:参与者没有共享的内存和锁表,谁也无法替谁做承诺,只能靠协议协商。差别在于承诺的强度,以及维持这个强度要付多少代价。 本地事务与分布式事务的差别 本地事务依赖数据库内部的锁、回滚段和原子落盘。事务边界内的中间状态对其他事务不可见,崩溃时由数据库自己用 undo 日志回退
AsyncLab
-
高并发第一课:无状态设计与水平扩展
谈高并发时,话题经常一上来就跳到缓存、分库分表、消息队列。这些手段都对,但都属于"单机能力之外的补救"。真正决定一个系统能不能横向长大的,是更基础的一件事:服务本身能不能无状态地复制。这一层没打通,加多少台机器都是在跟自己较劲。 有状态服务的扩展障碍 先看反例。一个典型的有状态服务,会话数据存在进程内存里:用户登录后,session 对象挂在当前 JVM 或当前进程的哈希表上。此时来了第二台机器,
栈外游
-
前后端分离架构演进:从模板渲染到 API 优先
"前后端分离"在国内技术圈流行了十年以上,如今已经很少有人把它当成新概念讨论。但有意思的是,近几年随着服务端组件、岛屿架构等形态的出现,渲染逻辑又开始往服务端回流。回头看这段演进,驱动变化的从来不是某种风格的优劣,而是页面复杂度、团队协作方式和终端数量这三件事的实际变化。 服务端渲染:老而弥坚的形态 模板渲染的流程很朴素:请求进来,服务端查数据、填模板、吐 HTML,浏览器直接展示。它的优势在今天
Talen
-
消息队列入门:削峰、解耦与最终一致性
消息队列是后端架构里最容易被"上车"的组件:加一层 MQ,流量尖峰扛住了,系统之间也不直接调用了,看上去两全其美。但队列解决的是时间维度上的耦合,代价是把一次调用拆成了"发"和"收"两段,中间多了消息丢失、重复投递、顺序错乱等一整排新问题。把它用对的前提,是先想清楚它到底在解决什么。 为什么需要队列 最原始的场景是同步阻塞。下单之后要发短信、算积分、推仓库,这些动作加起来要一两秒,用户却只关心下单
North 北境
-
缓存策略实战:旁路缓存、穿透、击穿与雪崩
缓存是性能优化里收益最直接的一招,也是出问题时最难查的一类。数据不对、缓存雪崩、重建风暴,这些事故的共同点是:缓存引入的不只是速度,还有一套独立于数据库的失效逻辑。把缓存当成"加一层就快"的透明加速器,迟早要为它补课。 读写模式先选对 缓存读写有三种基本形态,选哪种决定了后面所有问题的形状。 旁路缓存(cache aside)是最常见的形态:读的时候先查缓存,没有就查库再回填;写的时候只更新数据库
Riven
-
事件驱动架构:事件溯源与 CQRS 的适用场景
服务之间用事件通信,看起来只是把同步调用换成异步消息。真正的差别在于:事件里带回多少信息、谁来使用它、以及系统的真实状态到底存在哪里。把这三件事想清楚,才知道该选事件通知、事件携带状态转移还是事件溯源,以及是否需要 CQRS。 三种事件模式的差异 事件通知 是最小的一类。事件只描述"发生了什么",几乎不带数据,订阅方要主动回查。 { "eventType": "OrderPaid", "order
Byte 吴
-
服务治理:注册发现、熔断与限流的工作原理
单机应用里调用就是一次函数调用,失败立即抛异常。服务拆开后调用跨了网络,故障从"失败"扩展成"慢""超时""半死不活"三种新形态,而且往往先慢后挂、局部扩散。注册发现、熔断、限流处理的分别是"调用谁""要不要继续调""允许多少进来"。 注册发现与健康检查 服务实例的 IP 和端口不是固定的:扩缩容、故障迁移、滚动发布都会让实例列表变化。注册中心维护的就是这份动态清单。 健康检查 决定一个实例什么时
苏念禾
-
单体到微服务:什么时候才真的需要拆
关于"要不要上微服务"的讨论里,情绪往往盖过事实。一边是把单体等同于"落后",另一边是把微服务嘲讽为"把网络当函数调"。抛开这些口水,工程上真正要回答的只有一个问题:当前系统的哪些痛点,是非拆不可的?如果列不出具体条目,拆分就是在用确定的复杂度去换一个想象中的收益。 单体被低估的优势 单体最直接的好处是简单。一个进程、一份配置、一条部署流水线,本地起一套环境就能跑通完整业务。函数调用是进程内的,参
KernelPan
-
架构评审怎么做:一份可落地的检查清单
很多团队的架构评审有两个极端:一种是走形式,方案讲完二十分钟没人提问,上线后集体救火;另一种是挑刺会,资深工程师围着命名和框架选型争论,会议结束没人记得决定了什么。两者源于同一个问题——没说清评审要产出什么。 什么时候做评审 评审应该在方案定稿前,而不是上线前,这个差别决定了能改动的上限。 代码写完之后评审,能提的意见只剩"这里重构一下比较好",而重构排期通常永远排不上。评审对象是设计:依赖假设是
苏念禾
-
领域驱动设计入门:限界上下文与聚合根
一个订单系统迭代到第三年,代码里出现了四个不同含义的"订单"。交易域的订单是支付前的待付款单据,履约域的是待发货清单,结算域的是待开票账目,客服域的是投诉凭证。四者都叫 Order ,却因为同名被反复复用、强行兼容。这不是命名问题,是模型边界缺失。领域驱动设计处理的核心正在于此:在复杂业务域里切出清晰的语言边界与一致性边界。 语言先于代码 DDD 强调先建立统一语言,再写第一行代码。这不是仪式感,
Schema 李
-
技术债的量化与管理:从感知到偿还
"这块代码该重构了"很难争取到资源,它描述的是主观感受,而排期表上每一行都是可交付的功能。技术债管理的第一步不是动手重构,而是把感受翻译成能用同一套标准比较的东西——否则偿还永远排在交付之后,直到某天以故障的形式强制偿还。 债务先要分类 不同类型的债,利息形式和偿还方式完全不同,混在一起算总账必然失真。 类型 典型表现 主要利息形式 代码债 重复逻辑、超长函数、命名混乱 每次改动耗时增加、改动诱发
码同客
-
幂等设计的工程实践:重复请求防护体系
用户点了一次"支付",结果扣了两笔钱。这类事故几乎总能追溯到同一个原因:某个环节没做幂等。另一面是,团队知道要做幂等,于是给每个接口都加了一张去重表,最后系统又慢又复杂,边角场景上依然会漏。 幂等不是"加个锁"或"加张表",而是一套需要分层的防护体系。 幂等的严格定义 数学上的定义:对同一个操作的多次执行与一次执行产生的 效果 相同。 注意定义里说的是"效果",不是"返回值"。这一点常被误读,导致
顾清池
-
多租户架构设计:隔离级别与数据模型
一套系统同时服务多家客户,每家客户看不到别人的数据,还能各自配置、各自扩容、各自退租——这就是多租户。听起来简单,真正落地时你会发现,难点从来不是"加个 tenant_id 字段",而是从这一刻起,系统的每一个查询、每一条索引、每一次统计、每一次数据导出都被这个字段绑住了。 三种隔离形态 隔离方案的选择,本质是在隔离强度和单位成本之间做取舍。 形态 隔离强度 单租户成本 运维复杂度 适用客户 独立
码同客
-
API 网关设计:路由、鉴权与限流的职责边界
所有外部流量汇聚到一个入口,天然适合做统一处理。问题是"统一处理"很容易失控:路由、鉴权、限流、日志、协议转换、数据聚合、业务校验、流程编排越堆越多,网关从基础设施变成最复杂的单点,改一行配置要全公司排期。划清职责边界,比挑选具体的网关实现更重要。 网关该做与不该做 判断标准可以简化为两条: 是否与传输协议相关 ; 是否需要对所有服务一致执行 。满足任一条倾向放网关,都不满足就该放回业务服务。 适
苏念禾
-
可观测性三支柱:日志、指标与链路的协同
线上出问题时的第一诉求永远是"发生了什么"。而常见的处境是:监控面板一片绿,用户投诉却有几十条;或者告警显示某个接口错误率上升,翻遍日志找不到一条异常。缺的不是数据,是数据之间的关联,以及据此回答未知问题的能力。 三者各自回答什么 三类数据的结构决定了各自的能力边界,用错地方就会觉得"什么都没有"。 指标(Metrics) 是聚合后的数值时间序列:QPS、错误率、P99 延迟、队列深度。它的强项是
码同客
-
服务间通信选型:REST、gRPC 与消息队列
讨论服务间通信时,最常见的误判是把问题理解成"哪种协议更快"。沿着这条路走下去就变成基准测试数据的比拼,最后得出"gRPC 比 REST 快"这个既正确又没什么用的结论。 真正的差别在 通信语义 。协议只是语义的载体,语义决定了你的系统怎么失败、怎么重试、怎么演进。 三种通信语义 维度 REST gRPC 消息队列 语义 同步请求-响应 同步强类型 RPC 异步事件传递 调用方是否等待结果 是 是
陆知远