Redis扫描密钥限制

时间:2018-09-04 14:23:00

标签: redis

我有一些代码在每个用户的唯一密钥下,在redis中存储一个用户是否处于活动状态的标志。

class RedisProfileActiveRepo implements ProfileActiveRepo
{
    /** @var Redis  */
    private $redis;

    public function __construct(Redis $redis)
    {
        $this->redis = $redis;
    }

    public function markProfileIsActive(int $profile_id)
    {
        $keyname = ProfileIsActiveKey::getAbsoluteKeyName($profile_id);

        // Set the user specific key for 10 minutes
        $result = $this->redis->setex($keyname, 10 * 60, 'foobar');
    }

    public function getNumberOfActiveProfiles()
    {
        $count = 0;
        $pattern = ProfileIsActiveKey::getWildcardKeyName();
        $iterator = null;

        while (($keys = $this->redis->scan($iterator, $pattern)) !== false) {
            $count += count($keys);
        }

        return $count;
    }
}

当我从此代码生成密钥时:

namespace ProjectName;

class ProfileIsActive
{
    public static function getAbsoluteKeyName(int $profile_id) : string
    {
        return __CLASS__ . '_' . $profile_id;
    }

    public static function getWildcardKeyName() : string
    {
        return __CLASS__ . '_*';
    }
}

这会导致键看起来像ProjectName\ProfileIsActive_1234,Redis中的扫描命令无法匹配任何键。

当我用下划线替换斜杠时:

class ProfileIsActive
{
    public static function getAbsoluteKeyName(int $profile_id) : string
    {
        return str_replace('\\', '', __CLASS__) . '_' . $profile_id;
    }

    public static function getWildcardKeyName() : string
    {
        return str_replace('\\', '', __CLASS__) . '_*';
    }
}

代码按预期工作。

我的问题是-为什么在键名中使用斜杠进行扫描无法正常工作,并且在键名中还应该避免使用其他字符来避免类似的问题吗?

1 个答案:

答案 0 :(得分:1)

理论上最新的Redis在redis-cli中设置键时会自动转义反斜杠:

127.0.0.1:6379> set this\test 1
OK
127.0.0.1:6379> keys this*
1) "this\\test"

在运行PHP客户端代码之前,请在MONITOR中发出redis-cli命令,并注意SCAN命令。如果您的集合足够大,而count参数不存在或足够低,则您可能不会获得记录:

127.0.0.1:6379> scan 0 match this*
1) "73728"
2) (empty list or set)

127.0.0.1:6379> scan 0 match this* count 10000
1) "87704"
2) 1) "this\\test"