Php 适用于高负载环境的APC用户缓存?

Php 适用于高负载环境的APC用户缓存?,php,crash,apc,spinlock,high-load,Php,Crash,Apc,Spinlock,High Load,我们尝试在高负载环境中部署APC用户缓存,作为我们的中央缓存服务(redis)的每台服务器上的本地第二层缓存,用于缓存结果很少变化的数据库查询和配置。我们基本上看了Facebook(几年前)所做的事情: 它在一段时间内工作得很好,但是在高负载下工作了几个小时后,APC遇到了问题,因此整个mod_php不再执行任何php。 即使是一个简单的PHP脚本,也不会再回答这个问题,而静态资源仍然是由Apache提供的。它没有真正崩溃,没有故障。我们尝试了APC的最新稳定版和最新beta版,我们尝试了p

我们尝试在高负载环境中部署APC用户缓存,作为我们的中央缓存服务(redis)的每台服务器上的本地第二层缓存,用于缓存结果很少变化的数据库查询和配置。我们基本上看了Facebook(几年前)所做的事情:

它在一段时间内工作得很好,但是在高负载下工作了几个小时后,APC遇到了问题,因此整个mod_php不再执行任何php。 即使是一个简单的PHP脚本,也不会再回答这个问题,而静态资源仍然是由Apache提供的。它没有真正崩溃,没有故障。我们尝试了APC的最新稳定版和最新beta版,我们尝试了pthreads、自旋锁,每次都遇到同样的问题。我们为APC提供了更多的内存,在崩溃前1分钟,我们有2%的碎片,大约90%的内存是可用的。当它“崩溃”时,我们在错误日志中找不到任何东西,只有重新启动Apache有帮助。只有使用旋转锁,我们才会得到一个php错误,即:

PHP致命错误:未知:在中检测到卡住的自旋锁(0x7fcbae9fe068) 第0行未知

这似乎是一种超时,pthread不会发生这种情况,因为pthread不使用超时

发生的事情可能是这样的:

一些数字:一台服务器每秒有大约400个APC用户缓存命中率和大约30个插入率(我认为这是很多),一个请求有大约20-100个用户缓存请求。用户缓存中有大约300.000个变量,都有ttl(我们只在我们的中央redis中存储没有ttl的变量)

我们的APC设置为:

apc.shm_segments=1 
apc.shm_size=4096M
apc.num_files_hint=1000
apc.user_entries_hint=500000
apc.max_file_size=2M
apc.stat=0
目前,我们使用的是3.1.13-beta版本,使用旋转锁编译,与旧的PHP5.2.6一起使用(这是一个遗留应用程序,我听说这个PHP版本也可能有问题?),Linux 64位

调试真的很难,我们已经编写了监控脚本,可以收集每分钟从apc、系统等获取的尽可能多的数据,但我们看不到任何不寻常的情况——即使是在崩溃前1分钟

我在这里看到了很多类似的问题,但到目前为止,我们还没有找到解决问题的解决方案。当我读到类似的内容时:

我不确定在高负载环境中使用APC进行本地用户缓存是否是最好的主意。我们已经在这里使用了memcached,但是APC速度快得多。但是如何使其稳定呢

致以最良好的祝愿,
Andreas

除非您使用的是freebsd派生的操作系统,否则使用自旋锁不是一个好主意,自旋锁是地球上最糟糕的同步方式。您必须在freebsd中使用自旋锁的唯一原因是实现者拒绝将PTHREAD_PROCESS_共享对互斥锁和rwlock的支持包括在内,因此您几乎没有选择t在这种情况下使用pg sql启发的旋转锁。

第1课:

上面的单自旋锁定原语并不是唯一的原语。它们是 是最安全的,在任何情况下都能工作的, 但部分原因是因为它们是安全的,它们也相当慢 因为他们必须禁用中断 (这只是x86上的一条指令,但代价昂贵- 在其他体系结构上,情况可能更糟)

这是莱纳斯写的

旋转锁的速度很慢;这种说法不是基于我在facebook网上读到的某篇文章,而是基于事情的实际情况

另外,一个附带的事实是,由于您提到的问题,自旋锁部署在比内核更高的级别;由于糟糕的实现,无法跟踪的死锁

内核可以有效地使用它们,因为这就是它们被设计用来使用的地方,锁定小部分,而不是坐在那里等待你将amazon soap响应复制到apc中,然后每秒返回十亿次

APC中最合适的锁定类型(对于web,而不是内核)肯定是rwlocks,您必须在遗留APC中使用configure选项启用rwlocks,这是APCu中的默认设置

我已经给出了最好的建议,不要使用自旋锁,如果互斥导致堆栈死锁,那么试试rwlocks

在我继续之前,您的主要问题是您使用的是一个来自antiquity的PHP版本,甚至没有人记得如何支持它,一般来说,您应该考虑升级,我知道OP上的限制,但是否认这是一个真正的问题是不负责任的,您不想在不受支持的软件上部署。Addit从历史上看,APC几乎没有维护,它注定会消亡。O+和APCu是现代PHP版本中的替代品

无论如何,我离题了

当你在内核级别进行编程时,同步是一件令人头疼的事情,比如使用自旋锁,或者其他什么。当你从内核中移除了几层,当你依赖于下面的6或7位复杂软件时,你需要正确地同步,以便你的代码能够正确地同步。同步不仅仅是一个headache对于程序员来说很重要,但是对于执行者来说也很重要;它很容易成为闪亮的web应用程序的瓶颈,即使您的实现中没有bug

幸运的是,今年是2013年,雅虎并不是唯一能够用PHP实现用户缓存的人:)

这是一个非常聪明的、针对userland PHP的无锁缓存,它被标记为实验性的,但一旦完成,就可以玩一玩,也许再过7年,我们就不会考虑同步问题了:)


我希望你能了解到底:)

如何清除缓存?你是在apc配置中使用ttl/gc设置,还是经常调用apc_clear_缓存(“用户”)?目前我们甚至一天都不能依赖apc,所以我们必须一天多次调用该函数。你是否将其与缓存预热结合起来?你在谈论什么