Redis单线程
众所周知,Redis执行任务为单线程,简化了编程模型,使用者也不用担心并发读写导致的可能的错误。
为什么
一般为了解决高吞吐、多并发的设计任务,都会基于多线程(Java中的线程池等方式),而Redis底层采用epoll方式对io进行复用,且Redis中操作主要为内存操作,不需要等待IO等因素(这些因素也是引入多线程的原因,等待IO、数据库等操作),也能避免多线程上下文切换带来的性能损耗。
其中Redis的一些耗时操作:
- 文件句柄关闭
- AOF持久化任务
- 内存释放等操作
这些操作,会从Redis主线程中pork出子进程(异步化组件)来执行这些耗时操作,不会因这些操作阻塞主线程的执行。
单线程会让CPU成为可能的瓶颈;然而一般情况下,Redis的任务更多是因为网络io。即使单线程,无法利用多CPU的优势,也可以单机部署多个Redis实例,充分利用多CPU资源。
注意点
因为Redis为单线程模式,如果一个任务执行时间过程、引起阻塞,极其影响性能,一般耗时操作(也是需要尽量避免的操作)如下:
- 不合适使用API,一个比较大的map,hgetall操作,O(n)的复杂度和对网络io带来的影响都是巨大的;
- CPU饱和,Redis会对单CPU造成压力,当CPU利用率到达100%时,需要分析什么原因导致的,是否操作不合理等;如果真是因为QPS过高,考虑水平分割
- 持久化相关
- CPU竞争,避免和其他CPU密集相关进程部署在同一机器,设计足够量内存,且需要控制器内存无限制增长
- 内存交换,Redis的高速存取是基于数据在内存之中,当交换到硬盘上后,会极其影响性能
- 网络问题