【问题标题】:PHP Redis Session Locking InternalsPHP Redis 会话锁定内部机制
【发布时间】:2019-12-20 14:06:14
【问题描述】:

phpredis 会话锁定在内部如何工作?它是否在内部存储一个值并继续检查它?如果我有一个很高的redis.session.lock_retries,如果需要 10 秒才能获得锁定并且必须尝试数千次,这是否会给服务器带来负载?

以下是配置参数。

; Should the locking be enabled? Defaults to: 0.
redis.session.locking_enabled = 1
; How long should the lock live (in seconds)? Defaults to: value of max_execution_time.
redis.session.lock_expire = 60
; How long to wait between attempts to acquire lock, in microseconds (µs)?. Defaults to: 2000
redis.session.lock_wait_time = 50000
; Maximum number of times to retry (-1 means infinite). Defaults to: 10
redis.session.lock_retries = 10

【问题讨论】:

    标签: php phpredis


    【解决方案1】:

    添加这个的提交是here

    似乎暗示它使用了锁定配方described in the Redis docs

    总的来说,这个秘诀依赖于原子尝试设置一个不存在的密钥(这是锁),如果它已经存在则失败。这意味着每次尝试都是对 Redis 服务器的命令,它本身非常快,但是如果您的 Redis 服务器是远程托管的,那么就会产生网络往返的开销

    【讨论】:

    • 好的,明白了。在我的情况下,锁定不会经常发生,但如果发生,可能需要 1-10 秒。对于我所描述的参数,您有什么建议?此外,如果在redis.session.lock_retries 之后未能获得锁,程序是否会继续执行并丢失任何数据或对会话的访问(设置或获取)
    • 我认为 2 秒的等待时间应该很不错。如果 Redis 与 Web 服务器在同一台服务器上(或者如果您在 AWS 上运行并在同一 VPC 上使用 ElasticCache),那么您可能会减少它。我不建议增加它,除非往返非常高(在这种情况下,使用 Redis 进行缓存可能最终会适得其反)
    【解决方案2】:

    Looks like it's a hot loop:

    static int lock_acquire(RedisSock *redis_sock, redis_session_lock_status *lock_status)
    {
      ...
      for (i = 0; retries == -1 || i <= retries; i++) {
          set_lock_key_result = set_session_lock_key(redis_sock, cmd, cmd_len);
          ...
          /* Sleep unless we're done making attempts */
          if (retries == -1 || i < retries) {
            usleep(lock_wait_time);
          }
    

    对于长阻塞请求没有指数回退或其他缓解措施。如果您有很高的传播(例如,有时即时锁定获取,有时 1 秒,有时 10 秒等),那么我建议将锁定尝试长度设置得非常低,然后编写自己的热循环,该循环更符合您的预期等待时间。如果您有一个相当稳定的预期等待时间(例如总是大约 10 秒),那么只需将等待时间设置得相当长。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-22
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-31
      • 2011-01-21
      • 1970-01-01
      相关资源
      最近更新 更多