PHP 在高并发下,怎么正确处理,才能保持数据的一致性?

2018-03-15 10:05:13 +08:00
 madaima

//流程一
class Factory
{
    public static function get($item)
    {
        switch ($item->status){
            case 1;
                return new a($item);
            case 2;
                return new b($item);
            ...
        }
    }
}

//流程二
class  a
{
    public function aa($item)
    {
        //DB BEGIN
        //set status = 2
        //DB COMMIT
        //catch DB ROLLBACK
    }
}

首先我们排除使用悲观锁这种方法。

如代码所示,现在处理数据时会先进入工厂类判断数据状态,然后到不同的类中去处理数据。

但是在高并发下,流程二没走完的情况下,数据状态没更新,第二次请求还会走到流程二中去处理。

这种情况 有什么好的方法去处理?

7170 次点击
所在节点    PHP
36 条回复
jack010love
2018-03-15 10:08:54 +08:00
PHP 的话,我们一般都是在 Redis 加个 flag。
l57t7q
2018-03-15 10:16:42 +08:00
extreme
2018-03-15 10:19:33 +08:00
才疏学浅,坐等高人回答
TIGERB
2018-03-15 10:23:32 +08:00
和语言无关吧

方案 1: 串行操作
方案 2: 锁
vus520
2018-03-15 10:34:18 +08:00
高并发下,还用数据库的锁来实现,我感觉这是要炸啊,数据库的性能得多好?
madaima
2018-03-15 10:43:00 +08:00
@jack010love 做类似乐观锁的操作吗?
kimmykuang
2018-03-15 10:46:03 +08:00
你的问题是要实时一致性还是最终一致性?现在高并发场景下一般都是舍弃实时一致性保证吞吐,借助队列或 redis 锁或幂等表等方式来实现最终一致性
robinchina
2018-03-15 10:51:09 +08:00
因为搞不定别的方法··········所以·锁表···········一锁解千愁·······
puritania
2018-03-15 10:52:42 +08:00
Redis setnx 了解一下
puritania
2018-03-15 10:53:11 +08:00
或者串行消息队列
solaya
2018-03-15 10:53:47 +08:00
MVCC ?
madaima
2018-03-15 10:55:41 +08:00
@l57t7q 谢谢你提供的资料 我一会研究一下。
madaima
2018-03-15 10:59:46 +08:00
@vus520 对啊 所以问一下有没有其他好的实现方法学习一下。
harborM
2018-03-15 11:04:46 +08:00
之前看了点文章,一般都是串行或者锁实现的,文件锁数据库锁在高并发情况下都挺粗糙的,可以用 redis 来锁,毕竟锁作为一个同步原语只要实现 acquire 和 release 理论上就成立了,而且 redis 本身可以分布式部署,应该是个可行的方案;串行的话对于部分语言有些难言之隐,php 的话如果回调形式返回结果有点难以主动推.只是我的一点思路
dilu
2018-03-15 11:06:48 +08:00
加锁
如果需要更高的性能 我才疏学浅 看别的大神怎么回答吧
rqrq
2018-03-15 11:09:43 +08:00
缓存加标志怎么弄都可以,并发了直接返回一个提示给用户,操作失败,让用户自己重试。
数据库乐观锁有个好处是并发了会挂着等前面的处理完毕,然后自动再读取,只要不超时,用户只需要等待。
看实际情况用哪种。
这是我的理解,也不知道对不对,这也应该就是 @kimmykuang 说的实时一致性和最终一致性。
rqrq
2018-03-15 11:11:48 +08:00
我还没试过 redis 的锁是不是可以像数据库锁那样,如果可以肯定优先用 redis 来实现。
madaima
2018-03-15 11:16:38 +08:00
感谢 楼上各位热心回复 我现在大概有个思路了 现在去实现下 试试效果。
eslizn
2018-03-15 11:16:40 +08:00
事务化,每次请求一个 id,然后这个请求中的任何原子操作,都需要额外具备确认(用于超时等情况下的重试)、回滚接口。不能确定的失败操作一律丢入队列进行重试、回滚或人工处理
Junjunya
2018-03-15 11:17:32 +08:00
码一下, 等高人回答完了, 来学习

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/438205

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX