您的位置:首页 > 其它

事务型开发(如何设计防重入接口)

2015-12-03 11:36 489 查看
半年前,自己从BD来到一个创业小公司,开始接触事务型开发的一些基本技术。自己的服务器开发技术最开始部分源于腾讯,主要是使用服务器的单线程异步IO模型+UDP+状态机来做一些事情。对于很多高并发的服务是比较适用的。之后来到百度的一个团队,里面提倡使用TCP+多线程的网络模型。可以说各自有各自的优缺点。半年前来到小公司,开始接触一些类似电商业务的开发,跟之前接触的很多都不太一样。
首先谈谈事务,什么是事务?mysql事务可以定义为,一组sql语句,要么全部执行成功,要么全部执行失败,即是保持数据的一致性。举个简单的例子,订单支付成功之后,你需要修改两个表,要么两个表同时修改成功了,要么两个表都没有去修改,不能出现表1成功,表2失败,这样就会导致数据的不一致性。
交待了事务的基本概念,后面接着说说,事务型开发的接口设计的一个原则:防重入。
先假定,我们的DB,都是部署在同一个实例中(不同实例的,后面再谈)。对于数据的一致性问题,我们可以使用mysql中的innodb的事务进行处理,这有数据库的基础支持,相对容易。
防重入:即是接口具有幂等性,简单来说:即是同样的请求,来请求一次或多次,他的执行结果是一样的。系统接口的防重入设计,是实现系统分布式的基本条件。
为什么接口需要有防重入的特性呢?举个简单例子:例如你要设计一个库存管理系统。你的前端要来修改库存的时候,来请求修改库存时,假如需要减少1个库存,但如果请求超时了。但库存系统已经收到请求,并减少了这一个库存,但前端由于超时,他并不知道已经减少成功。如果此时来重试,那么就有可能减少一个库存的意图,实际减了两个库存数量,导致数据不一致的严重问题!
如果此时你的接口具体幂等性,前端就可以来调用多次,从而实现可靠的数据一致性服务。即使失败或超时的情况下,也能保证数据保持一致性。

问题点2:如果能设计一个防重入的接口?
这里提供一个常用的方法,使用lock_id来构造冲突的方式。还是举库存管理系统的例子。
在协议中让客户端带上一个随机序列,可以用时间戳+随机值来实现。每次请求的时候,服务器工作流程:
1)开启事务
2)服务器先用这个随机值构造lock_id,插入一个防重入表中。
3)如果插入失败,且主键冲突,则说明已经执行过这个操作了,返回成功。否则继续往下执行。
4)再执行库存操作。
5)提交或回滚事务。

如果客户端请求超时的时候,可以再使用相同的序列进行访问,而不会对库存造成有影响。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: