A和B接口同时修改table字段,无法确认调用顺序

本文涉及的产品
Serverless 应用引擎 SAE,800核*时 1600GiB*时
性能测试 PTS,5000VUM额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 在互联网应用开发中,经常会碰到多个接口同时需要修改数据库表字段的情况。然而,由于无法确认接口调用的顺序,可能会导致数据冲突和一致性问题。本文将介绍一种解决这一问题的方法,通过合理的设计和技术手段,确保同时修改table字段的操作能够顺利进行,数据一致性得到保障。

先描述下问题原因,我先文字描述,再画了个流程图。

描述

AB两个接口更新同一个表的字段,但是以B接口下发数据为准,上游调用A接口的同时调用C接口,C接口再同时调用B接口,理论情况下更新时间是按着A先插入了tabel的字段,B再进行更新,最终数据是以B接口下发数据为准的,但由于A接口下发业务逻辑复杂,导致短时间A接口未提交事务时B接口被调用就进行了更新并提交事务导致A接口的事务提交覆盖了B操作,但更可怕的就是A还未提交事务,表中无数据可更新,B无法更新的情况如何更新数据?目前方案在B接口调用时放入缓存数据,在A接口被调用时缓存中有数据则更新缓存中的数据,没有则表明此时B还未被调用则不更新,常规的发生异常或者B后提交事务可以解决,但是A未提交事务时,B无法更新的情况如何处理?

image.png

然后说下场景:order服务统一下发数据,异步调用RPCa和RPCc,order服务不关心AC是否调用成功,A调用失败也不会回滚C,C同理。A插入数据,B根据条件更新table中的某些数据。

问题

A事务还未提交时,B被调用,B无法更新数据

A下发数据异常导致B无法更新数据

在什么节点下删除缓存

是分布式事务吗?

当然不是,AC被调用就是线程隔离的,并且其中一个事务回滚不影响另一个事务。

思路

A就不需要insert所需数据,调整字段类型为null,当B被调用时更新。但是既然无法保证调用顺序,作废

是否能够保证B永远在A被调用后执行?不能

在B被调用就放入缓存,然后Ainsert的时候取缓存的值,缓存有数据ok,没数据不更新,在A insert提交事务后再次触发判断缓存是否有数据,有更新,无的话就说明B还未被调用,B正常去更新就好了,这样只要B成功调用不管是否更新,A被调用时提交事务前后都能更新数据,如果A提交了事务缓存都没值,B也能顺利更新,即便A事务发生回滚再次被调用时也会更新成正确数据。代码比较简单就不上了。

4.能不能当B被调用时先查询是否有数据,没有的话先阻塞,等A提交事务后再被唤醒?可能不行,因为接口肯定调用就超时了。

5.删除缓存节点的话,等业务流程关闭的时候进行删除就可以了。
  1. 并发控制机制
    为了解决同时修改table字段的调用顺序问题,我们需要引入并发控制机制。最常用的并发控制机制是事务。事务提供了一种机制,可以保证一组操作作为一个逻辑单元被执行,要么全部成功,要么全部失败。在这种方式下,我们可以通过对数据库操作进行事务封装,确保同时修改table字段的一致性。

  2. 设计适应并发修改的数据结构
    为了适应同时修改table字段的场景,我们需要针对具体的应用场景设计适合的数据结构。常见的做法是引入版本号或时间戳字段,并将其作为修改字段时的判断条件。这样,在并行修改时,只有满足特定条件的修改操作会被执行,避免了数据冲突。

  3. 分离读写操作
    为了进一步提高并发性能,可以将读操作与写操作进行分离。通过引入读写分离机制,将读操作路由到读库,将写操作路由到写库,可以提高系统的并发处理能力。这样,在同时修改table字段的情况下,不会出现因为读写操作的争抢而导致的性能瓶颈。

  4. 异步消息队列
    另一种解决同时修改table字段的调用顺序问题的方法是使用异步消息队列。当多个接口需要修改同一数据库表的字段时,可以将这些修改操作作为消息发布到消息队列中。然后,通过消费者从消息队列中获取消息,并按照特定的顺序进行处理。这样,即使无法确定接口调用的顺序,也可以通过消息队列的有序性保证数据一致性。

  5. 数据库级别的锁机制
    除了事务和异步消息队列,数据库本身也提供了并发控制的手段。例如,通过行级锁或表级锁,可以限制同时修改table字段的操作。在数据库中,可以根据具体情况选择适合的锁机制,在保证数据一致性的前提下,提高系统的并发性能。

  6. 结论
    同时修改数据库表字段的调用顺序是互联网应用开发中常见的问题。通过合理的设计和技术手段,我们可以解决这一问题,确保数据一致性和系统的并发性能。在具体的应用场景中,可以根据需求选择适合的并发控制机制,并结合数据结构设计、读写分离、异步消息队列和数据库级别的锁机制等手段,保证同时修改table字段的操作能够顺利进行。

参考文献:
[1] Gray, J. D., & Reuter, A. (1993). Transaction processing: concepts and techniques (Vol. 75). Elsevier.
[2] Shi, K., Wang, S., Jin, H., Wang, X., & Luo, J. (2016). A distributed low-latency Transaction Processing System for Web Services. IEEE Transactions on Services Computing, 9(4), 545-558.
[3] Stonebraker, M., Hellerstein, J. M., & Hamilton, J. (2013). Architecture of a database system. Foundations and Trends® in Databases, 5(4), 197-246.

目录
相关文章
|
缓存 测试技术
podam mock 对象部分字段没有赋值问题
本文主要分析使用 podam mock 对象时,部分字段无法自动赋值的原因,并给出解决方案。
|
5月前
|
Python
定义字段
定义字段。
20 1
|
存储
PG11新特性解读:新增非空默认值字段不需要重写表
PG11新特性解读:新增非空默认值字段不需要重写表
156 1
|
缓存
A和B接口同时修改table字段,无法确认调用顺序
先描述下问题原因,我先文字描述,再画了个流程图。
100 0
A和B接口同时修改table字段,无法确认调用顺序
|
存储 Java 索引
Class文件结构介绍[访问标志,类索引,父类索引,接口索引集合]
在常量池结束后,紧接着的两个字节代表访问标志(access_flags),这个标志用于识别一些类或者接口层次的访问信息,包括:这个Class是类还是接口,是否定义为public类型,是否定义为abstract类型,如果是类的话是否被声明为final等,
Class文件结构介绍[访问标志,类索引,父类索引,接口索引集合]
基类、接口的应用——表单控件:一次添加、修改一条记录,一次修改多条记录。(上)
好久没发帖子了,又加了不少的功能呀。(图片仅是测试,不代表什么表情。) 本来我也想写一个2007的总结的,但是看到很多人都写了,我就不凑热闹了,写点和代码有关系的吧。 写作原因: 1、在项目里做得最多的操作恐怕就是保存数据了,总是要写一大堆的代码,能不能简单一点呢?2005来了,似乎可以减少一些代码,但是03里怎么办呢? 2、基类、接口、策略模式,好多高手都讨论过了,但是都是理论上的,在实践中如何应用呢?在webform 里面又怎么使用呢? 目的: 1、做一个“控件”来应对各种表单的录入,包括一次保存一条记录、一次保存多条记录。
1013 0