Home  >  Article  >  Backend Development  >  php中没有进程锁,有没有什么解决方案?

php中没有进程锁,有没有什么解决方案?

WBOY
WBOYOriginal
2016-06-06 20:07:49784browse

php中貌似没有进程锁机制,但是在并发订单处理时需要用到进程锁,不知道有没有什么现成的解决方案?我的考虑是使用flock的方式,生成一个文件锁,对文件锁进行检测,如果已经锁定则休眠1秒后再次检测,直到无锁状态再返回执行,不知道这样子的方案可行吗?

回复内容:

php中貌似没有进程锁机制,但是在并发订单处理时需要用到进程锁,不知道有没有什么现成的解决方案?我的考虑是使用flock的方式,生成一个文件锁,对文件锁进行检测,如果已经锁定则休眠1秒后再次检测,直到无锁状态再返回执行,不知道这样子的方案可行吗?

用php扩展的,或者文件锁的方式明显不可行。
在分布式部署的情况下就会出问题。

而即使是分布式部署,数据库一般也能保持唯一。
所以可以使用mysql新建一个字段用来记录锁定情况。
这就是数据库乐观锁技术见:

http://chenzhou123520.iteye.com/blog/1863407

当然,这种方案也不是尽善尽美的,但比之题主和那个php扩展的方案,还是优雅太多了。

PHP文件排它锁flock($fp,LOCK_EX)不是用于控制订单并发的吧.
订单并发为什么不用数据库事务?MySQL默认的引擎InnoDB就支持事务.

<code>$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');
</code>

如果不想用事务,或者引擎比如MyISAM不支持事务,
可以考虑用CAS(Check And Set)版本号乐观锁,保证高并发下的数据一致性.
上面采用的是事务加悲观锁来控制数据库并发,但是如果系统的并发非常大的话,
悲观锁定会给数据库带来比较大的性能问题(其他事务要等待),
这时可以考虑选择使用版本号乐观锁的方法.
就像防止多人编辑一样,给表弄一个版本号字段.
获取数据时拿到版本号和余额,写入时比对版本号,相同则插入,并把版本号加1.

<code>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;
</code>

affected_rows返回0表示操作失败.
注意到UPDATE里的last_version为SELECT获取的本次读写的版本号.
上述版本号的方法借鉴了Memcached的CAS(Check And Set)冲突检测机制,这是一个乐观锁,能保证高并发下的数据安全.
这种方法不需要数据库事务的支持,SELECT操作和UPDATE操作的时间跨度再大也没有问题.

PHP内有个Semaphore扩展,可以借用系统信号量进行进程锁,编译时加上--enable-sysvsem或者从pecl安装即可。不支持Windows系统。

数据库里不是会加锁么。。。。。

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn