1. Redis是用来干嘛的?

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs, geospatial indexes with radius queries and streams. Redis has built-in replication, Lua scripting, LRU eviction, transactions and different levels of on-disk persistence, and provides high availability via Redis Sentinel and automatic partitioning with Redis Cluster.

通过上面redis官网的说明可以看出,redis是一个可以对内存数据结构进行存储的东西,它可以用作数据库、缓存和消息代理。它支持数据结构,如字符串,散列,列表,集合,带有范围查询的排序集,位图,超级日志,具有半径查询和流的地理空间索引。Redis具有内置复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentinel提供高可用性并使用Redis Cluster自动分区。
在项目中主要用来用作数据的缓存,将数据缓存在redis中,减轻对底层数据库的访问压力,获得更高的并发和更快的请求响应速度。


2. 在项目中如何使用?

我们知道,项目中的数据一般情况下都是存在于数据库当中的,而且数据库的并发性能不是特别高,如果同时接收到大量的请求,数据库可能就会崩掉,而且sql查询会消耗一定的时间,增加请求的响应时间,所以不用缓存会出现系统无法支撑大量的并发情况,请求响应时间会变长等问题。
如果我们在第一次访问某个数据的时候,比如根据一个订单id获取订单的详细信息,将这条数据再返回的时候,也放到缓存里面去,那么下次就可以直接在缓存里面返回数据,不必去查询数据库,这样就可以减轻数据库的访问压力,而且缓存在内存中,势必要比直接访问数据库的速度要快很多,这样也就减小了请求的响应时间,redis在项目中就主要使用来解决数据的缓存问题。


3. 为啥要使用缓存?

使用缓存的目的主要有两个:
(1)高性能
比如说有一个很复杂的sql数据查询,这个查询要耗费大量的时间,如果每次都直接取数据查询,那必然会对请求响应时间造成很大的影响,如果能在第一次查询完毕之后,将其直接保存在缓存当中,下次查询的时候,直接在缓存中拿走现成的数据,这样就会大大缩短请求的响应时间。

(2)高并发
我们知道数据库能承受的并发是有限的,那么在流量高峰期(比如,抢购、打折、秒杀等等),会有大量的请求进入我们的系统,比如查询某个商品的详情,如果我们没有缓冲,那么给次查询都要走数据库,假如我们的数据库每秒只能接受2000个请求,结果一秒钟进来了5000个请求,那么数据库就直接崩掉了,毫无高并发可言,而如果我们中间具有缓存服务,那么在第一个用户查询商品详情时(或者提前将放好)我们可以直接将商品的详情信息数据放到缓存里面,这样在后续用户查询时就可以直接走缓存,不走数据库,缓存是基于内存的,它的访问速度快,并发高;因此就可以提供一个高并发的支持。


4.用了缓存会出现什么问题?

主要常见的有下面三个问题
1)缓存与数据库双写不一致
2)缓存雪崩
3)缓存穿透
4)缓存并发竞争

             

5. memcached和Redis有什么区别?

(1)Redis支持服务器端的数据操作
redis和memcached相比,redis拥有更多的 数据结构并且支持更丰富的数据操作 ,通常在memcached里面,你需要将数据拿到客户端来进行类型的修改然后在set回去,这样就严重增加了网络IO的次数和数据体积。在redis里面,这些操作可以在服务端完成,所以这些复杂的操作就和一般的GET/SET一样高效。所以,如果需要缓存能支持更复杂的结构和操作,那么redis是不错的选择 。
(2)内存使用率
如果使用简单的 key-value 存储的话,Memcached的内存利用率会更高,而如果Redis采用 hash 结构来做 key-value 存储,由于其组合式的压缩,其内存利用率会高于Memcached。
(3)性能
由于redis只使用单核,而Memcached可以使用多核,所以平均每一个核上redis在存储小数据时比Memcached性能更好。而在100K以上的数据中,Memcached性能要高于redis。
(4)集群模式
memcached没有原生的集群模式,需要依靠客户端来实现集群中分片写入数据;redis原生支持cluster模式,官方支持redis cluster集群模式。


对比点 memcached redis
是否支持服务端操作 不支持 支持
数据结构类型 简单 复杂多样
内存使用率 简单 key-value 存储,利用率高 采用hash结构存储,内存利用率高
性能 存储大数据性能高 存储小数据性能高
集群模式 没有原生支持 原生支持cluster模式


