最近在做一个任务管理平台,其中又一个业务是定时请求任务,由于业务逻辑和服务器性能原因不太适合做socket连接,所以采用的是定时请求方式获取数据。这直接造成了间歇性小并发。于是就带来了一些mysql脏读的问题。
每次请求到服务器都会进行一次读表,判断,或更新。如果任务未启动,则更新任务表,然后控制运行程序运行任务。
但是在运行过程中有时候会出现,一个任务多个程序再跑,浪费资源。查看代码后才发现问题。
每次都要select一条数据,然后判断任务状态,然后更新任务状态。如果只是单次访问,能控制流程还比较稳定。但是一旦遇到并发问题,就无法保证数据的可靠性。有概率会在第一次请求还未提交的时候,第二个请求已经来获取数据了,从而造成数据脏读。
1、如果是大量并发,且时间很长,建议采用列队方式,保证稳定和可靠性,但对于小项目来说有点大。
2、如果访问量不是很大但是集中并发,和我这样,可以采用mysql事务+事务串行隔离来保证每个任务都按顺序执行。
3、利用一些其他控制办法。
是的,我不太想动数据库来操作,因为除了这个表,其他都是请求比较大。事务隔离会有一定的性能损耗。
于是找到了一个另类的办法来控制php实现事务隔离。
由于我的业务场景,就算一次请求失败了,他也会定时再次请求,于是,在分配任务的代码中,加入一个文件锁,利用文件锁的阻塞来直接拒绝其他请求。
//阻塞锁
//打开一个锁文件(空文件)
$fp = fopen("./db.lock", "w+");
//尝试加锁,加锁失败返回false
if(flock($fp,LOCK_EX)){
//查表
//数据处理
//更新表
//解锁文件,让其他进程可以进入
flock($fp,LOCK_UN);
}else{
//这里要返回一些等待信息,或者阻塞信息
echo '急个毛,等会到你';
}
//关闭文件
fclose($fp);
这样,就可愉快的阻塞了。