首页 > 数据库 >php redis之高性能扫描和批量操作

php redis之高性能扫描和批量操作

时间:2022-12-27 20:58:04浏览次数:37  
标签:scan keyArr redis 游标 高性能 key test php

前提:

redis的扫描方法,使用scan,而不是使用 keys* 

因为keys* 会全部key扫描一次,key数量很多时,容易造成阻塞太久甚至down机。

 

scan 原理: 指定每次遍历的key数目和查找规则 ,通过遍历去匹配出对应的key。还会返回当前最后一个匹配值的游标cursor 

scan 语法:   SCAN cursor [MATCH pattern] [COUNT count]

  • cursor - 游标。从0开始
  • pattern - 匹配的规则。
  • count - 指定每次遍历多少个key。
    • 可以简单理解为每次遍历多少个元素
    • 根据测试,推荐 Count大小为 10000

 

因此:Count 参数和  Key的总数 一致时,Scan 命令就和 Keys 效果一样了。Count 参数越大,总时间越短,但每次Redis 阻塞时间也会越长,需要取舍。

 

 

scan用法:

SCAN命令是基于游标的,每次调用后,都会返回一个游标,用于下一次迭代。当游标返回0时,表示迭代结束。

第一次 Scan 时指定游标为 0,表示开启新的一轮迭代,然后 Scan 命令返回一个新的游标,作为第二次 Scan 时的游标值继续迭代,一直到 Scan 返回游标为0,表示本轮迭代结束。

eg: 我想查找  test 开头的key,每次查找30条

 

1.第一次执行找到了test_b,返回了下个游标 17 。

scan 0 match test* count 30

2.使用上次返回的游标,再次查找,又找到了 test_a 和 test

scan 17 match test* count 30

此时游标返回0,表示结束,一共找到 test_a test_b test 三个key

 

在PHP的用法:

/**
 * 查找redis key
 * @param null $pattern // 要匹配的规则  'test_*'
 * @param int $count    // 每次遍历数量.count越大总耗时越短,但单次阻塞越长。 建议5000-10000。并发不高则可以调至接近1w。
 * @return array
 */
public function scan($pattern,$count = 6000){
    $keyArr = array();
    while (true){
        // $iterator 下条数据的坐标
        $data = $this->redis->scan($iterator, $pattern, $count);
        $keyArr = array_merge($keyArr,$data ?: array() );

        if ($iterator === 0){   //迭代结束,未找到匹配
            break;
        }
        if ($iterator === null) {//"游标为null了,重置为0,继续扫描"
            $iterator = "0";
        }

    }
    $keyArr = array_flip($keyArr);
    $keyArr = array_flip($keyArr);
    return $keyArr;
}

//使用 查找test开头的key
$pattern = 'test*';
$this->scan($pattern);

 

 

查出来key之后,若要批量删除,则可以使用redis管道 PIPELINE ,效果是 将多个命令合起来只执行一次,减少redis和客户端的交互时间;

其他批量操作也可以用PIPELINE,下面举个删除的例子:

$keyArr = array('test','test_a','test_b');
$pipe = $redis->multi(2);   //使用管道 事务=2,表示使用管道
foreach ($keyArr as $key){
    $pipe->del($key);
}
$pipe->exec();

 

 

最后来个 PIPELINE结合scan的用法:

// 返回查询的redis key
function redisScan($pattern = null,$count = 6000,$is_del = 1){
    $redis = RedisClient::getInstance();
    $keyArr = $redis->scan($pattern,$count); // 上面的scan方法

    if ($is_del){
        $pipe = $redis->multi(2);   //使用管道
        foreach ($keyArr as $key){
            $pipe->del($key);
        }
        $pipe->exec();

    }else{
        return $keyArr ?? [];
    }
}

//清除缓存
$pattern = 'test*';
$this->redisScan($pattern);

 

标签:scan,keyArr,redis,游标,高性能,key,test,php
From: https://www.cnblogs.com/jaychou-/p/17008906.html

相关文章

  • Redis的高并发和快速原因
     1.Redis是基于内存的,内存的读写速度非常快;2.Redis是单线程的,省去了很多上下文切换线程的时间;3.Redis使用多路复用技术,可以处理并发的连接。非阻塞IO内部实现采用epol......
  • 欢迎加入Apache Mina高性能通信框架研究邮件列表.
    一直到现在,我都没有发现国内讨论ApacheMina高性能通信框架研究的好地方。我也经常被网友问起一些有关ApacheMina高性能通信框架研究相关的问题,有些问题是很基本的网络编......
  • php包管理工具推荐
    ​​http://www.phpcomposer.com/​​ Composer是PHP用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer会帮你安装这......
  • CakePHP 2.x十分钟博客教程(一):安装与配置
     Cakephp2.0依然保持着Cakephp框架的各种优良传统,其中之一就是非常易于新手入门,几乎不做任何复杂的配置即可使用。非常可惜的是,Cakephp2.0手册竟然没有了中文翻译,1.3的翻......
  • 严重漏洞攻击:影响PHP、Java和ASP.NET
    安全研究员AlexanderKlink和JulianWalde发现了一个严重的漏洞,这个漏洞影响到大多数网络服务器。针对这个漏洞的攻击只需要一个HTTP请求,这个特殊设定......
  • redis针对超卖现象
    可以使用锁的方式解决锁分为乐观锁和悲观锁  乐观锁的实际运用方法:版本号法通过在数据库中的一个版本号字段来表示。 乐观锁又利用了CAS的思想......
  • Seata-php 入门与下半年展望
    通俗地讲,Seata-php是seata的PHP语言实现,实现了Java和PHP之间的互通,让PHPer也能使用seata-php来实现分布式事务。Seata是一个非常成熟的分布式事务框架,在Java......
  • Redis持久化
    Redis 为了内存数据的安全考虑,会把内存中的数据以文件形式保存到硬盘中一份,在服务器重启之后会自动把硬盘的数据恢复到内存(redis)的里边。数据保存到硬盘的过程就称为“持......
  • 高性能 Python web 框架 Blacksheep 初见
    Pythonweb框架性能对比一说到Python大家多半最先想到的就是它代码的简洁与性能的孱弱。在我所使用体验过的Pythonweb框架中Tornado性能最好,Flask次之,Django最差......
  • 基于go语言的声明式流式ETL,高性能和弹性流处理器
    简要介绍Benthos,并给出若干示例,指导如何安装和运行。BenthosBenthos是一个开源的、高性能和弹性的数据流处理器,能够以各种代理模式连接各种源和汇,可以帮助用户在不同......