• manatee
    2019-08-28
    想请问下老师多次提到的timer数量限制,这个限制具体是多少呢,从哪里可以查到相关资料呢

    作者回复: lua_max_pending_timers 和 lua_max_running_timers 这两个指令来做控制

     2
     4
  • Shliesce
    2019-09-01
    接着我上面的这个观点,最近在设计“联动注册发现中心 动态更新 upstream 并缓存在进程内”的插件时,目前仅做了shared dict这一层的缓存,从初步的压测结果来看,单机 32C 的 cpu 平均使用率 30%可以达到 8w 的 qps,也不知道是不是错觉,性能比我们用 upsync 时还要好。。。
    重点是在后续增加 lrucache 时,因为考虑到这种场景不存在key expired 的问题,主要是 value 变更比较频繁,且需要保证尽可能的数据一致性,像 mlcache 这种被动更新的逻辑就不太好实现,而且还要考虑到每次 reload 时的lrucache 全量 miss 的场景,最终评估下来我决定采用主动更新缓存的方案。同时因为 nginx 每次 reload 时都会加载 init_by_lua*阶段,所以我打算把主动更新的逻辑做到 init 阶段,借助 master fork worker 时继承内存空间的逻辑提前预热缓存;另外就是每次更新 shared dict 时同步更新 lrucache。暂时还不确定这个方案有没有什么坑,老师能帮忙提几条建议吗?
    展开

    作者回复: 没有明白为什么把主动更新的逻辑放在 init 阶段呢?
    你可以在 init 阶段获取全量数据,通过长连接监听事件通知,去获取增量的数据。
    这时候其实你可以只用 lru 缓存,去掉共享字典这个 L2 缓存。
    APISIX(https://github.com/iresty/apisix)也是这么实现的,它的数据源在 etcd,通过 etcd 的 watch 来获取上游的变更。

    
     2
  • Shliesce
    2019-09-01
    在实际的生产应用中,我认为 shared dict 这一层缓存是必须的,貌似大家都只记得lrucache的好,数据格式没限制,不需要反序列化,不需要根据 k/v 体积算内存空间,worker 间独立不相互争抢,没有读写锁,性能高云云,但是却忘记了它最致命的一个弱点就是 lrucache 的生命周期是跟着 worker 走的,每当nginx reload 时,这部分缓存会全部丢失,这时候如果没有 shared dict,那 L3 的数据源分分钟被打挂,当然这是并发比较高的情况下,但是既然用到了缓存,说明业务体量肯定不会小。。不知道我的这个观点对吗?

    作者回复: 大部分情况下确实如你所说,共享字典在 reload 的时候不会丢失。也有一种特例,如果在 init 阶段或者init_worker阶段就能从 L3 主动获取到所有数据,那么只有 L1 其实也是可以接受的。

    
     2
  • 许童童
    2019-08-28
    共享字典这一层缓存不是必须的,但有这一层性能会高很多,因为lrucache 只能在单个worker中共享,而共享字典可以在整个server中共享,所以当一个worker中命中不了时,此时数据可能在另一个worker中存在,如果有server层的缓存,那命中率将大大提高。
    
     2
  • 张仕华
    2020-01-17
    多级缓存的更新类似cpu,必须有lrucache层的缓存失效信号,看了看文档也确实是这样。但其实还有个疑问,如何更新db中的数据然后让缓存失效呢?
    
    
  • 言身寸飞
    2019-09-19
    我觉得shared dict是必须的。如果只有L1的话,量级大的、缓存经常变化的应用的话work多的话后面的数据会有连接压力吧。
    
    
  • wusiration
    2019-08-28
    共享字典这一层缓存并非必须,只用lrucache同样可以满足需求。只不过多加一层L2缓存(共享字典),可以使得服务器在L1缓存未命中的情况下,通过多个worker之间的共享数据,以减少读库的次数。
    
    
我们在线,来聊聊吧