分布式高并发环境下的幂等控制

背景

现在的大型互联网站系统都是基于SOA或者微服务架构设计的,系统之间通过远程服务调用或者异步消息等方式进行交互。分布式系统的环境非常复杂,网络抖动或者服务端系统响应慢都有可能造成重复的服务调用或者消息的重发,当服务端对于请求的响应或者消息的处理涉及到数据的变更时,可能会造成极大的危害。重复的请求或消息的后果在支付或者账务等系统中尤为严重,我们在设计服务端系统地时候,需要进行幂等控制。

何为幂等

幂等概念来自数学,表示N次变换和1次变换的结果是相同的。在我们的讨论的场景下指,客户端在通过同步服务调用或者异步消息与服务端交互而没有达到预期结果时,可能会进行多次交互,服务端为避免多次重复地处理而对服务资源产生地不良影响,必须要对同一请求的多次调用进行幂等控制。
  业务开发中,经常会遇到重复提交的情况,无论是由于网络问题无法收到请求结果而重新发起请求,或者是服务端系统响应慢地情况。在支付或者账务等系统这种重复提交造成的问题有尤其明显,比如:向支付宝发起支付请求,由于网络问题或系统BUG重发,支付宝应该只扣一次钱。很显然,声明幂等的服务认为,外部调用者会存在多次调用的情况,为了防止外部多次调用对系统数据状态的发生多次改变,将服务设计成幂等。

幂等控制的解决方案

服务端系统对服务调用或者异步消息地处理,总结为就是对数据资源的增、删、改、查,针对这四种情况,我们来看一下如何进行幂等控制。

查询

查询操作是天然幂等的,对数据库而言它不会涉及到数据的更改,以下语句:select balance from account where account_no = '666666',不管执行多少次都不会对数据表中的数据造成影响。

删除

删除操作虽然涉及到数据表的变动,但在某些情况下它也是幂等的,比如下面根据订单号(支付系统中同一个订单号不会生成两次,一般的做法都是时间+sequence方式生成)删除订单的操作:delete from order where order_id = '2017011312345678',不管执行一次还是多次,在数据表上体现地变化都是一样(虽然可能对客户端来讲返回结果不一样,当账户存在时,第一次删除返回1,后面的删除操作都返回0)。设计服务端数据模型时,要避免删除的数据再次生成(每个字段都一样),否则多次执行删除有可能造成不利影响(把别人刚生成的数据又删掉了)。

新增

新增地数据中一个或多个字段能够唯一识别这条数据,那么我们在设计数据表时将其设置为主键或者唯一索引或者唯一组合索引,例如账号就是账户表中的主键,在创建账户时,如果出现重复创建的情况,在账户表中插入数据地时候,会出现幂等冲突,数据库的存储机制帮我们控制了幂等;

修改
  • 利用去重表控制幂等,例如,在SOA架构下支付系统发起分布式事务同步调用账务时,账务首先是插入事务表,事务号transactionId是事务表的主键,然后在进行账户表等其他数据表的修改操作。由于事务号是唯一的,所以重复地调用会通过被事务表幂等住;
  • 同样地,系统之间通过异步消息进行交互时,当订阅方系统响应慢时,消息中心很有可能对同一条消息进行重发,这个时候订阅方在根据消息内容进行业务处理之前,可以先将消息插入自己的消息表(消息的messageId是唯一的),以此来防止同一个消息(同样的messageId)的重复处理。
  • select+update的方式幂等,例如在进行同步调用或者消息处理地时候,我们可以根据调用参数或者消息内容与与从db中查询出来数据的时间字段进行比较,如果数据库中查询出来的数据进行比较如果数据一致,则进行幂等控制。
  • 乐观锁的方式,update with condition,我们在更新数据表中的数据时候,可以利用版本号或者时间戳字段(时间精度足够高)做乐观锁:
    update order set status = 'C', version=version+1 where order_id = '2017011312345678' and version = #version#
    或者
    update accout set balance = 1000, trans_dt = #trans_dt# where account_no = '666666' and trans_dt < #trans_dt#
    需要注意的是,在使用乐观锁做更新操作时,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,锁表在高并发的环境下是灾难性的。
总结

幂等性使我们在设计系统时需要着重考虑的问题,尤其是涉及到重要数据处理的时候,比如支付或者账务系统的订单、账户都能数据,既要满足高并发的需要,又要准确处理每次请求,不能出现重复订单或者记错账的情况。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,172评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,346评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,788评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,299评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,409评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,467评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,476评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,262评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,699评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,994评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,167评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,499评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,149评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,387评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,028评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,055评论 2 352

推荐阅读更多精彩内容