Redis之Key值遍历

话不多说,先上码


    @Test
    public void test12(){
        Jedis jedis = new Jedis("x.x.x.x", 6379);
        jedis.auth("xxx");

        long start = System.currentTimeMillis();
        String cursor = "0";
        do {
            ScanParams scanParams = new ScanParams();
            scanParams.match("hello*");

            ScanResult scan = jedis.scan(cursor, scanParams);
            List result = scan.getResult();
            result.forEach(x->{
                System.out.println(x);
            });
            cursor = scan.getStringCursor();
        }while (!StringUtils.equals("0",cursor));

        long end = System.currentTimeMillis();
        System.out.println(new Double(end-start)/1000d);
    }

key的遍历,常用于key值匹配

场景1:查找key值是否存在,可以使用:expire key,返回-2,则表示key值不存在。

场景2:查找redis中已经存储的key1的一段,由于其他原因,使用key1中的一段的“正则匹配”。

解决方案:

1. 使用:keys *

2. 使用:scan cursor [match pattern] [count count]

“生产环境不要用keys命令和smembers命令 尝试使用scan和sscan替换它”

原因:

1、redis是单线程的,其所有操作都是原子的,不会因并发产生数据异常;

2、使用高耗时的Redis命令是很危险的,会占用唯一的一个线程的大量处理时间,导致所有的请求都被拖慢。(例如时间复杂度为O(N)的KEYS命令,严格禁止在生产环境中使用);

  • 运维人员进行keys *操作,该操作比较耗时,又因为redis是单线程的,所以redis被锁住;
  • 此时QPS比较高,又来了几万个对redis的读写请求,因为redis被锁住,所以全部Hang在那;
  • 因为太多线程Hang在那,CPU严重飙升,造成redis所在的服务器宕机;
  • 所有的线程在redis那取不到数据,一瞬间全去数据库取数据,数据库就宕机了;

"redis禁用危险命令"

1、打开redis配置文件
vim redis.conf
2、找到##SECURITY##区域,按照Example配置rename_command
:/rename_command
#n下一个,N上一个
3、禁用命令
rename-command KEYS     ""
rename-command FLUSHALL ""
rename-command FLUSHDB  ""
rename-command CONFIG   ""

后期补充:

对于场景2中redis中key1模糊匹配key2的情况解决方案:可以在key1或者key2设置的时候,再使用一个缓存来绑定二者关系。

你可能感兴趣的:(redis总结,java)