关于session 的 redis 实现问题,目前参考了ci和laravel 的实现,有些疑问?

1.laravel
看了文档,文档中使用的是 predis 这个包,实现 session redis handel 地址:
github.com/predis/predis/blob/v1.1...

    /**
     * {@inheritdoc}
     * @return bool
     */
    #[\ReturnTypeWillChange]
    public function write($session_id, $session_data)
    {
        $this->client->setex($session_id, $this->ttl, $session_data);

        return true;
    }

实现起来有点简单,setnx 都不判断返回值的么?

2.ci
自带 session redis handel 地址
github.com/codeigniter4/CodeIgnite...

    /**
     * Acquires an emulated lock.
     *
     * @param string $sessionID Session ID
     */
    protected function lockSession(string $sessionID): bool
    {
        // PHP 7 reuses the SessionHandler object on regeneration,
        // so we need to check here if the lock key is for the
        // correct session ID.
        if ($this->lockKey === $this->keyPrefix . $sessionID . ':lock') {
            return $this->redis->expire($this->lockKey, 300);
        }

        $lockKey = $this->keyPrefix . $sessionID . ':lock';
        $attempt = 0;

        do {
            if (($ttl = $this->redis->ttl($lockKey)) > 0) {
                sleep(1);

                continue;
            }

            if (! $this->redis->setex($lockKey, 300, (string) time())) {
                $this->logger->error('Session: Error while trying to obtain lock for ' . $this->keyPrefix . $sessionID);

                return false;
            }

            $this->lockKey = $lockKey;
            break;
        } while (++$attempt < 30);

        if ($attempt === 30) {
            log_message('error', 'Session: Unable to obtain lock for ' . $this->keyPrefix . $sessionID . ' after 30 attempts, aborting.');

            return false;
        }

        if ($ttl === -1) {
            log_message('debug', 'Session: Lock for ' . $this->keyPrefix . $sessionID . ' had no TTL, overriding.');
        }

        $this->lock = true;

        return true;
    }

注意,lockSession 方法里的 sleep?
这是啥,这里有个问题,相同 session 的并发请求,会造成 1s 上的延迟,这是啥?(这里 sleep 我们团队直接改成 100ms 了)
争议连接:github.com/bcit-ci/CodeIgniter/pul...

就感觉这两种实现方式,都有点奇怪,有没有大佬说下?
我准备再去看看其他框架的实现,大家一起沟通下

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 8

我再去看看 协程框架的

3年前 评论

hyperf 的 与 laravel 类似,但是没有上面说的直接返回 true 的问题, 关于 ci 的实现,感觉是,在程序方面 采用 sleep 重试的方式,减缓 redis 的压力。

3年前 评论

1 假设没有异常的话 确实不应该

2 看样子是锁的重试。 类似 Lock 之类的组件代码过一遍 都有 sleep

3年前 评论
zion_xayts_com (楼主) 3年前
cvoid (作者) 3年前
zion_xayts_com (楼主) 3年前

@Macken 这个是谁?咋没看到,管理员么

3年前 评论
  • 第一种方式比较简单粗暴,正常情况下是会写入成功的,如果在下面你用上面写入 session 数据做判断的时候可能已经被其他线程修改了
  • 第二个是做了防止 session 并发读写的,先获取锁,再进行写数据,while 是获取锁失败后进行的多次尝试,应该类似于 go 协程里面并发控制的自旋锁
3年前 评论