前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >幂等是什么及Ansible幂等实现源码解析

幂等是什么及Ansible幂等实现源码解析

作者头像
运维部落
发布2021-02-23 16:39:45
1.4K0
发布2021-02-23 16:39:45
举报
文章被收录于专栏:运维部落运维部落

运维就要无所不能,无所不会

  • 一、幂等概念
  • 二、幂等使用场景
  • 三、幂等实现方案
    • 3.1 db去重表
    • 3.2 MVCC(多版本并发控制)
    • 3.3 状态机约束
  • 四、Ansible 幂等实现源码剖析

幂等是什么及Ansible幂等实现源码解析

大家好,我是史丹利「Stanley」,昨天被老板「粉丝」批评说近段时间文章太软。。。今天我们硬一把,来聊聊幂等。先上图

Ansible-Copy-1st

Ansible-Copy-2st

Notice: 第一次执行结果和第二次一致,所以第二次执行命令时并没有实质变更,即不对目标对象做变更。

一、幂等概念

幂等(idempotence)一词原为数学上的概念,用一个最直观的数学式子表达为:

f(f(x)) = f(x)

对应到软件开发领域,即为同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的,实际上就是接口的可重复调用(包括时间和空间上两个维度)。

不是要求返回值完全相同,而且是指后续多余的调用对系统的数据一致性不造成破坏

  • 写操作

如果第一次写入是成功的,后续的写入应该抛出异常或者空操作,或者执行了写入但是未对数据造成变化。

作业:数据库如何保证写操作幂等?

  • 读操作

读取类操作,需要保证其实现上是真正的读取,不能在读操作中夹带写操作。如HTTP get method

好的如:秒杀按钮只能点击一次,之后会变成灰色无法点击。如微信红包

差的如:某东秒杀按钮可重复点击,每次返回“茅台已被抢完”...

二、幂等使用场景

  • 应用场景类
    • 某东抢茅台
    • 某信抢红包
  • 技术场景类
    • ansible执行命令,如符合幂等刚不会重复执行
    • curl -X GET HTTPURL

三、幂等实现方案

方式不一,具体和业务场景有关联性。

3.1 db去重表

订单支付信息录入至去重表,每次支付请求先录入订单信息再执行支付行为。

如插入成功,且支付,如插入失败。则抛异常

图1-1:支付场景时序图

3.2 MVCC(多版本并发控制)

数据库并发请求场景下,根据唯一字段判断最新状态,唯一字段可以是版本号、JS生成的唯一码、表唯一索引等。如果唯一字段不存在,则无法获取数据或执行增、删、改等变更操作

update table_name set deposit = deposit-#{payment}, version = version + 1 where orderId = #{orderId} and version = #{version}

3.3 状态机约束

通过程序代码逻辑等技术手段实现,在代码段是增设状态判断,如果状态机已处于下一个状态,这时候不能往回跳转到上一个状态,通过状态机的跳转约束,可以做到有线状态机的跳转约束,比如基于状态机实现的乐观锁:

update table set status=next_status where id=#{id} and status=#{status}

当前状态第一次被修改后,状态被修改为下一种状态,同一记录针对当前状态的其他修改会失败,程序跑出异常,这常见于并发场景的修改。

如下 Ansible 即通过该方式实现。

四、Ansible 幂等实现源码剖析

以文首 copy 模块为例。

# 文件所在位置
ansible/modules/files/copy.py

ansible-copy模块逻辑

  • 幂等核心源码如下「请留意注释」
def main():
  ...
  # 调用sha1先做md5校验
  checksum_src = module.sha1(src)
  checksum_dest = None
    # Backwards compat only.  This will be None in FIPS mode
    try:
        md5sum_src = module.md5(src)
    except ValueError:
        md5sum_src = None
  # 设置状态机 changed
    changed = False   
    
    ...
    
  if checksum_src != checksum_dest or os.path.islink(b_dest):
    # 开始文件copy
    ....
         # 成功copy
        changed = True
    else:
         # 如果文件已经存在,且md5一样,则不执行操作。
        changed = False
    
  

Notice: Ansible 的幂等通过各模块或插件, AdHocPlaybook 只实现了命令分发执行和结果收集展示

参考: 幂等实现[1]


~ over ~ 你学废了吗?

参考资料

[1]

幂等实现: https://segmentfault.com/a/1190000015884659

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-01-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 运维部落 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 幂等是什么及Ansible幂等实现源码解析
    • 一、幂等概念
      • 二、幂等使用场景
        • 三、幂等实现方案
          • 3.1 db去重表
          • 3.2 MVCC(多版本并发控制)
          • 3.3 状态机约束
        • 四、Ansible 幂等实现源码剖析
          • 参考资料
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档