//获取缓存
$tmp = unserialize(file_get_contents('tmp.txt'));
//得到以下缓存数组
$tmp = [
'a' => 'qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq',
'b' => 'wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww',
'c' => 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
'd' => 'rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr',
'e' => 'tttttttttttttttttttttttttttttttttttttttttt',
'f' => 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy',
'g' => 'uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu',
'h' => 'iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii',
...
];
//更新缓存
$tmp['b'] = 'ooooooooooooooooooooooooooooooooooooooooo';
file_put_contents('tmp.txt', serialize($tmp));
//那么问题来了,多个线程在读取这个缓存的时候
//当线程 A 在更新缓存时,调用以下方法
$tmp['a'] = 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
file_put_contents('tmp.txt', serialize($tmp));
//而在线程 A 更新缓存的同时,线程 B 在读取 tmp 这个缓存
$tmp = unserialize(file_get_contents('tmp.txt'));
//假设 A 线程执行更新缓存时,文件内容刚写入一部分,那么线程 B 读取出来的
//缓存数据是
$tmp = false;
//那么线程 B 就会查数据库后得到数据后写入缓存
$tmp['b'] = 'ssssssssssssssssssssssssssssssssssssssss';
file_put_contents('tmp.txt', serialize($tmp));
//然后最终的问题来了
//如果设置这个缓存数据有效期 1 小时,
//当几十上百个线程频繁访问这个缓存数据,如果不存在其中的 a 或 b 或其他键的值,就
$tmp['x'] = '......................................'; //x 为 abcdefg..的之中一个键
file_put_contents('tmp.txt', serialize($tmp));
//如果更新其中一个键的值时,刚写入一部分到 tmp.txt,那么其他线程读取
//缓存时得到的值是 false,那么又各自更新写入自己的缓存
//这么一来,只要有一个进程更新写入到 tmp.txt 文件而还没全部写完时,另一线程就
//读取,就会造成清空了所有缓存的情况,最后造成这个 tmp 缓存被不停清空又不停写入
//这就缓存的使用目的了
//这种情况该怎么解决
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.