如果一个项目开启了 OPcache,但是不启用预加载,同时该项目使用的是软链接到新目录的方式发布新版本。
因为 OPcache 使用的是文件路径来标识缓存,由于软链接到了新的目录,所以文件路径变了,那不就要重建全部的缓存,不就是缓存雪崩了么?就算开启了 OPcahce 的 file cache 好像也帮不上忙,因为 file cache 也是基于文件路径的。
问题一:是不是真的就会缓存雪崩? 问题二:除了换成覆盖式发布,还有办法解决么?
1
rushssss 2020-07-17 10:22:20 +08:00
第一缓存雪崩不是这个意思,第二你更新了代码但是 OPcache 不更新跑的不就是原来的代码了? 那更新代码有啥意义
|
2
mitu9527 OP @rushssss 这个不是缓存雪崩么,那是啥?第二点,代码发布到新目录下,所有文件的路径全部变了,OPcache 中现有的缓存全都是以前的路径的,也用不到了,相当于自动作废了,不是么?然后这时候去访问新版本,不就相当于从头开始建缓存么?
|
3
yc8332 2020-07-17 10:33:40 +08:00
你在说什么?先把概念搞清楚再发帖吧
|
5
simapple 2020-07-17 11:01:49 +08:00
你是要做什么?让不同机器的 php 进程复用同一份 opcache ?
|
6
mitu9527 OP @simapple 就是想问一下,使用软链接到新目录的方式发布新版本,旧的 OPcache 缓存就全部失效,就相当于从头建缓存,在高流量的服务器上压力不就瞬间上来了?想问一下有没有什么办法解决。
|
7
yc8332 2020-07-17 11:40:04 +08:00
opcache 的缓存也是有时间的。并不是说你代码更新了马上就更新,更新也不是全部都更新,用到才会更新。。而且这个也不是什么缓存击穿、缓存雪崩。。。那个是相对应缓存系统来说的,有兴趣可以自己搜索一下
|
8
mitu9527 OP @yc8332 OPcache 也算是缓存,怎么不能用这些词啊,有人规定这些词只能用在 redis 和 memcache 上?再者,你确定你理解我在问什么了么?我看不是我讲的不够清楚,是你没理解。
|
9
hauzi 2020-07-17 11:46:52 +08:00 1
先把常用的 PHP 脚本预热下
|
10
mitu9527 OP @hauzi 我明白预加载可能解决这个问题,但是不是所有项目都能预加载,而且预加载是把缓存放在工作进程上,也不是所有内容都适合预加载,所以我才问不启用预加载的情况下,有没有办法解决这个问题。
|
11
yc8332 2020-07-17 11:53:18 +08:00
@mitu9527 opcache 不会马上都更新,你觉得你的 php-fpm 进程一开始,服务器的处理能力会影响到你的 qps 吗?如果不会,更新代码也不会有这个问题。
|
12
mitu9527 OP @yc8332 请求一个新文件,不会去更新?高并发场景下,多人同时去读取这个文件,然后尝试去把这个文件的字节码写到 OPcache 中,那个瞬间,CPU 压力不就爆了?
|
13
coosir 2020-07-17 12:08:35 +08:00
更新代码后,主动清一下 opcache
|
14
mitu9527 OP @coosir opcache 被重置后,不也是相当于任何缓存都没有了,效果不也和缓存雪崩一样了么?瞬间压力就上来了。
|
15
loveyu 2020-07-17 12:43:31 +08:00 1
看了上面的。楼主安心摘流量,然后一点点放量吧,这样就没这些问题。
还要,清缓存就是了,并发读文件建缓存那点压力,忽略吧 |
16
mitu9527 OP @loveyu 高并发下重建缓存那个瞬间,压力比不开启 OPcache 直接去读 PHP 源文件还要大,直接不管了么?我觉得这个点可能是 PHP 压力的最高点,最有可能撑不住的就是这个点,所以才想问。
|
17
coosir 2020-07-17 13:17:29 +08:00 1
@mitu9527 真有这么大流量那就是很多个实例来支撑,那么就不应该热更。
就像上面说的,发布的时候部分实例先摘掉下线,更新代码,预热好,再上线。逐步更新所有实例防止服务中断。 |
19
gantleman 2020-07-17 13:37:21 +08:00 1
@mitu9527 缓存服务重置后,重建缓冲存是否会导致后端压力过大。通常情况下外网带宽远远小于内网带宽,内网带宽远远小于硬盘 io 。所以一般情况下不存在击穿或雪崩。有一种特殊情况,就是所有外网带宽持续集中在一点,外网带宽总和大于磁盘 io 。例如产品活动的特殊情况。然后缓存服务器故障重置,压力突然后移到 io 。进而导致拒绝服务。
出现这种情况首先有一个必要条件,就是外网带宽大于磁盘 io 。当前服务器磁盘 io 一般速度为 500m 每秒。单台服务外网带宽约为 24m 。大概是大于 20 台主机的集群规模。那么这 20 多台服务器接到请求不做任何处理直接转发给同一台服务器。并且那台服务器缓存重置出现雪崩。 第二服务器读写数据有 28 定律,20%为写入操作,80%为读取操作。出现雪崩也就是对于 80%的读取操作不做 CDN 加速。如果有 cdn 加速,雪崩的条件就要上升到 100 台服务器同时写入并内存重置。 也就是需要外网带宽要高达 2400m,才可能触发雪崩。这里还没考虑限流措施。 雪崩有存在的可能,但在实际运维的条件下,要达到雪崩的条件非常苛刻。 |
20
wangritian 2020-07-17 13:54:56 +08:00
如果你真的担心大流量,优化业务逻辑为先,用好 redis,然后做负载均衡+多台部署,时间允许的话,底层代码换 swoole 协程,最后上一套 k8s 做好自动部署
|
21
yc8332 2020-07-17 15:02:37 +08:00
@mitu9527 说了 opcache 不是马上失效,是去检测是否失效,重建。和你自己设计缓存系统一下,你会让所有的请求都去重建一个通用的缓存吗?人家的系统是考虑的。
|
22
mitu9527 OP @gantleman 谢谢,我明白服务器崩溃并不是这么容易。我是反过来想,把 OPcache 缓存可能会造成雪崩的情况给找出来并解决,就不用担心雪崩了。OPcache 的设计是基于源文件路径来缓存源文件的字节码,如果采取覆盖式发布,发布完要重置缓存,理论上这里也会发生缓存雪崩,但是此时可以开启 OPcache 的 file cache,虽然压力还是会有,但是不至于崩溃,如果项目还可以开启预加载,压力就会更小,所以在覆盖式发布下,雪崩可以避免。但软链接式发布,新版本的代码全都在新的路径下,而就像上面说的 OPcache 的设计是基于源文件路径来缓存的,所以之前为旧版本建好的缓存全都相当于自动失效了,还占着位置,file cache 也是一样失效了,如果再不能启用预加载,我认为一定会缓存雪崩。至于缓存雪崩会不会导致服务器崩溃,那要看情况。所以我目前认为,软链接式发布,一定会缓存雪崩,这个问题还是要尽量去解决掉的,解决不掉才可以采用你们建议的各种方案进行规避,总之放在那不理会感觉不太好。
另外,你说的外网带宽、内外带宽和硬盘 io 的这种阶梯我其实也知道。如果只是读写文件,那确实几乎百分百适用,因为是对于三者来说,数据量差不多是相等的。但对于 Web 请求来说就不一定了,一个动态 http 请求返回的数据大小一般都在几 k 到小几十 k 之间,而为了生成这份请求数据,读写的 PHP 源文件很可能有小几十个,总大小加起来上百 k 也是很常见的,这时这种速度阶梯不见得可靠,还是要观察。 最后,我到目前为止,只用过 CDN 加速静态请求文件,还没加速过动态请求文件,所以这块保留不谈。 |
23
gantleman 2020-07-17 16:14:18 +08:00
@mitu9527 也许你还会找到其他的方法,这些方法都能在一定概率上保证服务器不崩溃。并且每增加一个方法都会降低崩溃的概率。也可以找到一种使崩溃大幅下降的方法。也可能会找到一种价格最便宜的方法。或者找到一个价格最便宜并且效果最好的方法。但你思考的问题已经非常的深。恐怕很少人能帮助你,需要你自己去实验代码,检索开源代码,查找论文。从模糊的知识碎片到形成问题,到找到答案,再实验,再迭代。
好像我又自言自语的说奇怪的话,简单说我知道的就这么多了。完全避免崩溃是不可能的,但应该有更好的方法还没被发现。 |
24
mitu9527 OP @yc8332 能说一下是怎么做到的么?是用了锁和队列,还是像 APCu 那样通过 slam_defense 去随机抽签?
|
26
rushssss 2020-07-17 17:43:56 +08:00
OPcache 的缓存是基于时间的,过期的才会去重载缓存,而发布代码最重要的是什么?是确定新代码上线并且保持一致性!
所以发布代码以后都会主动清除缓存以保持新代码的一致性,这里不是一个可以做性能优化的点,而是必要的操作。 另外根据经验 OPcache 带来的性能提升百分比不会超过整个系统的性能上限,除非你的系统本来就不勘重负必须要运行 warm 的代码才能正常提供服务。 最后如果实在不能接受缓存失效的代价,那就滚动更新了,一个新实例足够 warm 以后撤下一个旧实例再以此类推 |