84669 person learning
152542 person learning
20005 person learning
5487 person learning
7821 person learning
359900 person learning
3350 person learning
180660 person learning
48569 person learning
18603 person learning
40936 person learning
1549 person learning
1183 person learning
32909 person learning
有大量文件需要处理。 用一个php进程去操作会很慢。
如何在一个进程读某一个文件的时候,把文件锁上。不让其他进程可以再读而直接跳过,继续读其他的?
把正在读得文件rename,读完之后再rename回来,效率挺低的。如果实在没有更好的方法,就只能用这个了。flock,测试了一下,貌似不太好用,试了一下,没实现文件的非阻塞读锁。给不同进程分配不同的文件,不好实现。也没数据库。就算有。用数据库做锁,貌似比rename更低效。
请问有什么更好的方式可以给文件加 读锁。因为,只需要读文件。
走同样的路,发现不同的人生
你的问题是: 1. 很多文件,想多进程处理,以提高效率,缩短总处理时间 2. 这些进程只需要读文件,不需要写 3. 对每个文件,只要有一个进程处理过它就可以了,没有多个进程都必须处理它的需求
你的需求其实是分治,将文件分为多个组(不一定要在文件系统上新建目录),然后分而治之,这种情况不需要用锁.
锁不是用于这种场景的,锁用于下面这种场景:
1. 文件file.txt里面记录了user1的销售额和user2的销售额,user1+user2的销售总额 2. 进程php1负责写入user1的数据,进程php2负责写入user2的数据,两个进程各读出销售总额显示给user1,user2 3. user1和user2同时要求写入,真的是同时,不是前后差个几秒什么的
建议你这样解决: 1. 启动多个PHP进程(nohup php your_script.php your_dir &) 2. 每个PHP进程赋予一个序号(假设4个进程,那就0,1,2,3),可以通过对进程自身的pid模运算取余数得到,也可以在启动进程的时候通过命令行传入,随你了 3. 每个进程在处理文件前先对文件名做crc32()运算,模一下进程总数: crc32(file_name) % 4, 取模结果与此进程的序号相等就读取内容并处理,不相等就跳过
最后:小编帮我排个版吧...
除了文件锁以外,其他自行实现的锁在有锁进程意外退出时,都需要自行实现解锁机制。所以,还是推荐用文件锁,会由系统来自动释放……
function do_flock(){ ob_implicit_flush(true); //关闭PHP输出缓冲 $file = __FILE__; $f = fopen($file, 'r'); $count = 0; while(1){ $locked = flock($f, LOCK_NB | LOCK_EX); if($locked) { echo "GOT LOCK\n"; sleep(10); flock($f, LOCK_UN); echo "RELEASE LOCK\n"; break; } else { echo 'LOCKED BY OTHER, WAIT:' . ($count ++) . "\n"; sleep(1); } } }
测试方法:
time curl --no-buffer "http://localhost/flock" //在10秒钟之内另外一个terminal里再执行相同命令
Terminal 1 输出:
GOT LOCK RELEASE LOCK real 0m10.023s user 0m0.008s sys 0m0.008s
Terminal 2 输出:
LOCKED BY OTHER, WAIT:0 LOCKED BY OTHER, WAIT:1 LOCKED BY OTHER, WAIT:2 LOCKED BY OTHER, WAIT:3 LOCKED BY OTHER, WAIT:4 LOCKED BY OTHER, WAIT:5 LOCKED BY OTHER, WAIT:6 LOCKED BY OTHER, WAIT:7 LOCKED BY OTHER, WAIT:8 GOT LOCK RELEASE LOCK real 0m19.025s user 0m0.008s sys 0m0.008s
Ubuntu 12.04 测试通过,没有Mac没法测,但应该没啥问题,毕竟是同根同源的,PHP源码里也只是对Win有特殊实现……
注意,以下情况会影响输出效果
针对这些缓冲,可以在每次echo时,把内容用str_pad补齐4096字节
1. 为什么你会觉得rename效率低呢?如果一个目录下的文件不是相当多的话,这个应该不低。
2. 你肯定没有好好看flock的文档.
如果不希望 flock() 在锁定时堵塞,则给 operation 加上 LOCK_NB(PHP 4.0.1 以前的版本中设置为 4)。
用memcached实现吧。
比如读取文件 $filename = "t.txt";
if(!$memcached->get($filename)){ //文件锁不存在,那么执行文件读取功能 //首先再将文件锁住, $memcaced->save($filename,'1'); $fs = fopen($filename,'r+'); fclose($fs); //读取完毕释放文件锁 $memcaced->delete($filename); }else{ // 文件锁已经存在,跳过 }
以上是 memcaced 纯内存操作,速度会很快,根本不要考虑到性能的问题,当然还有一种方法,采用真正的文件锁,即添加一个新文件的方法控制,文件争用,但是此方法将加大IO的开销。
flock,测试了一下,貌似不太好用,试了一下,没实现文件的非阻塞读锁。
我记得好像有啊
http://php.net/manual/zh/function.flo...
LOCK_SH 就是读取锁,加锁后,其他程序可以读取,但不能写入 LOCK_EX 就是写入锁,加锁后,其他程序不能读也不能写 LOCK_NB(Windows不支持) 就是非阻塞模式,得不到锁立刻返回
我觉得这三个参数组合起来完全可以实现楼主的需求.
最简单解决办法,一共俩文件,一个write,一个read。reader完了等writer close了就对调文件名。
你的问题是:
1. 很多文件,想多进程处理,以提高效率,缩短总处理时间
2. 这些进程只需要读文件,不需要写
3. 对每个文件,只要有一个进程处理过它就可以了,没有多个进程都必须处理它的需求
你的需求其实是分治,将文件分为多个组(不一定要在文件系统上新建目录),然后分而治之,这种情况不需要用锁.
锁不是用于这种场景的,锁用于下面这种场景:
1. 文件file.txt里面记录了user1的销售额和user2的销售额,user1+user2的销售总额
2. 进程php1负责写入user1的数据,进程php2负责写入user2的数据,两个进程各读出销售总额显示给user1,user2
3. user1和user2同时要求写入,真的是同时,不是前后差个几秒什么的
建议你这样解决:
1. 启动多个PHP进程(nohup php your_script.php your_dir &)
2. 每个PHP进程赋予一个序号(假设4个进程,那就0,1,2,3),可以通过对进程自身的pid模运算取余数得到,也可以在启动进程的时候通过命令行传入,随你了
3. 每个进程在处理文件前先对文件名做crc32()运算,模一下进程总数: crc32(file_name) % 4, 取模结果与此进程的序号相等就读取内容并处理,不相等就跳过
最后:小编帮我排个版吧...
除了文件锁以外,其他自行实现的锁在有锁进程意外退出时,都需要自行实现解锁机制。所以,还是推荐用文件锁,会由系统来自动释放……
关于flock的演示
测试方法:
Terminal 1 输出:
Terminal 2 输出:
Ubuntu 12.04 测试通过,没有Mac没法测,但应该没啥问题,毕竟是同根同源的,PHP源码里也只是对Win有特殊实现……
注意,以下情况会影响输出效果
针对这些缓冲,可以在每次echo时,把内容用str_pad补齐4096字节
1. 为什么你会觉得rename效率低呢?如果一个目录下的文件不是相当多的话,这个应该不低。
2. 你肯定没有好好看flock的文档.
用memcached实现吧。
比如读取文件 $filename = "t.txt";
以上是 memcaced 纯内存操作,速度会很快,根本不要考虑到性能的问题,当然还有一种方法,采用真正的文件锁,即添加一个新文件的方法控制,文件争用,但是此方法将加大IO的开销。
我记得好像有啊
http://php.net/manual/zh/function.flo...
LOCK_SH 就是读取锁,加锁后,其他程序可以读取,但不能写入
LOCK_EX 就是写入锁,加锁后,其他程序不能读也不能写
LOCK_NB(Windows不支持) 就是非阻塞模式,得不到锁立刻返回
我觉得这三个参数组合起来完全可以实现楼主的需求.
最简单解决办法,一共俩文件,一个write,一个read。reader完了等writer close了就对调文件名。