幂等性设计

 

在使用微服务框架时出现数据不一致。

一般的框架,调用接口只有两种情况,成功和失败。但是在微服务框架还有第三种情况,超时。

在判断超时时,如果采用重试的处理方式,就可能出现数据不一致。

另外一种处理是查询一次被调用方,如果能查到数据就代表调用过了,不继续执行,如果查不到数据,就走失败流程。此时,就需要接口提供幂等性保证。防止重复调用出现不一致的情形。

幂等性强调的是外界通过接口对系统内部的影响,外界怎么看系统和幂等性没有关系,只要一次或多次调用对某一个资源应该具有同样的副作用就行。注意,是对资源造成的副作用必须一样,但是返回值可以不同。

那数据库的增删改查来举例子:

  1. 查询操作:查询操作并不会产生或者变更新的数据,因此查询操作时天然具备幂等性的。
  2. 删除操作:这里分为物理删除和逻辑删除。

物理删除:删除只会进行一次,无论执行几次delete操作,造成的效果是一样的!是幂等性操作

逻辑删除:这类删除,是用update修改字段而已,这种操作无论update几次,造成的效果是一样的!是幂等性操作

3. 增加操作
这里要看这张表是否带唯一索引。

  • 带唯一索引Insert:此时如果重复插入操作,是会插入失败的!该操作是幂等性操作

  • 不带唯一索引Insert: 这种情况是非幂等性操作

4. 修改操作
要看修改了啥

  • 计算式Update:这类操作是指UPDATE table SET number=number-1 WHERE id=1,这类SQL的操作,是非幂等性操作!

  • 非计算式Update:这类操作是指UPDATE table SET number=3 WHERE id=1,这类SQL操作,这种修改是属于幂等性的操作!

在数据库库表有唯一索引的情况下,插入重复数据会报异常。

但是也可能不报异常。

Mysql提供了三组这样防止重复插入的语句,必须要有唯一索引才能用的

  • insert ignore into :若有导致unique key冲突的记录,则该条记录不会被插入到数据库中.

  • replace :若插入时如发现unique key已存在,则替换原记录,即先删除原记录,后insert新记录。

  • on duplicate key update :若插入时如果发现unique key已存在,则执行update更新操作

解决方法

全局token,生成一个全局性唯一的token,然后请求过来的时候,查一下token存在么,存在代表做过了,就丢弃。不存在,就执行正常业务流程,把token丢到某个存储介质里。

这个方案乍听之下很完美!但是细想一下还是有一点不大好。你看啊,假设有1000个请求,重复请求一般不到10个。为了这不到10个请求的正确性,让剩下990个正常的请求都多一个查询流程,这似乎不大妥吧。

以烟哥主张在数据库的操作上解决这个问题!就插入操作来说,建议还是建一个唯一索引,来防止重复插入

可是我们的数据量很小,就是不想建索引怎么办?

那你的插入语句可以像下面这么修改

INSERT INTO table(field1, field2, fieldn) SELECT 'field1', 
'field2', 'fieldn' FROM DUAL WHERE NOT EXISTS(SELECT field
 FROM table WHERE field = ?)

采用这种写法,就可以防止重复插入,而且不需要建立唯一索引!SQL可以判断field字段有值,则不insert。如果无值,则会执行insert操作!这种方法其实就是使用了mysql的一个临时表的方式,但是里面使用到了子查询,效率也会有一点点影响。但是很重要的一点,这种写法在oracle里也能跑的通,通用性之强,无与伦比。如果真的达到了影响性能那个级别了,估计数据量够大,可以用上索引了。这会数据量太小,先这么写吧!”

那针对修改场景怎么办

也很简单,加一个版本字段就行!比如,原来的sql为

UPDATE table SET number=number-1 WHERE id=1

,你加一个版本号字段就好啦,变成

UPDATE table SET number=number-1,_version=_version+1  
WHERE id=1 AND _version= last_version

摘自:java编程,烟哥和小刘的对话。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值