admin管理员组文章数量:1794759
Redis的面试题
1.为什么使用Redis做缓存
redis具有高性能和高并发的特点
redis为什么具有高性能,或者说redis为什么快?
1.首先redis的数据存在内存中,所以比存储磁盘上的数据库快。 2.其次redis本身使用了高效的数据结构redis内部的基本数据类型有String , List, Set, Hash, Sorted Set
底层的数据结构:
键的数据结构
(Note:存整数时以long来存储)
String-简单动态字符串(Simple Dynamic String,SDS)
1.一个数组存储实际数据buf
2.数组占用长度alloc
3.实际使用长度len
值的数据结构
String - 简单动态字符串
List - 双向链表/压缩列表
Set - 整数数组/哈希表
Hash - 哈希表/压缩列表
SortedSet - 跳表/压缩列表
压缩列表是紧凑的数据结构,占用内存小的同时在数据量不大时访问速度也不慢。
跳表是利用了二分查找的思想,对链表建立了多级索引
键值对的组织结构:
redis维护了两个交替使用的全局hash表,由key指向value的指针。
冲突过多时进行渐进式rehash。
每处理一个请求将该索引位置的所有数据移到新表中。
3.Redis的单线程模式和网络框架redis采用网络IO多路复用机制,在网络IO操作中能并发的处理大量的请求。
Redis的核心网络模型是单线程的单reactor模型,利用Linux系统提供的epoll/select的IO多路复用技术,在单线程的事件循环中不断处理事件,回写响应数据到客户端。
IO模型是什么?有哪些IO模型?
(152条消) linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO_xiaohuima_dong的专栏-CSDN博客blog.csdn/xiaohuima_dong/article/details/45096865?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164629562316781683974719%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164629562316781683974719&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-14-45096865.pc_search_insert_es_download&utm_term=epoll%2Fselect&spm=1018.2226.3001.4187
在linux系统下, 根据IO操作是否被阻塞以及同步异步问题进行分类,可以得到5种IO模型。
1.阻塞I/O模型
2.非阻塞I/O模型
3.I/O复用模型
linux提供了select/poll/epoll 三个系统调用接口,可以将多个fd的集合传入,因此可以同时监控多个socket是否就绪。把多个IO的阻塞复用到一个select之类的阻塞上,从而使得系统在单线程的情况下同时支持处理多个请求。
区别:
select:
(1)数量有限,最多支持1024个fd。
(2) 只知道有事件,不知道在哪个IO流发生的事件,所以对返回的fd集合进行遍历
poll: 和select类似,但是没有数量的限制,fd列表由一个数组表示
epoll:
epoll_create 创建一个epoll的描述符
epoll_ctl 对监听的事件进行注册。 为fd注册回调函数,当可读可写时,发生中断,内核调用该Socket的callback函数,把该fd加入到就绪的事件链表。
epoll_wait 从内核得到事件的链表。
epoll是触发式的,没有以上的缺点。
4.信号驱动异步I/O模型
5.异步I/O模型
redis的IO多路复用提供了一定程度上的高并发的能力。
还可以通过主从复制实现读写分离提供更高程度的并发能力。
Redis的过期删除惰性删除:客户端访问某个key的时候,如果过期了则删除
定期删除:定期执行扫描,选择随机20个key,如果过期的比例超过25%则重复操作。
Redis的淘汰策略noeviction 对可能导致内存增大的返回错误
volatile/allkeys - lru/random
volatile-ttl 选择剩余存活时间最短的
Redis的lru是近似lru。随机采样5个key,淘汰最老的。
Redis的持久化机制redis的持久化机制主要有RDB快照和AOF(Append-Only-File)日志
AOF日志在写命令执行完后会在磁盘记录。记录日志的频率由appendfsync配置。
Always 每次写后记录到磁盘。
Everysec 写后记录在内存缓冲区,每秒更新到磁盘
No 写后记录在缓冲区,由操作系统决定何时写到磁盘。
AOF文件过大会进行重写。
RDB快照
记录内存快照到磁盘中。使用CopyOnWrite的方式复制。
调用bgsave(), 调用fork(), 父子进程共享物理地址,发生写的时候会copy对应的page, 父子各一份。
可以执行全量快照和增量快照,也可以和全量快照和AOF文件结合使用。
周期性持久化数据仍然会丢失:解决方案-Gemfire
缓存雪崩、缓存穿透、缓存击穿缓存雪崩:大量数据集中在某一时间失效,大量访问数据库。
(1)给key设置一个失效时间的随机波动值。
(2)多级缓存(本地缓存)
(3)热点数据永不过期
缓存穿透:key对应的数据在数据库中不存在,没有缓存值,在缓存中查询不到会到数据库中查。
(1)boolean过滤器,所有可能存在的数据hash到一个bitmap上,如果不存在会被拦截。
(2)空值也缓存到缓存里
缓存击穿:某个数据失效的一瞬间,大量数据访问数据库
(1)对数据的访问加互斥锁,当一个线程访问该数据时,其他缓存不能访问。
(2)热点数据永不过期
并发竞争key问题多个线程的多个读写操作是非原子性的,所以会出现竞争问题。
多个线程修改同一个key。
解决方案:
1.乐观锁:
watch命令会监控某一个key,如果key被其他线程修改过则事务会回滚。(数据分片情况下不适用)
2.分布式锁
3.时间戳
4.在客户端加锁
缓存和数据库双写时的数据一致性使用Cache Aside模式, 缓存更新时先更新数据库,然后再让缓存失效,为缓存设置过期时间。
Redis的主从同步为什么要做主从同步?
同一份数据具有多个备份,提供高可靠性。主从库实现读写分类,提供更高的并发能力
主从同步的机制:
第一次数据同步进行全量复制:
第一步:从库向主库发出同步请求,双方协商
第二步:主库将调用bgsave()创建子进程生成RDB文件,传给从库,从库加载rdb文件
第三步:主库的replication buffer储存了RDB文件后的写操作,传给从库,从库执行这些写操作。
数据同步的维护:
基于长连接的命令传播
网络断开后的恢复
有一个环形缓冲区,主库指向写到的位置,从库指向读到的位置。断网后进行增量复制。
只能实现最终一致性,如果需要强一致性的话,可以用gemfire。
Redis的哨兵机制redis的哨兵也是redis实例,具有三个功能
监控,选主,通知。
监控通过发送命令是否响应判断服务器工作状态。
(主观下线和客观下线)
主库客观下线要进行选主,执行主从切换
选主
选主操作的执行者称为leader, leader通过投票选举产生。
通知
通知从库与新主库建立连接。
通过发布订阅模式通知客户端与新主库建立连接
Redis的集群数据过大,单机存储困难。运行速度慢(RDB生成时进行fork(),占用内存越大越慢)
将数据划分为多份,每份用一个redis实例来储存
Redis Cluter 方案 将所有的key映射到一个固定数量的hash槽中,将这些槽在数据库实例中进行分配。可以手动或自动分配。
客户端会存储哈希槽和实例的对应关系,查找数据时先计算哈希槽,再去对应实例中取。
Redis事务Redis是单线程的数据库,能够单线程运行得益于
1. 数据储存在内存中,读取和修改很快(没有IO)
2.Transaction很短,修改和读取的数据少
所以Redis的事务不支持交互式的事务,而是以Stored Procedure的形式运行事务。用户将预先写好的事务代码提交,Redis以脚本的方式运行,但不额外提供事务的atomicity。
Redis 通过 MULTI、EXEC、WATCH 等命令来实现事务(transaction)功能。
如果要执行真正的事务,可以通过LUA脚本执行。Lua脚本具有原子性。
Lua脚本和Redis的事务一样,都是完全在Server端运行,不需要IO,具有局部性执行快。
版权声明:本文标题:Redis的面试题 内容由林淑君副主任自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.xiehuijuan.com/baike/1686561297a82070.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论