版权声明:非商业目的可自由转载,转载请标明出处 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命令的具体执行过程如下: