84669 人学习
152542 人学习
20005 人学习
5487 人学习
7821 人学习
359900 人学习
3350 人学习
180660 人学习
48569 人学习
18603 人学习
40936 人学习
1549 人学习
1183 人学习
32909 人学习
php中貌似没有进程锁机制,但是在并发订单处理时需要用到进程锁,不知道有没有什么现成的解决方案?我的考虑是使用flock的方式,生成一个文件锁,对文件锁进行检测,如果已经锁定则休眠1秒后再次检测,直到无锁状态再返回执行,不知道这样子的方案可行吗?
ringa_lee
PHP文件排它锁flock($fp,LOCK_EX)不是用于控制订单并发的吧.订单并发为什么不用数据库事务?MySQL默认的引擎InnoDB就支持事务.
flock($fp,LOCK_EX)
$db = new mysqli('127.0.0.1','user','pass','dbname',3306); $db->query('SET AUTOCOMMIT=0'); $db->query('START TRANSACTION'); $db->query($sql); $db->query('COMMIT'); $db->query('SET AUTOCOMMIT=1');
如果不想用事务,或者引擎比如MyISAM不支持事务,可以考虑用CAS(Check And Set)版本号乐观锁,保证高并发下的数据一致性.上面采用的是事务加悲观锁来控制数据库并发,但是如果系统的并发非常大的话,悲观锁定会给数据库带来比较大的性能问题(其他事务要等待),这时可以考虑选择使用版本号乐观锁的方法.就像防止多人编辑一样,给表弄一个版本号字段.获取数据时拿到版本号和余额,写入时比对版本号,相同则插入,并把版本号加1.
SELECT balance,version FROM user WHERE id=1 AND balance>10; UPDATE user SET balance=balance-10,version=last_version+1 WHERE id=1 AND version=last_version;
affected_rows返回0表示操作失败.注意到UPDATE里的last_version为SELECT获取的本次读写的版本号.上述版本号的方法借鉴了Memcached的CAS(Check And Set)冲突检测机制,这是一个乐观锁,能保证高并发下的数据安全.这种方法不需要数据库事务的支持,SELECT操作和UPDATE操作的时间跨度再大也没有问题.
用php扩展的,或者文件锁的方式明显不可行。在分布式部署的情况下就会出问题。
而即使是分布式部署,数据库一般也能保持唯一。所以可以使用mysql新建一个字段用来记录锁定情况。这就是数据库乐观锁技术见:
数据库乐观锁技术
http://chenzhou123520.iteye.com/blog/1863407
当然,这种方案也不是尽善尽美的,但比之题主和那个php扩展的方案,还是优雅太多了。
PHP内有个Semaphore扩展,可以借用系统信号量进行进程锁,编译时加上--enable-sysvsem或者从pecl安装即可。不支持Windows系统。
PHP
Semaphore
--enable-sysvsem
pecl
Windows
数据库里不是会加锁么。。。。。
http://blog.csdn.net/rodgexue... 关于进程锁,这篇文件讲的是怎么实现,更加通俗易懂
如果是单机的话,flock是很好的阻塞锁解决方案。事务跟锁是两个概念,并不能混为一谈。。如果是分布式锁的话,redis会比mysql更合适,因为redis的性能会更好,实现也很简单。
https://github.com/malkusch/lock 各种锁方案,单机分布式都可以解决
并发使用文件锁和数据库表锁都可以解决,但不是最优方案。。因为你锁定的时候别的请求是无法成功的,所以会造成等待。。。使用队列可能会好一点吧
PHP文件排它锁
flock($fp,LOCK_EX)
不是用于控制订单并发的吧.订单并发为什么不用数据库事务?MySQL默认的引擎InnoDB就支持事务.
如果不想用事务,或者引擎比如MyISAM不支持事务,
可以考虑用CAS(Check And Set)版本号乐观锁,保证高并发下的数据一致性.
上面采用的是事务加悲观锁来控制数据库并发,但是如果系统的并发非常大的话,
悲观锁定会给数据库带来比较大的性能问题(其他事务要等待),
这时可以考虑选择使用版本号乐观锁的方法.
就像防止多人编辑一样,给表弄一个版本号字段.
获取数据时拿到版本号和余额,写入时比对版本号,相同则插入,并把版本号加1.
affected_rows返回0表示操作失败.
注意到UPDATE里的last_version为SELECT获取的本次读写的版本号.
上述版本号的方法借鉴了Memcached的CAS(Check And Set)冲突检测机制,这是一个乐观锁,能保证高并发下的数据安全.
这种方法不需要数据库事务的支持,SELECT操作和UPDATE操作的时间跨度再大也没有问题.
用php扩展的,或者文件锁的方式明显不可行。
在分布式部署的情况下就会出问题。
而即使是分布式部署,数据库一般也能保持唯一。
所以可以使用mysql新建一个字段用来记录锁定情况。
这就是
数据库乐观锁技术
见:http://chenzhou123520.iteye.com/blog/1863407
当然,这种方案也不是尽善尽美的,但比之题主和那个php扩展的方案,还是优雅太多了。
PHP
内有个Semaphore
扩展,可以借用系统信号量进行进程锁,编译时加上--enable-sysvsem
或者从pecl
安装即可。不支持Windows
系统。数据库里不是会加锁么。。。。。
http://blog.csdn.net/rodgexue... 关于进程锁,这篇文件讲的是怎么实现,更加通俗易懂
如果是单机的话,flock是很好的阻塞锁解决方案。
事务跟锁是两个概念,并不能混为一谈。。
如果是分布式锁的话,redis会比mysql更合适,因为redis的性能会更好,实现也很简单。
https://github.com/malkusch/lock 各种锁方案,单机分布式都可以解决
并发使用文件锁和数据库表锁都可以解决,但不是最优方案。。因为你锁定的时候别的请求是无法成功的,所以会造成等待。。。使用队列可能会好一点吧