这样的流程能有效防止高并发吗?

玟质兵兵 发布于 2012/06/18 10:55
阅读 768
收藏 0

设计了一个轻量级的用户资金表和操作流程,希望得到大家的指证,先谢过。

一、用户资金的变动表的表结构,大致有下面几个字段:

1.用户ID
2.余额
3.增加量
4.减少量
5.记录生成时间
6.校验码
7.校验码过期时间

二、操作函数:
1.取用户资金的最近一条记录:
function A(用户ID) {
    return $arrRow;
}

2.写校验码:
function B(用户ID) {
    $arrRow = A(用户ID);
    if ($arrRow的校验码是空 || 校验码时间过期) {
        $str = 校验码;
        $int = 校验码过期时间;
        更新arrRow到数据库
        return $str;
    }
    return false;
}

3.变动资金:
function C(用户ID, 校验码, 增加量, 减少量) {
    $arrRow = A(用户ID);
    if ($arrRow的校验码 == 校验码 && 校验码没有过期) {
        计算余额;
        插入一条新的数据到数据库,此新数据里没有校验码和校验码过期时间;
        return true;
    }
    return false;
}

三、用户充值/消费记录流程:
新的校验码 = function B(用户ID);
if (false !== 新的校验码) {
    结果 = function C(用户ID, 新的校验码, 增加量. 减少量);
}

以下是问题补充:

@玟质兵兵:校验码是一个“随机,唯一”的字符串 (2012/06/18 11:57)
@玟质兵兵:感谢大家回复,我最想知道的是“这样的流程设计会不会产生错误数据”,而不是想要一个新的解决途径(新的方法我这多的是,呵呵) (2012/06/18 12:09)
加载中
0
纠结名字_我艹你妹
纠结名字_我艹你妹

"防止高并发吗?"...你们老板看到要炒掉你的

玟质兵兵
玟质兵兵
请兄台指教
0
jeffsui
jeffsui
高并发你无法防止,你的意思是处理高并发下的程序编程吧。
玟质兵兵
玟质兵兵
可能我问的不准确 我想表达的是,按我设计的流程控制,会不会产生错误数据? 谢谢
0
飞晏
飞晏

校验码是什么用途?

能否加个 时间戳+随机字符串(或者再加上uid)的主键,这样可以不用校验码。

另外增加量和减少量合并使用正负表示就行了。

玟质兵兵
玟质兵兵
谢谢回复 校验码在这里的作用相当于一个“短期的口令”,只有拥有正确口令的请求,才可以插入新记录,看看里面的function C 谢谢你的建议
0
酒逍遥
酒逍遥

理解不能...看不出 校验码是干啥用的...

我想楼主的 目的是想防止 高并发情况下资金变动异常的情况

例如:现在用户余额为100.

有2个 并发操作分别为 +50 和 -50

本来操作顺序是 先+50  后减 50   还是保持100不变

但是在并发的情况下..+50的操作还没做完..就做了 -50 结果就变成了 150。

或者+50的操作 还没做完呢 -50的操作就读取了余额数据,结果变成了50.

这种问题应该用事务去解决吧

玟质兵兵
玟质兵兵
谢谢回复,对,你理解了我的问题,但我想知道的是:“我这样的流程控制行不行?”,其它的解决途径我也了解,比如:事务,锁,批处理机制。。。再次谢谢
0
vampirekiss
vampirekiss

额,刚才建议你用锁,仔细一看。 你的校验码就是“锁”的功能。应该是木有问题的。

0
穿衣服比较麻烦
穿衣服比较麻烦

1、线程A 、B同时进入到 fun b ,同时准备进行更新数据操作

2、线程A由某种原因sleep

3、线程B进入到 fun C,计算余额

4、线程A继续执行

穿衣服比较麻烦
穿衣服比较麻烦
回复 @玟兵 : 5、线程A,进入到 fun C,验证条件(此时是通过的) 6、线程B,此时余额计算完毕,新增一条新纪录 7、线程A,计算余额 。。。
玟质兵兵
玟质兵兵
呵呵,第4之后,进入到fun C,应该会被条件过滤掉,不会产生错误数据吧?
0
xyz555
xyz555
如果说一个帐号单独一个人操作就是不像楼主这样做,一般也是不会出问题的,但是多人同时对一个帐号操作呢?楼主的高并发会出问题的地方就在这里。
0
vampirekiss
vampirekiss

额,楼主还是单独做个全局锁吧。

有可能会有这样的情况:

例如此时余额100

有2个 并发操作分别为 +50 和 -50,

这时候+50的操作已经读出余额100,但是还没有写入,-50的操作取的可能是比较老的校验码。

这时候就-50了,余额为50

而真正到+50写了。余额就是 100 + 50 = 150了

变更记录可能会变成这样

ID 余额  +  -

1  100  0  0

2  50   0  50

3  150 50 0

玟质兵兵
玟质兵兵
我这里的校验码是有“有效期”的,应该不会存在你说的问题,谢谢回复
0
lfsfxy9
lfsfxy9

你这样已经实现了锁的功能,逻辑不出问题的话,不会有错误数据的.

对账户的操作都会去判断这条记录的码生效日期和码值,这样就类似锁的东西. 保证每次只能有一个操作去处理表.

 

玟质兵兵
玟质兵兵
感谢回复
0
xwz
xwz

乐观锁吧, 在数据库中存放一个数据版本字段, 在每次更新之前, 一定确保你手里的版本和数据库版本一致, 才能继续. 每次更新时, 同时把版本+1

比如你这里的校验码,就可以当做数据版本. 

update table set mony=mony+50 where id=1 and 数据版本=你的校验码

玟质兵兵
玟质兵兵
谢谢,受教了
返回顶部
顶部