V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
mitu9527
V2EX  ›  PHP

OPcache 配合软链接发布的一个疑问,希望懂的人帮忙解答一下

  •  1
     
  •   mitu9527 · 2020-07-17 09:51:46 +08:00 · 2314 次点击
    这是一个创建于 1350 天前的主题,其中的信息可能已经有所发展或是发生改变。

    如果一个项目开启了 OPcache,但是不启用预加载,同时该项目使用的是软链接到新目录的方式发布新版本。

    因为 OPcache 使用的是文件路径来标识缓存,由于软链接到了新的目录,所以文件路径变了,那不就要重建全部的缓存,不就是缓存雪崩了么?就算开启了 OPcahce 的 file cache 好像也帮不上忙,因为 file cache 也是基于文件路径的。

    问题一:是不是真的就会缓存雪崩? 问题二:除了换成覆盖式发布,还有办法解决么?

    第 1 条附言  ·  2020-07-17 10:37:42 +08:00
    更正:缓存雪崩 =》 缓存击穿
    第 2 条附言  ·  2020-07-17 11:27:45 +08:00
    补充:我觉得这个情况还是叫缓存雪崩比较合适,因为(上个版本对应的)全部缓存在同一时间点失效,整体雪崩了。而不是个别缓存因为到期失效而被击穿。
    26 条回复    2020-07-17 17:43:56 +08:00
    rushssss
        1
    rushssss  
       2020-07-17 10:22:20 +08:00
    第一缓存雪崩不是这个意思,第二你更新了代码但是 OPcache 不更新跑的不就是原来的代码了? 那更新代码有啥意义
    mitu9527
        2
    mitu9527  
    OP
       2020-07-17 10:28:04 +08:00
    @rushssss 这个不是缓存雪崩么,那是啥?第二点,代码发布到新目录下,所有文件的路径全部变了,OPcache 中现有的缓存全都是以前的路径的,也用不到了,相当于自动作废了,不是么?然后这时候去访问新版本,不就相当于从头开始建缓存么?
    yc8332
        3
    yc8332  
       2020-07-17 10:33:40 +08:00
    你在说什么?先把概念搞清楚再发帖吧
    mitu9527
        4
    mitu9527  
    OP
       2020-07-17 10:34:52 +08:00
    @yc8332 我去改一下
    simapple
        5
    simapple  
       2020-07-17 11:01:49 +08:00
    你是要做什么?让不同机器的 php 进程复用同一份 opcache ?
    mitu9527
        6
    mitu9527  
    OP
       2020-07-17 11:09:53 +08:00
    @simapple 就是想问一下,使用软链接到新目录的方式发布新版本,旧的 OPcache 缓存就全部失效,就相当于从头建缓存,在高流量的服务器上压力不就瞬间上来了?想问一下有没有什么办法解决。
    yc8332
        7
    yc8332  
       2020-07-17 11:40:04 +08:00
    opcache 的缓存也是有时间的。并不是说你代码更新了马上就更新,更新也不是全部都更新,用到才会更新。。而且这个也不是什么缓存击穿、缓存雪崩。。。那个是相对应缓存系统来说的,有兴趣可以自己搜索一下
    mitu9527
        8
    mitu9527  
    OP
       2020-07-17 11:45:34 +08:00
    @yc8332 OPcache 也算是缓存,怎么不能用这些词啊,有人规定这些词只能用在 redis 和 memcache 上?再者,你确定你理解我在问什么了么?我看不是我讲的不够清楚,是你没理解。
    hauzi
        9
    hauzi  
       2020-07-17 11:46:52 +08:00   ❤️ 1
    先把常用的 PHP 脚本预热下
    mitu9527
        10
    mitu9527  
    OP
       2020-07-17 11:50:37 +08:00
    @hauzi 我明白预加载可能解决这个问题,但是不是所有项目都能预加载,而且预加载是把缓存放在工作进程上,也不是所有内容都适合预加载,所以我才问不启用预加载的情况下,有没有办法解决这个问题。
    yc8332
        11
    yc8332  
       2020-07-17 11:53:18 +08:00
    @mitu9527 opcache 不会马上都更新,你觉得你的 php-fpm 进程一开始,服务器的处理能力会影响到你的 qps 吗?如果不会,更新代码也不会有这个问题。
    mitu9527
        12
    mitu9527  
    OP
       2020-07-17 11:58:03 +08:00
    @yc8332 请求一个新文件,不会去更新?高并发场景下,多人同时去读取这个文件,然后尝试去把这个文件的字节码写到 OPcache 中,那个瞬间,CPU 压力不就爆了?
    coosir
        13
    coosir  
       2020-07-17 12:08:35 +08:00
    更新代码后,主动清一下 opcache
    mitu9527
        14
    mitu9527  
    OP
       2020-07-17 12:12:57 +08:00
    @coosir opcache 被重置后,不也是相当于任何缓存都没有了,效果不也和缓存雪崩一样了么?瞬间压力就上来了。
    loveyu
        15
    loveyu  
       2020-07-17 12:43:31 +08:00   ❤️ 1
    看了上面的。楼主安心摘流量,然后一点点放量吧,这样就没这些问题。

    还要,清缓存就是了,并发读文件建缓存那点压力,忽略吧
    mitu9527
        16
    mitu9527  
    OP
       2020-07-17 12:56:32 +08:00
    @loveyu 高并发下重建缓存那个瞬间,压力比不开启 OPcache 直接去读 PHP 源文件还要大,直接不管了么?我觉得这个点可能是 PHP 压力的最高点,最有可能撑不住的就是这个点,所以才想问。
    coosir
        17
    coosir  
       2020-07-17 13:17:29 +08:00   ❤️ 1
    @mitu9527 真有这么大流量那就是很多个实例来支撑,那么就不应该热更。
    就像上面说的,发布的时候部分实例先摘掉下线,更新代码,预热好,再上线。逐步更新所有实例防止服务中断。
    mitu9527
        18
    mitu9527  
    OP
       2020-07-17 13:24:18 +08:00
    @coosir 明白了,谢谢!
    gantleman
        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,才可能触发雪崩。这里还没考虑限流措施。

    雪崩有存在的可能,但在实际运维的条件下,要达到雪崩的条件非常苛刻。
    wangritian
        20
    wangritian  
       2020-07-17 13:54:56 +08:00
    如果你真的担心大流量,优化业务逻辑为先,用好 redis,然后做负载均衡+多台部署,时间允许的话,底层代码换 swoole 协程,最后上一套 k8s 做好自动部署
    yc8332
        21
    yc8332  
       2020-07-17 15:02:37 +08:00
    @mitu9527 说了 opcache 不是马上失效,是去检测是否失效,重建。和你自己设计缓存系统一下,你会让所有的请求都去重建一个通用的缓存吗?人家的系统是考虑的。
    mitu9527
        22
    mitu9527  
    OP
       2020-07-17 15:39:36 +08:00
    @gantleman 谢谢,我明白服务器崩溃并不是这么容易。我是反过来想,把 OPcache 缓存可能会造成雪崩的情况给找出来并解决,就不用担心雪崩了。OPcache 的设计是基于源文件路径来缓存源文件的字节码,如果采取覆盖式发布,发布完要重置缓存,理论上这里也会发生缓存雪崩,但是此时可以开启 OPcache 的 file cache,虽然压力还是会有,但是不至于崩溃,如果项目还可以开启预加载,压力就会更小,所以在覆盖式发布下,雪崩可以避免。但软链接式发布,新版本的代码全都在新的路径下,而就像上面说的 OPcache 的设计是基于源文件路径来缓存的,所以之前为旧版本建好的缓存全都相当于自动失效了,还占着位置,file cache 也是一样失效了,如果再不能启用预加载,我认为一定会缓存雪崩。至于缓存雪崩会不会导致服务器崩溃,那要看情况。所以我目前认为,软链接式发布,一定会缓存雪崩,这个问题还是要尽量去解决掉的,解决不掉才可以采用你们建议的各种方案进行规避,总之放在那不理会感觉不太好。

    另外,你说的外网带宽、内外带宽和硬盘 io 的这种阶梯我其实也知道。如果只是读写文件,那确实几乎百分百适用,因为是对于三者来说,数据量差不多是相等的。但对于 Web 请求来说就不一定了,一个动态 http 请求返回的数据大小一般都在几 k 到小几十 k 之间,而为了生成这份请求数据,读写的 PHP 源文件很可能有小几十个,总大小加起来上百 k 也是很常见的,这时这种速度阶梯不见得可靠,还是要观察。

    最后,我到目前为止,只用过 CDN 加速静态请求文件,还没加速过动态请求文件,所以这块保留不谈。
    gantleman
        23
    gantleman  
       2020-07-17 16:14:18 +08:00
    @mitu9527 也许你还会找到其他的方法,这些方法都能在一定概率上保证服务器不崩溃。并且每增加一个方法都会降低崩溃的概率。也可以找到一种使崩溃大幅下降的方法。也可能会找到一种价格最便宜的方法。或者找到一个价格最便宜并且效果最好的方法。但你思考的问题已经非常的深。恐怕很少人能帮助你,需要你自己去实验代码,检索开源代码,查找论文。从模糊的知识碎片到形成问题,到找到答案,再实验,再迭代。
    好像我又自言自语的说奇怪的话,简单说我知道的就这么多了。完全避免崩溃是不可能的,但应该有更好的方法还没被发现。
    mitu9527
        24
    mitu9527  
    OP
       2020-07-17 16:17:41 +08:00
    @yc8332 能说一下是怎么做到的么?是用了锁和队列,还是像 APCu 那样通过 slam_defense 去随机抽签?
    mitu9527
        25
    mitu9527  
    OP
       2020-07-17 16:19:57 +08:00
    @gantleman 我不认为你说的话奇怪哈,挺实用的,虽然不见得能百分百适用,但方向是没问题的,再次感谢。
    rushssss
        26
    rushssss  
       2020-07-17 17:43:56 +08:00
    OPcache 的缓存是基于时间的,过期的才会去重载缓存,而发布代码最重要的是什么?是确定新代码上线并且保持一致性!

    所以发布代码以后都会主动清除缓存以保持新代码的一致性,这里不是一个可以做性能优化的点,而是必要的操作。

    另外根据经验 OPcache 带来的性能提升百分比不会超过整个系统的性能上限,除非你的系统本来就不勘重负必须要运行 warm 的代码才能正常提供服务。

    最后如果实在不能接受缓存失效的代价,那就滚动更新了,一个新实例足够 warm 以后撤下一个旧实例再以此类推
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1097 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 22:48 · PVG 06:48 · LAX 15:48 · JFK 18:48
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.