6. Redis的线程模式?

要了解redis的线程模式,必须先了解下面几个概念
(1)文件事件处理器
①redis是基于reactor模式开发了网络事件处理器,这个处理器叫做 文件事件处理器(file event Handler)。这个文件事件处理器是单线程的,所以redis才叫做单线程模式,采用IO多路复用机制去同时监听多个socket,根据socket上的时间来选择对应的事件处理器来处理这个事件。

②如果被监听的socket准备好执行accept、read、write、close等操作的时候,跟操作对应的文件事件就会产生,这个时候文件处理器就会调用之前关联好的的事件处理器来处理这个事件。

③文件事件处理器是单线程模式运行的,但是通过IO多路复用机制监听多个socket,可以实现高性能的网络通信模型,又可以跟内部其他单线程的模块进行对接,保证了redis内部的线程模型的简单性。

④文件事件处理器的结构包含四个部分:多个socket、IO多路复用程序、文件事件分派器、事件处理器(命令请求处理器、命令回复处理器、连接应答处理器,等等)。

⑤多个socket可能并发的产生不同的操作,每个操作对应不同的文件 事件,但是IO多路复用程序会监听多个socket,但是会将socket放到一个队列中去处理,每次从队列中取出一个socket给事件分派器,事件分派器把socket给对应的事件处理器。

⑥然后一个socket的事件处理完了之后,IO多路复用程序才会将队列中的下一个socket给事件分派器。事件分派器会根据每个socket当前产生的事件,来选择对应的事件处理器来处理。

(2)文件事件
①当socket变得可读时(比如客户端对redis执行write操作,或者close操作),或者有新的可以应答的socket出现时(客户端redis执行connect操作),socket就会产生一个AE_READABLE事件。

②当socket变得可写的时候(客户端对redis执行read操作),socket就会产生一个AE_WRITABLE事件。

③IO多路复用程序可以同时监听AE_READABLE和AE_WRITABLE两种事件,要是一个socket同时差生了这两种事件,那么文件分配器优先处理AE_READABLE事件,然后才是AE_WRITABLE事件。

(3)文件事件处理器
如果是客户端要连接redis,那么会为socket关联连接应答处理器。
如果是客户端要写数据到redis,那么会为socket关联命令请求处理器。
如果是客户端要从redis读数据,那么会为socket关联命令回复处理器。


关于Redis的几件小事 | 使用目的与问题及线程模型_Redis

redis内存模式简单示意图


(4)客户端与redis通信的一次流程
①在redis启动初始化的时候,redis会将连接应答处理器跟AE_READABLE事件关联起来,接着如果一个客户端跟redis发起连接,此时redis会产生一个AE_READABLE事件,然后由连接应答处理器来处理跟客户端建立连接,创建客户端响应的socket,同时将这个socket的AE_READABLE事件跟命令请求处理器关联起来。

②当客户端向redis发起请求的时候(不管是读请求还是写请求,都一样),首先就会在socket产生一个AE_READABLE事件,然后由对应的命令请求处理器来处理。这个命令请求处理器就会从socket中读取请求的相关数据,然后执行操作和处理。

③接着redis这边准备好了给客户端的响应数据之后,就会将socket的AE_WRITABLE事件跟命令回复处理器关联起来,当客户端这边准备好读取相应数据时,就会在socket上产生一个AE_WRITABLE事件,会由相应的命令回复处理器来处理,就是将准备好的响应数据写入socket,供客户端读取。

④命令回复处理器写完之后,就会删除这个socket的AE_WRITABLE事件和命令回复处理器的关联关系。


关于Redis的几件小事 | 使用目的与问题及线程模型_Redis_02

一次通信过程


7. 为什么单线程redis还可以支撑高并发?

(1)纯内存操作。
(2)核心是基于非阻塞的IO多路复用机制
(3)单线程避免了多线程上下文切换的开销。


— THE END —

关于Redis的几件小事 | 使用目的与问题及线程模型_大数据技术_03


推荐阅读

《关于MQ面试的几件小事 | 消息队列的用途、优缺点、技术选型》       

《关于MQ面试的几件小事 | 如何保证消息队列高可用和幂等》

《关于MQ面试的几件小事 | 如何保证消息不丢失》

《关于MQ面试的几件小事 | 如何保证消息按顺序执行》

《关于MQ面试的几件小事 | 消息积压在消息队列里怎么办》