一.Redis可以存储的数据类型?
基础的五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set)
有序集合zset更类似于map集合,以数据为key,以分数为值从小到大排序
Redis的String是二进制安全的,能够进行序列化和反序列化,但最大文件不能超过512M
Redis使用的是乐观锁
Redis只有安装在linux上才能发挥自己的极致性能,因为Redis需要linux的epoll函数
二.Redis和Memcached的区别?
Memcached只支持String类型,Redis支持5种数据类型
Memcached一般不持久化,Redis支持两种持久化方式
Memcached使用的是多线程+锁,Reids使用的是单线程+多路IO复用
三.Redis的持久化有几种方式?各自的优缺点?
两种,RDB和AOF
- RDB是在满足一定条件后进行快照的存储(保存的是数据),节省磁盘空间,恢复速度快;
- AOF保存的是操作,占的空间较大,但可以更改存储文件,而且丢失数据概率更小
- RDB进行存储有两种命令:save和bgsave
区别:save需要手动调用,是利用主线程进行保存操作,保存期间Redis的功能失效,而bgsave是自动调用,是利用主线程fork出一个子线程保存,期间Redis的功能正常
四.和MySQL读写一致性的问题
-
使用延时双删
更新的时候先删除缓存,再进行数据库的更新
但是这样还是有可能在更新之前有线程来查询数据,导致数据不一致
所以,就在更新完数据库之后删除一次缓存,即双删 -
串行化
五.Redis的单线程工作过程
Redis的单线程主要是指Redis的网络IO和键值对读写是由一个线程完成的
即Redis在处理请求时(包括获取,解析,执行,内容返回)等,都是由一个顺序串行的主线程执行的
比如:set的时候socket中有数据,Redis会先通过调用将数据从内核态空间拷贝到核心态空间,再交给Redis调用,但是拷贝过程是阻塞的,所以key太大会有问题。
六.Redis的单线程演变过程
- Redis3.X采用单线程
①数据结构简单
②避免锁开销和线程上下文切换
③可以有很高的Qps - 为什么单线程快
①基于内存操作:Redis 的所有数据都存在内存中,因此所有的运算都是内存级别的;
②数据结构简单:Redis 的数据结构是专门设计的,而这些简单的数据结构的查找和操作的时间大部分复杂度都是 O(1)
③多路复用和非阻塞 I/O(NIO):Redis使用 I/O多路复用功能来监听多个 socket连接客户端,这样就可以使用一个线程连接来处理多个请求,减少线程切换带来的开销,同时也避免了 I/O 阻塞操作
④避免上下文切换:因为是单线程模型,因此就避免了不必要的上下文切换和多线程竞争,这就省去了多线程切换带来的时间和性能上的消耗,而且单线程不会导致死锁问题的发生 - 单线程的问题
正常情况下Redis的del命令可以很快删除数据,而当被删除的数据的key是一个非常大的对象时,del指令就会造成Redis主线程卡顿,即大key的删除问题
为了避免Redis的阻塞,所以Redis提出了惰性删除,引入了多线程 - Redis4.X开始引入多线程
负责客户端请求的仍未单线程,但是引入了多线程异步删除
即删除不用del key,而是引入unlink key等异步删除命令,将删除工作交给小弟(其他线程)异步删除 - Redis6.X告别了单线程,用一种全新的多线程
工作线程仍为单线程。但是Redis的其他功能,如:RDB持久化,异步删除等由额外的线程执行,即将socket的读写也交给多线程。
所以对于整个Redis来说是多线程的。
注:Redis默认没有开启多线程,需要更改配置文件开启
七.Redis的IO多路复用
因为Redis的操作是基于内存的,性能的瓶颈是在内存和网络IO带宽上,而不是CPU上,因此工作线程不需要多线程
- IO多路复用,简单来说就是通过监测文件的读写事件再通知线程执行相关操作,保证Redis的非阻塞IO能够顺利执行完成的机制。多路IO复用能让单线程高效的处理多个连接请求
- 多路:指多个socket连接
- 复用:指复用同一个线程,多路复用主要有三种技术:select,poll,epoll
八.Redis的IO多路复用工作过程
即将原本主线程最耗时的socket读写任务交给多线程执行,这样多个socket的读写就可以并行执行了,将网络IO操作多线程化,而执行操作仍交给单线程处理