在编程中的幂等性idempotence

在编程中,可能经常会听到幂等这个词,第一次是年初红包技术复盘时听到了这个词,这次是因为写脚本时被质疑,是否支持幂等。这里总结一下,也算是个记录吧。其实在编程中,很多时候都需要支持幂等,有的程序自然存在幂等,有的需要我们控制。比如与支付相关的场景,比如我们常见的HTTP方法。

幂等性概念

idempotence:在编程中,一个程序幂等操作的特点是其任意多次执行所产生的影响均与一次执行的影响相同

幂等案例

比如你写了一个script,实现的功能是:发送短信sms和私信message通知用户,而且要求每个用户每天只发送一次。如果不进行幂等控制,会有什么问题呢?

存在问题

sms和message发送完成后,你通过log发现,有部分用户发送失败,这时你又不能再跑一遍脚本,因为这会导致之发送成功的用户再次收到消息,显然这是不符合业务逻辑的,而且如果还是有发送失败的,那就再跑一遍?

解决方案
  1. 通过日志,筛选出发送失败的用户,重新补发,如果还是有失败的,继续补发。。。,而且!你还需单独准备一个脚本用于补发

  2. 控制脚本,实现幂等!一个脚本足以,无论发送多少次,都不会出现重复发送的情况
    很显然,第二种才是比较专业的解决方案,那么如何实现幂等呢,方法不止一个,此处我们使用缓存。具体如下:
    给用户发信息时,检查缓存中是否有用户发送记录,有则跳过不发送,无则发送,发送成功时设置用户缓存。

伪代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
foreach ($uids as $uid)
{
$cache = array();
$cache = getCache($uid);

if (empty($cache['sms']))
{
if (sendSMS($uid))
{
$cache['sms'] = 1;
setCache($uid, $cache);
}
}

if(empty($cache['msg']))
{
if (sendMessage($uid))
{
$cache['msg'] = 1;
setCache($uid, $cache);
}
}

}
总结

这样一来,程序就具有简单的幂等性,脚本跑n次和跑一次影响是一致的,而且还可以弥补发送失败的情况,大不了多跑几次,因为不会出现重发的情况。以后写脚本的时候,要考虑一下,是否支持幂等!

问题发散

消息发送成功,缓存设置失败怎么办?如果对程序要求非常严格,必须有更好的解决方案才行!比如金融电商业务。

继续学习

http://www.i3geek.com/archives/841