《redis学习》之高级功能

2019-04-18  本文已影响0人  夏天嘚花花

redis慢查询日志

慢查询日志就是系统在命令执行前后计算每条命令的执行时间,当超过预设阈值,就将这条命令的相关信息(例如:发生时间、耗时、命令的详细信息)记录下来。
慢查询记录的是执行命令的时间,不包括这个命令排队的时间,客户端发送请求的等待时间,返回数据的时间

设置慢查询

slowlog-log-slower-than : 用来设置超过时间的阈值,默认是10000,单位是微秒
slowlog-log-slower-than=0,那么系统会记录所有的命令;如果slowlog-log-slower-than<0,那么对任何命令都不会记录

127.0.0.1:6379> config set slowlog-log-slower-than 10000
OK
127.0.0.1:6379> config get slowlog-log-slower-than
1) "slowlog-log-slower-than"
2) "10000"

slowlog-max-len : 慢查询日志最多存储多少条,记录超过了旧删除最前面的数据

127.0.0.1:6379> config set slowlog-max-len 200
OK
127.0.0.1:6379> config get slowlog-max-len
1) "slowlog-max-len"
2) "200"
127.0.0.1:6379> config rewrite #重置设置
获取慢查询日志

命令slowlog get [n] 获取慢查询日志,n表示获取前面几条
先用redis自带的性能测试工具生成10万条数据,然后执行keys * 命令,由于生成了10万条数据,keys * 会执行很长时间

./redis-benchmark -r 100000 -n 100000 -q
127.0.0.1:6379> keys *
127.0.0.1:6379> slowlog get 2
1) 1) (integer) 86 [命令id]
   2) (integer) 1554139864 [执行命令的时间戳]
   3) (integer) 231982 [命令耗时]
   4) 1) "keys"
      2) "*"
   5) "127.0.0.1:43925"
   6) ""
2) 1) (integer) 85
   2) (integer) 1554137629
   3) (integer) 10714
   4) 1) "LRANGE"
      2) "mylist"
      3) "0"
      4) "599"
   5) "127.0.0.1:47661"
   6) ""
127.0.0.1:6379> slowlog reset #重置慢查询日志

redis管道pipeline

Pipeline指的是管道技术,指的是客户端允许将多个请求依次发给服务器,过程中而不需要等待请求的回复,在最后再一并读取结果即可。
例如每次执行一次redis命令发起请求然后返回结果,这样每次都需要建立连接,对于批量的命令执行会花费大量时间,管道命令支持客户端允许将多个请求一次发给服务器,过程中不需要等待请求的回复,最后一并读取结果,只需要一次IO

image.png
image.png
深入源码(普通jedis命令)

Redis客户端与Redis之间使用TCP协议进行连接,一个客户端可以通过一个socket连接发起多个请求命令。每个请求命令发出后client通常会阻塞并等待redis服务处理,redis处理完后请求命令后会将结果通过响应报文返回给client,因此当执行多条命令的时候都需要等待上一条命令执行完毕才能执行。

深入查看jedis的get方法
JedisConnectionFactory factory = (JedisConnectionFactory)applicationContext.getBean("jedisConnectionFactory");
Jedis jedis = factory.getConnection().getNativeConnection();
String value = jedis.get("key");

进入get方法内部,每次执行一次命令后都会flush,这样就将数据发送给redis-server并等待数据返回


image.png
image.png
image.png
深入源码(管道)
        Jedis jedis = factory.getConnection().getNativeConnection();
        Pipeline pipeline = jedis.pipelined();
        for (int i = 0; i < 10; i++) {
            pipeline.set("key_" + i, UUID.randomUUID().toString());
        }
        pipeline.sync();
        jedis.close();

管道的方式先将所有的cmd与参数都写入了outputstream,但还没有传到redis客户端,Pipeline对象sync方法里面执行了flush将请求发给redis-server

image.png
image.png
image.png
pipeline通过减少客户端与redis的通信次数来实现降低延时时间,而且Pipeline 实现的原理是队列,而队列的原理是时先进先出,这样就保证数据的顺序性。pipeline会将命令返回的数据缓存到内存,所以如果命令越多返回的数据也会越多,这样会消耗内存,所以也不是将所有的操作都放到管道会最好
pipeline使用
public void test00(){
        JedisConnectionFactory factory = (JedisConnectionFactory)applicationContext.getBean("jedisConnectionFactory");
        Jedis jedis = factory.getConnection().getNativeConnection();
        Pipeline pipeline = jedis.pipelined();
        for (int i = 0; i < 10; i++) {
            pipeline.set("key_" + i, UUID.randomUUID().toString());
        }
        //pipeline.sync(); 提交命令
        List<Object> objectList = pipeline.syncAndReturnAll(); //提交命令并获取返回值
        System.out.println(objectList);
        jedis.close();
    }

redis的过期策略和内存淘汰机制

过期策略

redis采用的是定期删除 + 惰性删除策略

定期删除

Redis默认每个100ms检查是否有过期的key,有过期的key则删除。这个检查删除不是说说所有的key全部检查过去,而是随机抽取检查。因此,如果只采用定期删除策略,会导致很多Key到时间没有删除。

惰性删除

由于定期删除的缺陷会导致部分key不能在规定时间内删除,惰性删除就派上用场了,所谓的惰性删除就是在你获取某个key的时候,redis会检查一下是否过期,如果过期了就会删除

定期删除+惰性删除是否就没有其他问题了?

不是的,如果定期删除没删除Key。然后你也没及时去请求Key,也就是说惰性删除也没生效。这样,Redis的内存会越来越高,这时候必须采用内存淘汰机制

内存淘汰机制
# maxmemory-policy volatile-lru
Noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。应该没人使用吧;
Allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的Key。推荐使用,目前项目在用这种;
Allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key,应该也没人使用吧;
Volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的Key。这种情况一般是把Redis既当缓存又做持久化存储的时候才用。不推荐;
Volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个Key。依然不推荐;
Volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的Key优先移除。不推荐。
上一篇下一篇

猜你喜欢

热点阅读