千寻

道路很长, 开始了就别停下!

0%

幂等性设计

简介

服务间调用有三种状态:成功;失败;超时。前两个状态明确,但超时状态完全不知道是什么状态。

可能是请求没有到达,也可能是请求到达了,但返回结果没有到达。我们不知道下游系统是否收到了请求,而收到了请求是否处理了。

例如:

  • 创建订单接口,第一次调用超时,然后client重试了一次,是否会多创建一笔订单?
  • 用户付款时,服务端发生扣款行为,接口响应超时,调用方重试了一次,是否会多扣一次钱?

解决方案:

  • 下游系统提供查询接口,上游系统在timout后去查询一次,并根据结果执行不同的策略
  • 幂等处理。上游只管重试,下游系统保证一次和多次的请求结果是一样的。(推荐方式)

全局id

Twitter的分布式自增ID算法snowflake

snowflake的结构如下(每部分用-分开):

0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000

  • 第一位为未使用
  • 接下来的41位为毫秒级时间(41位的长度可以使用69年)
  • 然后是5位datacenterId和5位workerId(10位的长度最多支持部署1024个节点)
  • 最后12位是毫秒内的计数(12位的计数顺序号支持每个节点每毫秒产生4096个ID序号)

一共加起来刚好64位,为一个Long型。(转换成字符串后长度最多19)

snowflake生成的ID整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和workerId作区分),并且效率较高。经测试snowflake每秒能够产生26万个ID。

本机测试,每秒产生约4W个id

处理流程

以交易为例,当收到交易请求时,先去查,有没有创建过?如果查到了就不做处理

一般可以采用乐观锁,基本CAS方式。

1
update 订单表 set  status="交易成功"  where id=#orderId# and status="等待买家确认收货"

或者

以论坛发贴为例,在表单中隐藏一个token,防止用户多次点击表单提交按钮。防重复。