Yii2 redis Active Record 使用, 查询慢的问题

Redis · Fecmall · 于 6年前 发布 · 4413 次阅读

Yii2 有redis AR扩展,可以方便的使用

但是使用过程中,发现AR的查询非常的慢

譬如我的定义:

namespace fecshop\models\redis;

use yii\redis\ActiveRecord;

/**
 * @author Terry Zhao <2358269014@qq.com>
 * @since 1.0
 */
class SessionStorage extends ActiveRecord
{
    public function attributes()
    {
        return [
            'id', 'session_uuid',
            'session_key', 'session_value',
            'session_timeout','session_updated_at'
        ];
    }
    /**
     * relations can not be defined via a table as there are not tables in redis. You can only define relations via other records.
     */
}

查询:

$one =  SessionStorage::find()->where([
            'session_uuid' => $uuid,
            'session_key'  => $key,
        ])->one();

改进:

redis AR中插入数据的id通过 uuid 和key生成,

public function getUuidKey($uuid, $key){
        return $uuid.'###^^###'.$key;
    }

查询:

public function get($key,$reflush){
        $uuid = Yii::$service->session->getUUID();
        $r_id = $this->getUuidKey($uuid, $key);
        $one = $this->_sessionModel->find()->where([
            'id' => $r_id,
        ])->one();
        if($one['id']){
            $timeout = $one['session_timeout'];
            $updated_at = $one['session_updated_at'];
            if($updated_at + $timeout > time()){
                if($reflush){
                    $one['session_updated_at']  = time();
                    $one->save();
                }
                return $one['session_value'];
            }
        }
    }

速度明显提升,对于vue端,以前需要300ms,现在只要100多ms(中间有网络时间,访问html静态文件也要80ms)

issue: https://github.com/yiisoft/yii2-redis/issues/146

共收到 17 条回复
Fecmall#16年前 0 个赞

对fecshop的代码进行了优化, https://github.com/fecshop/yii2_fecshop/commit/5173c7e2e3c9c260cf11570147fa71b793a9df21

vue访问速度明显提升

Axin#25年前 0 个赞

生产环境出现问题。

appserver session_storage中一直生成。导致接口响应超过2s。

Fecmall#35年前 0 个赞

@Axin #2楼

你能debug一下吗?说一下具体的原因,为什么会一致生成

代码位置:https://github.com/fecshop/yii2_fecshop/blob/master/services/session/SessionRedis.php#L35

你看看你的代码和这里的代码是不是一致?

debug一下具体的代码执行,说一下代码行,这样不好诊断

Axin#45年前 0 个赞

@Fecshop [[#3楼](#comment3)](#comment3) 代码是一致的。

我看代码是这样理解的,appserver入口 前端如果没有带uuid访问,后台会给他生成一个。可生成的session并没有过期时间,就会出现有redis key残留。 我看session中配置是有过期时间配置

'timeout' => 3600,

但该配置只对session_storage时 Hash里session_timeout值有效。

我现在做法是给session_storage中key设置过期时间。第六感觉 应该不是这样做

appserver main.php配置中的 'database' => 9, 也是无效的吧。

'session' => [
            /*
             * // use mongodb for session.
             * 'class' => 'yii\mongodb\Session',
             * 'db' => 'mongodb',
             * 'sessionCollection' => 'session',
             */
            'class'   => 'yii\redis\Session',
            'timeout' => 86400 * 7,
            'keyPrefix' => 'appserver_session',
            'redis' => [
                'database' => 9,
            ],
        ],
Fecmall#55年前 0 个赞

这个地方存在问题,使用使用redis的GET来做

https://redis.io/commands/set

EX seconds -- Set the specified expire time, in seconds.

而redis的AR用的是HMSET , https://redis.io/commands/hmset ,这个是没有过期时间的,因此这个地方需要重构一下

https://github.com/fecshop/yii2_fecshop/blob/master/services/session/SessionRedis.php#L35

重构完成后通知你

Fecmall#65年前 0 个赞

https://github.com/fecshop/yii2_fecshop/commit/77593d8d7ec6eae1966e8de291713cb54b4435d9

你可以将 services/session/SessionRedis.php 重新覆盖下你的本地

然后试试结果,重构后的使用的redis session的实现,使用的是timeout的SET方式

Fecmall#75年前 0 个赞

@Axin [#4楼](#comment4)

你的那种配置方式不对,不会生效,用我上面修改的方式测试下。

试玩后,回复一下,是否还有问题

Axin#85年前 0 个赞

刚把你的SessionRedis直接覆盖测试。 访问appserver 接口出现这种情况。访问一直追加生成的uuid

Fecmall#95年前 0 个赞

@Axin [[#8楼](#comment8)](#comment8)

如果是只有一个用户访问,第一次会添加一条数据到redis,后面的就不会了

当超时后,redis会删除掉这个记录

不明白你说的访问一直追加生成的uuid是什么意思,第一次访问,返回的Fecshop-Uuid,第二次得加上

Fecshop-Uuid	
6e10db6a-c14e-11e8-a721-00163e021360
Fecmall#105年前 0 个赞

我明白你的意思了,明天我测一下/

Axin#115年前 0 个赞

@Fecshop #10楼 我也回去晚上看一下。上头让我弄个pop3 接收gmail邮件。我先忙下公司的事

Axin#125年前 0 个赞

刚在google里面看到你这篇:

先拜读下https://blog.csdn.net/terry_water/article/details/14141775

Fecmall#145年前 0 个赞

@Axin [#12楼](#comment12) 按照试一下,我测试没有问题了,用redis 的 set 设置timeout时间, 另外,当时间快要过期的时候,更新timeout,这样可以持续访问的用户可以保证不过期。

看看还有问题不?有问题随时提交过来

Axin#155年前 0 个赞

@Fecshop #14楼

刚同步了下,现在看是没有之前追加的问题了,我测试段时间看看。

Fecmall#165年前 0 个赞

@Axin #15楼

恩,你仔细看一下代码,需要做设置,设置过期时间,和多长时间更新过期时间

譬如:过期时间为2小时, 30分钟需要更新过期时间,那么当1小时35分钟后访问,过期时间重新设置2小时,这样是为了持续的访问

删除机制是redis自动删除,使用了redis set command, 里面设置了过期时间

你可以先读一下代码,看看有没有问题,然后在测试一下。

Axin#175年前 0 个赞

恩,同步在了测试服,我测试一下

添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册
Your Site Analytics