
后端文档教程【免费下载链接】system-design-101Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.项目地址https://gitcode.com/GitHub_Trending/sy/system-design-101点击查看免费下载本文是开源仓库 System Design 101 中「Top 6 Cases to Apply Idempotency」指南的深度展开版围绕操作可能被重试、可能被多次执行这一前提逐一拆解 RESTful API、支付、订单、数据库、账号管理与分布式消息六大场景中的幂等性诉求并结合仓库内 如何避免双重扣款、失败重试策略、消息投递语义 等配套文档给出可直接落地的幂等键、重试退避、去重与补偿方案。读完本文你将能够判断一个操作是否必须幂等、选择正确的幂等实现层次并为一套面向生产环境的可靠系统设计出重试安全、扣款不重、下单不重、消息不重处理的完整防线。什么是幂等性先理解一次成功、多次无害幂等性Idempotency是指同一个操作被执行一次与被执行多次最终产生的状态是一致的。它尤其重要于那些可能被重试、可能被多次执行的场景——网络超时后的客户端重试、消息队列的重复投递、支付网关的回调重放都会让一个操作在物理上执行不止一次。从数学上讲一个操作是幂等的当且仅当f(f(x)) f(x)第一次执行改变了状态第二次及以后的执行不再产生新的变化。仓库文档 如何避免双重扣款 给出了一个更工程化的拆解方式恰好一次exactly-once 至少一次at-least once 至多一次at-most once。这两半分别由两种机制保证重试Retry提供至少一次保证——因为网络可能随时失败客户端必须敢于重发确保操作最终被送达幂等性检查Idempotency Check提供至多一次保证——服务端收到重复请求时能识别并丢弃确保操作只生效一次。配套的 消息投递语义 对这三档语义做了进一步界定投递语义含义典型适用场景At-most once消息最多送达一次可能丢失但不重复监控指标等可容忍少量丢失的场景At-least once消息不丢失但可能被重复投递数据重复影响不大、或消费端可去重的场景Exactly once既不丢失也不重复实现成本最高支付、交易、记账等金融场景且下游不支持幂等时幂等性正是在 at-least once 的基础上用应用层去重把重复执行挡在门外从而让系统整体呈现出 exactly-once 的行为。幂等键Idempotency Key幂等实现的通用载体在客户端与服务端之间幂等性通常通过幂等键落地。依据 如何避免双重扣款 的说明幂等键是由客户端生成的唯一值且在一定时间后过期UUID 是最常用的幂等键并被 Stripe、PayPal 等多家公司推荐使用发起幂等请求时把幂等键放进 HTTP 请求头idempotency-key: key_value。服务端收到请求后先以幂等键查询是否已处理过若未处理则执行并记录若已处理则直接返回首次执行的结果或确认状态不再重复执行。场景一RESTful API 请求——重试不改变资源状态核心诉求确保重试一次 API 请求不会导致同一操作被执行多次从而维持资源状态的一致。实现要点选择幂等的 HTTP 方法。REST 语义中GET用于读取、PUT用于整体替换资源、DELETE用于删除资源这些方法天然是幂等的同一请求重发任意多次资源最终状态不变。POST用于创建通常不幂等——这正是需要幂等键保护的典型对象。为不幂等的操作绑定幂等键。对POST这类创建型请求客户端在请求头携带idempotency-key服务端按键去重即可把不幂等的 POST变成业务上幂等的 POST。保持幂等方法的语义纯粹。PUT必须做到全量替换而不是追加修改否则第二次重放会基于已变化的状态产生错误结果DELETE重复执行应返回已删除/不存在的一致结果而非报错。场景二支付处理——绝不重复扣款核心诉求网络抖动、网关超时、回调重放都不能让用户被扣两次钱。支付网关本身就经常需要重试交易幂等性保证一笔订单只产生一次扣款。这是整个分布式系统中幂等性最关键的战场。结合 如何避免双重扣款支付侧的标准做法是重试保证至少一次。客户端因网络差、超时而重试支付请求例如图中第四次的尝试才成功请求可能被多次送到服务端。幂等键保证至多一次。每次支付请求都携带客户端生成的 UUID 幂等键idempotency-key: key_value支付服务按键落库并去重无论请求到达几次扣款动作只执行一次。重试要配合退避策略而不是无脑风暴式重试。仓库文档 失败重试策略 归纳了四种常见策略策略行为优点缺点Linear Backoff线性退避每次等待固定递增间隔实现简单、易理解高并发下易引发资源争用与重试风暴Linear Jitter Backoff线性抖动退避线性间隔外加随机抖动随机性打散各实例的重试时间降低同步重试概率基础间隔线性增长仍可能触发同步重试Exponential Backoff指数退避间隔按 1s、2s、4s、8s……指数增长通常设上限显著降低系统负载与重试碰撞概率适合高负载本可快速重试解决的场景反而被拖慢Exponential Jitter Backoff指数抖动退避指数间隔叠加随机抖动加性/乘性兼具指数退避优点进一步降低重试碰撞抖动较大时可能产生过长等待支付场景应优先采用带抖动的指数退避既保证重试最终成功又避免同时重试打垮下游。支付链路本身也要在每一环防重。参照 支付系统 的典型流程用户点击购买后生成支付事件并入库一个支付事件可能包含多个支付订单如一个购物车内多家卖家的商品支付执行器逐个调用外部 PSP 完成扣款成功后更新钱包、追加账本Ledger夜间再由 PSP/银行下发对账文件。这条链路上事件、订单、扣款、钱包入账、账本追加都需要各自的幂等保护否则任何一个环节的重放都会造成金额不一致。此外支付对账 明确指出即便系统实现了 exactly-once 语义仍可能存在各种意外差异对账系统是必须的安全网——通过比较电商订单、支付渠道交易记录、账本借贷记录发现并消除不一致。幂等性负责事前不重对账负责事后兜底。场景三订单管理系统——下单多次只成一单核心诉求用户或客户端重试、前端重复点击多次提交同一订单系统只创建一个订单并防止库存被重复扣减。实现要点客户端生成订单幂等键。下单请求携带idempotency-keyUUID服务端先查幂等表键已存在则直接返回原订单否则创建新订单并记录键。库存扣减必须幂等或有唯一约束兜底。库存流水表以订单 ID 商品 ID作为唯一约束详见下文场景四重复的扣减请求被数据库直接拒绝或让扣减以订单维度做去重保证同一订单只扣一次。超时重试与下单去重配合。下单请求超时后客户端重试是常态幂等键让第二次请求命中第一次的结果从源头杜绝重复下单、重复扣库存。场景四数据库操作——事务重放不改变最终状态核心诉求一条事务/一条 SQL 被重新执行重放时数据库状态不应发生超出首次执行的改变。实现要点善用原子性幂等写入。将先查后写改为条件写入/冲突覆盖INSERT ... ON CONFLICT DO NOTHING / DO UPDATEUPSERT保证同一行数据只被初始化一次INSERT IGNORE等数据库方言同理。重复执行对已有数据无影响。用唯一约束做最终防线。这是最硬核的幂等保障。消息投递语义 指出在 at-least once 语义下给每条消息或业务记录一个唯一键写入数据库时遇到重复直接拒绝——唯一索引将重复写入变成必然失败的确定性结果。注意与事务隔离级别的配合。幂等写入在高并发下要防止两个请求同时都判定未存在、都去写入唯一约束与适当的事务隔离级别可参考仓库 数据库隔离级别能共同保证并发下仍只有一个生效。场景五用户账号管理——注册不重复、重置只一次核心诉求重试注册请求不会创建多个用户账号多次密码重置请求最终只产生一次重置动作。实现要点注册场景用唯一标识 幂等键双保险。邮箱、手机号、用户名上加唯一索引是数据库层面不可重复注册的硬约束客户端携带的idempotency-key则保证同一次注册请求即使被重试 N 次也只走一遍注册流程、只发一封验证邮件。密码重置场景以重置令牌为核心。重置请求生成一次性令牌token令牌使用即失效——后续任何重复的重置请求要么命中同一个令牌、要么因令牌已失效被拒绝从而保证多次请求、一次重置。同时可对同一账号的重复重置请求按幂等键去重避免短信/邮件验证码被重复下发。写操作配合唯一键落库。账号表、重置令牌表均可通过唯一约束承接重复写入同场景四让数据库成为幂等性的最后一层保障。场景六分布式系统与消息——队列重放不产生重复处理核心诉求消息队列中的同一条消息被重新投递/重新处理时不应造成重复处理或重复副作用。需要实现能多次处理同一条消息而不产生副作用的处理器。这是分布式系统幂等性的核心应用可以分成三层来看投递侧理解 at-least once 是常态。以 Kafka 为例仓库文档 Kafka 会丢消息吗 指出生产者侧需要配置合理的acks与retries才能确保消息送达消费者侧不同的提交commit方式会影响语义——自动提交可能在消息真正处理完之前就提交了 offset一旦消费者在中间宕机部分消息会未被处理但已提交或反过来被重新消费。因此消费端必须假定同一条消息可能被处理多次。消费侧处理函数必须幂等。最直接的做法是在消费端去重给每条消息携带唯一键业务 ID 或消息 ID消费时先查重如通过唯一索引写入、幂等表、或 布隆过滤器 这类空间高效的概率结构做大规模去重再执行业务逻辑。布隆过滤器可回答URL/消息是否已存在false negative 不会出现false positive 可用唯一索引二次兜底。状态侧副作用要可重放。更新类消费写库、扣库存、发通知都要按场景一至四的方式做成幂等写或采用本地事务表 消息表如 Outbox 模式保证消息与业务状态同时落库避免状态变了但消息丢了或消息重了但状态没跟着重的错位。小结六大场景的幂等方案速查场景风险点推荐方案RESTful API 请求POST 重试导致重复创建/变更用 PUT/DELETE 等幂等方法POST 绑定幂等键支付处理重试导致重复扣款幂等键 指数抖动退避 对账兜底订单管理重复提交产生重复订单、重复扣库存订单幂等键 库存流水唯一约束数据库操作事务重放改变状态UPSERT、唯一索引、唯一键去重用户账号管理重复注册、重复重置邮箱/手机号唯一约束 一次性令牌 幂等键分布式消息队列重放导致重复处理消息唯一键 消费端去重唯一索引/幂等表/布隆过滤器 幂等处理器幂等性不是一个独立的功能模块而是一套贯穿客户端重试、网关透传、服务端去重、数据库约束、消息消费的设计纪律。把至少一次的重试与至多一次的幂等检查组合起来你的系统就能在不确定的网络世界里给出确定的业务结果——这正是 System Design 101 仓库想传达的核心理念用简单清晰的工程手段构建可靠的大规模系统。本文的六类场景与配套方案均可回到仓库对应文档继续深挖如何避免双重扣款幂等键与 exactly-once 拆解、失败重试策略四种退避算法、消息投递语义三档语义与去重、支付系统支付链路各环节、支付对账对账安全网、Kafka 会丢消息吗消息生命周期与提交策略、布隆过滤器去重大规模去重。赞分享后端文档教程【免费下载链接】system-design-101Explain complex systems using visuals and simple terms. Help you prepare for system design interviews.项目地址https://gitcode.com/GitHub_Trending/sy/system-design-101点击查看免费下载相关推荐System Design 101负载均衡算法与应用场景System Design 101负载均衡算法与应用场景 你是否曾遇到过网站访问缓慢、服务频繁崩溃的情况在高并发场景下单一服务器往往难以承受巨大的流量压力后端文档教程System Design 101 之 Kafka 101用 8 个步骤掌握 Kafka 核心原理与实战要点System Design 101 之 Kafka 101用 8 个步骤掌握 Kafka 核心原理与实战要点 导读 Kafka 是当前分布式系统中最流行的分布后端文档教程对象存储的 6 大核心使用场景Object Storesystem-design-101 深度解析对象存储的 6 大核心使用场景Object Storesystem design 101 深度解析 对象存储Object Storage是当前云原生时后端文档教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考