美文网首页
弹力设计之幂等性设计

弹力设计之幂等性设计

作者: 匠丶 | 来源:发表于2021-09-24 10:08 被阅读0次

    所谓幂等性设计,就是说,一次和多次请求某一个资源应该具有同样的副作用。用数学的语言来表达就是:f(x) = f(f(x))。

    比如,求绝对值的函数,abs(x) = abs(abs(x))。

    为什么我们需要这样的操作?说白了,就是在我们把系统解耦隔离后,服务间的调用可能会有三个状态,一个是成功(Success),一个是失败(Failed),一个是超时(Timeout)。前两者都是明确的状态,而超时则是完全不知道是什么状态。

    比如,超时原因是网络传输丢包的问题,可能是请求时就没有请求到,也有可能是请求到了,返回结果时没有正常返回等等情况。于是我们完全不知道下游系统是否收到了请求,而收到了请求是否处理了,成功 / 失败的状态在返回时是否遇到了网络问题。总之,请求方完全不知道是怎么回事。

    举几个例子:
    订单创建接口,第一次调用超时了,然后调用方重试了一次。是否会多创建一笔订单?
    订单创建时,我们需要去扣减库存,这时接口发生了超时,调用方重试了一次。是否会多扣一次库存?
    当这笔订单开始支付,在支付请求发出之后,在服务端发生了扣钱操作,接口响应超时了,调用方重试了一次。是否会多扣一次钱?

    因为系统超时,而调用户方重试一下,会给我们的系统带来不一致的副作用。

    在这种情况下,一般有两种处理方式。

    1、一种是需要下游系统提供相应的查询接口。上游系统在 timeout 后去查询一下。如果查到了,就表明已经做了,成功了就不用做了,失败了就走失败流程。
    2、另一种是通过幂等性的方式。也就是说,把这个查询操作交给下游系统,我上游系统只管重试,下游系统保证一次和多次的请求结果是一样的。

    对于第一种方式,需要对方提供一个查询接口来做配合。而第二种方式则需要下游的系统提供支持幂等性的交易接口。

    全局 ID

    要做到幂等性的交易接口,需要有一个唯一的标识,来标志交易是同一笔交易。而这个交易 ID 由谁来分配是一件比较头疼的事。因为这个标识要能做到全局唯一。

    如果由一个中心系统来分配,那么每一次交易都需要找那个中心系统来。 这样增加了程序的性能开销。如果由上游系统来分配,则可能会出现 ID 分配重复的问题。因为上游系统可能会是一个集群,它们同时承担相同的工作。

    为了解决分配冲突的问题,我们需要使用一个不会冲突的算法,比如使用 UUID 这样冲突非常小的算法。但 UUID 的问题是,它的字符串占用的空间比较大,索引的效率非常低,生成的 ID 太过于随机,完全不是人读的,而且没有递增,如果要按前后顺序排序的话,基本不可能。

    在全局唯一 ID 的算法中,这里介绍一个 Twitter 的开源项目 Snowflake。它是一个分布式 ID 的生成算法。其核心思想是,产生一个 long 型的 ID,其中:

    41bits 作为毫秒数。大概可以用 69.7 年。
    10bits 作为机器编号(5bits 是数据中心,5bits 的机器 ID),支持 1024 个实例。
    12bits 作为毫秒内的序列号。一毫秒可以生成 4096 个序号。

    其他的像 Redis 或 MongoDB 的全局 ID 生成都和这个算法大同小异。也可以根据实际情况加上业务的编号。

    相关文章

      网友评论

          本文标题:弹力设计之幂等性设计

          本文链接:https://www.haomeiwen.com/subject/jfrygltx.html