根据自己的学习和面试总结的,纯手工打,尽量简洁易懂,排版不好,请见谅
1.redis支持的数据结构
string list hash set zset
2.redis线程模型
redis是单线程实现。
3.redis 提供的持久机制
redis 支持rdb和afo两种持久机制。rdb是定时的持久机制,宕机有可能会存在数据丢失。aof是基于操作日志的持久机制。
另外如果使用了rdb备份机制,每个实例使用2G内存,则我们的系统需要大于8G内存,因为rdb使用了copy-on-write机制,需要fork出一个子进程,并且复制一份内存,因此需要双份的内存存储大小
4.redis事务
redis提供了一些在一定程度上支持线程安全和事务的命令。例如:multi/exec watch inc等。但是redis的事务并不支持回滚,即可以两个命令可以同时提交执行,但是如果有失败,成功的也不会回滚
5.redis高可用实现
redis支持主从节点复制配置,同时还支持Sentinel(哨兵 用到了raft选主协议)和Cluster(集群,3.0版本开始)等高可用集群方案
6.redis数据淘汰策略
在 redis 中,允许用户设置最大使用内存大小通过配置redis.conf
中的maxmemory
这个值来开启内存淘汰功能,在内存限定的情况下是很有用的。
redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。redis 提供 6种数据淘汰策略通过maxmemory-policy
设置策略:
- volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰
- volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
- volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
- allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰
- allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
- no-enviction(驱逐):禁止驱逐数据
redis默认不采用淘汰策略(no-enviction),直接返回错误。
7、redis lru数据淘汰机制
再数据集合中随机挑选几个键值对,取出其中lru最大的键值对淘汰。所以redis并不是保证淘汰的是最近最少使用的,而是随机挑选的几个键值对中的最近最少使用的
8.过期策略的实现
常见的过期策略有三种,定时,惰性,定期。redis使用了惰性和定期策略,memcached只使用了惰性策略
定时策略:指定在多少时间之后过期。
java代码部分实现实现:
ScheduledExecutorService ses = Executors.newScheduledThreadPool(8);
ses.schedule(new DelThread(), 10, TimeUnit.SECONDS);
惰性策略:key过期的时候不删除,每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null
定时策略:每隔一段时间执行一次删除(在redis.conf配置文件设置hz,1s刷新的频率)过期key操作。java实现的话就是起个定时任务而已
9.缓存穿透
缓存穿透指的是使用不存在的key进行大量的高并发查询,这导致缓存无法命中,每次请求都要穿透到后端数据库系统进行查询,数据库压力过大。
常用解决方案:将空值缓存起来。
其他解决方案:使用布隆过滤器(guava 19开始已支持布隆过滤器),布隆过滤器原理与应用
10.缓存雪崩
缓存雪崩指缓存服务器重启或者大量缓存集中在某一个时间段内失效
常用解决办法:对不同的数据使用不同的失效时间,甚至对相同的数据、不同的请求使用不同的失效时间。
11.缓存优秀实践
1)使用前对数据大小进行评估,包括缓存的数据结构、大小、数量、失效时间
2)根据业务进行隔离,尽量不要多个业务共用一个缓存实例
3)缓存的key尽可能的设定缓存失效时间,且失效时间不能集中在某一点
4)缓存尽量不要存大对象
5)写缓存时一定要写入完全正确的数据。如果缓存数据部分有效,部分无效,宁可放弃缓存
6)一定要对操作超时时间进行设置。一般我们设计缓存作为加速数据库读取的手段,也会对缓存操作做降级处理,因此推荐使用更短的缓存超时时间,如果一定要给出一个数字,则希望是100毫秒以内