常见面试问题
- 简单聊一下redis
- 为什么要使用缓存(redis),使用redis的好处?
- redis 和 memcached 的区别?
- 为什么redis这么快?
- 讲讲redis的单线程模型?
redis简介
Redis 是 C 语言开发的一个开源的(遵从BSD协议)高性能键值对(key-value)的内存数据库,可以用作数据库、缓存、消息中间件等。为了减少对数据库的读写io压力,缓存技术孕育而生,当前主流的缓存技术主要是redis和memcached,memcached比较简单,这里我们主要讲解redis,简单来说redis就是一个数据库,不过与传统数据库不同的是redis的数据是存在内存中的,所以存写速度非常快,因此 redis 被广泛应用于缓存方向,这里我们可以看一下下面的图。

这里简单说一下上图的熔断,其实就是当存储层无法提供服务时,让请求直接打到缓存上直接返回。
redis 和 memcached 的区别
memcached
- 支持简单数据类型
- 不支持数据持久化存储
- 不支持主从同步
- 不支持分片
redis
- 数据类型丰富
- 支持数据持久化存储
- 支持主从同步
- 支持分片
redis有多快
redis为什么这么快呢?redis的官方描述,经过测试它能支持100000qps(每秒查询数),它是完全基于内存,却大部分请求都是纯内存操作,执行效率高,采用单进程单线程模型的key-value数据库,由c语言编写,数据都是存储在内存中,读写数据都不会受io和磁盘的限制,这里我们可以看下图,纵轴是qps,横轴是连接数 。

redis为什么这么快
redis之所以这么快,主要有以下几点:
- ①完全基于内存,绝大部分请求都是纯内存操作,执行效率高,完全基于内存,绝大部分请求都是纯内存操作,执行效率高。
- ②数据结构简单,操作数据也简单。
- ③采用单线程,也能处理高并发请求,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
- ④使用多路i/o复用模型,非阻塞i/o。
- ⑤使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM机制。
redis的单线程模型
redis是基于reactor模式开发了自己的网络事件处理器,这个事件处理器被称为文件事件处理器,因为它是单线程的,所以称之为redis的单线程模型,文件事件处理器包括4个部分,多个socket、io多路复用程序、文件事件分派器、事件处理器,事件处理器又包括连接应答处理器、命令请求处理器、命令回复处理器。

redis单线程模型的大致工作流程有这几个步骤:
- ①首先在redis启动初始化的时候,redis会先将事件处理器中的连接应答处理器和AE_READABLE事件关联起来;
- ①如果客户端向redis发起连接,会产生AE_READABLE事件(步骤A),产生该事件后会被IO多路复用程序监听到(步骤B),然后IO多路复用程序会把监听到的socket信息放入到队列中(步骤C),事件分配器每次从队列中取出一个socket(步骤D),然后事件分派器把socket给对应的事件处理器(步骤E)。由于连接应答处理器和AE_READABLE事件在redis初始化的时候已经关联起来,所以由连接应答处理器来处理跟客户端建立连接,然后通过ServerSocket创建一个与客户端一对一对应的socket,如叫socket01,同时将这个socket01的AE_READABLE事件和命令请求处理器关联起来。

- ③当客户端向redis发生请求时(读、写操作),首先就会在对应的socket如socket01上会产生AE_READABLE事件(步骤A),产生该事件后会被IO多路复用程序监听到(步骤B),然后IO多路复用程序会把监听到的socket信息放入到队列中(步骤C),事件分配器每次从队列中取出一个socket(步骤D),然后事件分派器把socket给对应的事件处理器(步骤E)。由于命令处理器和socket01的AE_READABLE事件关联起来了,然后对应的命令请求处理器来处理。这个命令请求处理器会从事件分配器传递过来的socket01上读取相关的数据,如何执行相应的读写处理。操作执行完之后,redis就会将准备好相应的响应数据(如你在redis客户端输入 set a 123回车时会看到响应ok),并将socket01的AE_WRITABLE事件和命令回复处理器关联起来。

- ④当客户端会查询redis是否完成相应的操作,就会在socket01上产生一个AE_WRITABLE事件,会由对应的命令回复处理器来处理,就是将准备好的相应数据写入socket01(由于socket连接是双向的),返回给客户端,如读操作,客户端会显示ok。

- ⑤如果命令回复处理器执行完成后,就会删除这个socket01的AE_WRITABLE事件和命令回复处理器的关联。
- ⑥这样客户端就和redis进行了一次通信。由于连接应答处理器执行一次就够了,如果客户端在次进行操作就会由命令请求处理器来处理,反复执行。