问题
钉钉实人认证业务存在数据重复的问题。正常情况下,数据库中应该只有一条实人认证成功记录,但是实际上某用户有多条。
原因
并发导致了不幂等。
幂等(idempotent、idempotence)是一个数学与计算机学概念,常见于抽象代数中。
在编程中一个幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同。
--百度百科
该业务一般流程为: 1)用户选择实人认证后会在服务端初始化一条记录; 2)用户在钉钉移动端按照指示完成人脸比对; 3)比对完成后访问服务端修改数据库状态
然而在第三步,同一个请求会多次修改数据库状态,系统并未按照我们预期的那样实现幂等。究其原因,是因为请求并发访问,在首次请求完成修改服务端状态前,并发的其他请求和首次请求都通过了幂等判断,对数据库状态进行了多次修改。并发导致了原幂等设计失效。
解决方案
解决并发场景下幂等问题的关键,是找到唯一性约束,执行唯一性检查,相同的数据保存一次,相同的请求操作一次。
- 并发场景下,如果一个系统依赖的组件幂等,那么该系统在天然幂等。
- 钉钉通讯录加人就是通过数据库的唯一索引解决了幂等问题。以钉钉通讯录加人为例,在向数据库写数据之前,会先判断数据是否已经存在于数据库之中,如果不存在,加人请求最终会向数据库的员工表插入一条数据。大量相同的并发的通讯录加人请求让系统的幂等设计失效成为可能。在一次加人请求中,(组织ID,工号)可以唯一标记一个请求,在数据库中,也存在(组织ID,工号)的唯一索引。因此我们可以保证,多次相同的加人请求,只会修改一次数据库状态,即添加一条记录。
如果所依赖的组件天然幂等,那么问题就简单了,但是实际情况往往更加复杂。并发场景下,如果系统依赖的组件无法幂等,我们就需要使用额外的手段实现幂等。一个常用的手段就是使用分布式锁。分布式锁的实现方式有很多,比较常用的是缓存式分布式锁。
|