Redis单线程与慢查询

版权声明:非商业目的可自由转载,转载请标明出处 https://blog.csdn.net/u010013573/article/details/87933212

单线程

  • 对于每个Redis实例,在内部是使用单线程来处理所有命令请求的,即所有命令在该线程中排队执行。同时需要注意的是单个Redis实例的16个数据库的操作也都是共享这个单线程的,所以在设计时,如果16个数据库或者多个都要存放数据并且读写较频繁,则推荐采用独立的Redis实例来保存各个数据库的数据,即使用不同的端口来启动多个Redis实例,每个使用0号数据库。

单线程的实现基础

  • Redis实例作为一个服务器可以处理很多的Redis客户端的连接和请求,采用单线程来实现连接管理和请求处理主要是基于IO多路复用技术来实现的。
  • IO多路复用在Linux中是基于Linux提供的selector或epoll机制来实现的。将连接注册到内核中,内核监听这些连接是否存在IO事件过来,如果存在,则通知应用线程来处理这些IO事件。

使用单线程的原因

  • Redis的所有数据都是保存在内存中,相当于Java中的HashMap,故操作速度非常快,所以单线程不会影响性能。同时使用单线程可以避免了线程上下文切换,因为线程上下文切换涉及到内核用户态和内核态的切换,会影响应用程序性能,所以单线程也进一步提高了性能。其次使用单线程由于所有操作都在该线程执行,则避免了多线程中加锁来进行线程同步的问题,保证了线程安全性。

使用单线程存在的问题

  • 由于所有操作都在同一个线程中排队执行,所以如果某个操作需要较长时间,则会阻塞后面排队的操作的执行,如使用keys命令会阻塞其他命令的执行,导致整体Redis实例停顿。同时如果某个key对应的value太大,则Redis在读取该key并传输也会耗时较多,也会阻塞后续命令的执行。所以在程序设计中,对于keys命令的使用,需要评估需要返回的key列表的大小,如果太大,则可以考虑使用2.8及以后版本提供的scan命令来替代。对应key和value设计,要充分考虑Redis各个数据结构的特性,如字典hash在存放不同数量数据时使用不同数据结构的特性,避免将一个比较大的结构化数据直接序列化成String保存,而是需要考虑拆分,否则相应的get/set命令会耗时较长,阻塞其他操作。总之,Redis的单线程是基于每个操作对于内存的操作都是非常快速的前提下的,如果某个操作很耗时,则会导致整个Redis实例的阻塞,影响整体的吞吐量。所以在设计中,也可以考虑使用主从结构来实现读写分离的方式来将读写流量分流。

慢查询

  • 我们可以通过使用redis-cli登录控制台,然后使用slowlog get命令来获取最近的慢操作日志,默认返回10条,也可以在get后指定需要多少条:

    127.0.0.1:6379> slowlog get
     1) 1) (integer) 5468639 # 慢日志序号
        2) (integer) 1551157362 #执行时间戳
        3) (integer) 126291 # 执行微妙
        4) 1) "SCAN"  # 命令详情
           2) "0"
           3) "count"
           4) "50000"
           5) "match"
           6) "user_p:*"
     2) 1) (integer) 5468638
        2) (integer) 1551157362
        3) (integer) 111871
        4) 1) "SCAN"
           2) "0"
           3) "count"
           4) "50000"
           5) "match"
           6) "usr_p:*"
     3) 1) (integer) 5468637
        2) (integer) 1551157361
        3) (integer) 12972
        4) 1) "KEYS"
           2) "stat:*"
    
  • Redis默认为保留最近的128条慢日志,如果需要更多,可以通过在控制台或者redis.conf配置文件中设置保留最近多少条的慢日志,同时可以配置超过多少毫秒的才作为慢日志。

  • 在redis-cli控制台配置:这个下次重启会丢失,即重新使用redis.conf的。

    config set slowlog-log-slower-than 100   (单位ms)
    config set slowlog-max-len 1024    日志最多存个数
    
  • 在redis.conf配置:

    # The following time is expressed in microseconds, so 1000000 is equivalent
    # to one second. Note that a negative number disables the slow log, while
    # a value of zero forces the logging of every command.
    slowlog-log-slower-than 1000
    
    # There is no limit to this length. Just be aware that it will consume memory.
    # You can reclaim memory used by the slow log with SLOWLOG RESET.
    slowlog-max-len 1024
    
  • Redis慢日志记录的是Redis线程执行这条命令所用的时间,并不包括命令排队和结果数据的传输时间。所以如果慢命令的实际执行时间一般是大于慢日志记录的时间的,即应用程序实际等待的时间要大于这个慢日志记录的时间。Redis命令的具体执行过程如下:
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/u010013573/article/details/87933212