Redis:
Redis缓存那点破事|绝杀面试官 25 问! baijiahao.baidu.com/s?id=171101…
****
Redis 深度历险-核心原理与应用实践
\
1.五种基本数据结构
String
使用场景: ****缓存,计数,分布式锁,共享session, 限速
底层实现:SDS 动态字符串 ,一个字符串类型的值能存储最大容量是多少?512M
List列表
使用场景:消息队列 , 栈 , 文章列表
底层实现:当ziplist不能满足要求时,会使用linkedlist。
Hash哈希
使用场景:用户表结构
底层实现:ziplist(压缩列表),hashtable(字典)
Set 集合
使用场景:用户标签 , 抽奖功能,去重、赞、踩、共同好友
底层实现:当intset(整数集合)不能满足要求时,会使用hashtable(字典)
ZSet有序集合
使用场景:排行榜 , 延迟消息队列
底层实现: 当不满足ziplist的要求时,会使用skiplist
\
2.三种特殊的数据类型:Bitmap位图、HyperLogLog、Geospatial,
其中Bitmap 、HyperLogLog的底层都是 String 数据类型,
Geospatial 底层是 Sorted Set 数据类型
bitmap、1.统计用户的登录天数 随机统计某阶段天数2.某阶段活跃用户统计
布隆过滤器 :url是否爬取过,缓存穿透等场景
hyperloglogs: 做PV(页面浏览量)、UV(访客数量、)统计
geospatial:做附近的人,同城的人
3.- 什么是分布式锁
- 方案一:SETNX + EXPIRE
- 方案二:SETNX + value值是(系统时间+过期时间)
- 方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令)
- 方案四:SET的扩展命令(SET EX PX NX)
- 方案五:SET EX PX NX + 校验唯一随机值,再释放锁
- 方案六: 开源框架~Redisson
- 方案七:多机实现的分布式锁Redlock 参考 :www.cnblogs.com/wangyingshu…
- zset结构分析
当数据较少时,sorted set是由一个ziplist来实现的。 当数据多的时候,sorted set是由一个dict + 一个skiplist来实现的。简单来讲,dict用来查询数据到分数的对应关系,而skiplist用来根据分数查询数据(可能是范围查找)。 实现原因 ziplist节省内存,但是增删改查等操作较慢,而skiplist正好相反,增删改查非常快,但是相比ziplist会占用更多内存。redis在保存zset时按如下的规则进行选择: 当元素个数超过128或最大元素的长度超过64时用skiplist,其他情况下用ziplist,每次对zset进行插入、删除元素时都会重新判断是否需要转换保存格式。 原文链接:blog.csdn.net/hello_bravo… 跳表复杂度:blog.csdn.net/qq_34412579…
- Redis中的管道有什么用? 一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应,这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。这就是管道(pipelining) 6、怎么理解Redis事务? 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行,事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。Redis事务相关的命令有哪几个?MULTI、EXEC、DISCARD、WATCH
7.什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免? (1)缓存穿透:业务系统访问压根就不存在的数据,就称为缓存穿透。 方案1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。 方案2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。 方案3、布隆过滤器
(2)缓存雪崩当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。如何避免? 方案1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。 方案2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期 方案3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀 方案4.Hystrix是一款开源的“防雪崩工具”,它通过熔断、降级、限流三个手段来降低雪崩发生后的损失。 (3)缓存击穿表示恶意用户模拟请求很多缓存中不存在的数据,由于缓存中都没有,导致这些请求短时间内直接落在了数据库上,导致数据库异常。 方案1、使用互斥锁排队 方案2、接口限流与熔断、降级 方案3、布隆过滤器
8.redis的三种过期策略 1.定时删除2.惰性删除3.定期删除 redis采用的过期策略惰性删除+定期删除
9.redis6.0多线程网络模型 目前 Linux 平台上主流的高性能网络库/框架中,大都采用 Reactor 模式,比如 netty、libevent、libuv、POE(Perl)、Twisted(Python)等。
Reactor 模式本质上指的是使用 I/O 多路复用(I/O multiplexing) + 非阻塞 I/O(non-blocking I/O)的模式。
Redis 的核心网络模型在 6.0 版本之前,一直是单 Reactor 模式:所有事件的处理都在单个线程内完成,虽然在 4.0 版本中引入了多线程,但是那个更像是针对特定场景(删除超大 key 值等)而打的补丁,并不能被视作核心网络模型的多线程。
通常来说,单 Reactor 模式,引入多线程之后会进化为 Multi-Reactors 模式,基本工作模式如下:
区别于单 Reactor 模式,这种模式不再是单线程的事件循环,而是有多个线程(Sub Reactors)各自维护一个独立的事件循环,由 Main Reactor 负责接收新连接并分发给 Sub Reactors 去独立处理,最后 Sub Reactors 回写响应给客户端。
Multiple Reactors 模式通常也可以等同于 Master-Workers 模式,比如 Nginx 和 Memcached 等就是采用这种多线程模型,虽然不同的项目实现细节略有区别,但总体来说模式是一致的。
redis多线程网络模型的设计方案
- 使用IO线程实现网络IO多线程话,IO线程只负责网络IO和命令解析,不执行客户单命令
- 利用原子操作+交错访问实现无锁的多线程模型
- 通过设置 CPU 亲和性,隔离主进程和其他子进程,让多线程网络模型能发挥最大的性能。
模型缺陷:
- 最大的不同就是在标准的 Multi-Reactors/Master-Workers 模式下,Sub Reactors/Workers 会完成 网络读 -> 数据解析 -> 命令执行 -> 网络写 整套流程,Main Reactor/Master 只负责分派任务
- 而在 Redis 的多线程方案中,I/O 线程任务仅仅是通过 socket 读取客户端请求命令并解析,却没有真正去执行命令,所有客户端命令最后还需要回到主线程去执行,因此对多核的利用率并不算高,而且每次主线程都必须在分配完任务之后忙轮询等待所有 I/O 线程完成任务之后才能继续执行其他逻辑。
9.Redis怎么保持缓存与数据库一致性? Redis集群扩容,内部扩容 Redis 大key,热key 在某些业务场景下,Redis大key的问题是难以避免的,但是,memory usage命令和lazyfree机制分别提供了内存维度的抽样算法和异步删除优化功能, 这些特性有助于我们在实际业务中更好的预防大key的产生和解决大key造成的阻塞。异步化应该是Redis优化的主要方向。