1.resis五种基本数据类型
redis基本数据类型的key都是string,value有以下5种基本类型:
String:{"zs" }
List: {"sdsad","sadsa","sd","sa"} redis是以双向链表实现
Set: {"ad","bc","ef"} redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
Hash: {"zs":"ab","cd":"ef","qw":"er"} hash 是一个 string 类型的 field(字段) 和 value(值) 的映射表,hash 特别适合用于存储对象。
Zsort: {"1":"a","2":"b","3":"c"}
2.redis增加的三种特殊数据类型
HyperLogLogs(基数统计)、Bitmap (位存储)、Geospatial (地理位置)
HyperLogLogs: 这个结构可以非常省内存的去统计各种计数,比如注册 IP 数、每日访问 IP 数、页面实时UV、在线用户数,共同好友数等。
BitMap:即位图数据结构,都是操作二进制位来进行记录,只有0 和 1 两个状态。
Geospatial:这个功能可以推算地理位置的信息: 两地之间的距离, 方圆几里的人。
3.Redis进阶 - 持久化:RDB和AOF机制详解
RDB:redis database的缩写,RDB持久化是将当前进程的数据生成快照保存到磁盘的过程,快照的值会比实际内存的要少。
触发方式:手动触发和自动触发。
save命令:阻塞当前进程,知道RDB结束,对于内存比较大的实例会造成长时间的阻塞。
//代码效果参考:http://www.zidongmutanji.com/zsjx/324049.html
bgsave命令:redis进程执行fork操作创建子进程,RDB持久化过程由子进程负责,完成后自动结束,阻塞只发生在fork阶段,一般时间比较短。自动触发:
redis.conf中配置save m n,即在m秒内有n次修改时,自动触发bgsave生成rdb文件;
主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点;
执行debug reload命令重新加载redis时也会触发bgsave操作;
默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作;
RDB优缺点
优点
RDB文件是某个时间节点的快照,默认使用LZF算法进行压缩,压缩后的文件体积远远小于内存大小,适用于备份、全量复制等场景;
Redis加载RDB文件恢复数据要远远快于AOF方式;
缺点
RDB方式实时性不够,无法做到秒级的持久化;
每次调用bgsave都需要fork子进程,fork子进程属于重量级操作,频繁执行成本较高;
RDB文件是二进制的,没有可读性,AOF文件在了解其结构的情况下可以手动修改或者补全;
版本兼容RDB文件问题;
AOF:Redis使用写后日志即:先写内存,再写磁盘,大多数数据库采用写前日志如MySQL。
优势:避免额外的开销,保证记录日志的命令都是正确的命令。不会阻塞当前的写操作。
风险:如果计入内存成功,此时服务器进程宕机会导致数据不一致。主线程写入磁盘操作,磁盘操作压力大,会阻塞后续操作。
Redis默认是不开启AOF,可以通过配置redis.conf文件来开启AOF持久化。
深入理解AOF重写
主线程fork出子进程重写aof日志
子进程重写日志完成后,主线程追加aof日志缓冲
替换日志文件
RDB和AOF混合方式(4.0版本)
内存快照以一定的频率执行,在两次快照之间//代码效果参考:http://www.zidongmutanji.com/bxxx/275738.html
,使用AOF日志记录这期间的所有操作命令。redis恢复持久化数据,优先加载AOF文件,如果AOF不存在则加载RDB文件。
1.为什么redis单线程却很快?
redis瓶颈在io,不在cpu。6.0之前,热地上都是采用单线程,采用了io多路复用。但是rdb,aof都是主线程fork子进程去进行。
线上环境采用全量的RDB+增量的AOF
4.Redis事务
redis事务就是一次性、顺序性、排他性的执行一个队列中的一系列命令
redis事务不支持回滚。原因:
redis错误一般都是执行语法的错误,这些都是在开发阶段可以避免的,而不是应该出现在生产环境。
不需要支持回滚,redis内部可以保证简介快速。
5.Redis主从模式
主从库之间采用的是读写分离的方式。
读操作:主库、从库都可以接收;
写操作:首先到主库执行,然后,主库将写操作同步给从库。
主从复制原理:
注意:在2.8之前redis支持全量复制,而2.8之后支持增量复制。
在从库执行replicaof 172.16.19.3 6379,确立主从关系。
为什么主从全量复制使用RDB而不使用AOF?
redis过期删除策略:
1.惰性删除:
服务器不会主动删除过期数据,当客户端查询某个数据,服务端判断该数据是否过期,过期之后删除。
2.定期删除;
服务器执行定时任务删除过期数据,删除就会释放内存,但是频繁删除又会对cpu不友好。随机取出20个key进行删除,如果过期key比例大于25%,重复此过程,直到过期key比例小于25%。
redis3.2增加,从节点读取数据判断,若数据已过期则不会返回给客户端。
6.Redis哨兵机制详解
哨兵集群,是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点
哨兵的选举机制其实很简单,就是一个Raft选举算法
7.Redis 集群的设计目标
8.缓存问题:一致性, 穿击, 穿透, 雪崩, 污染等
缓存穿透:大量请求缓存和数据库都没有的数据,恶意请求会导致大量请求到DB,造成数据库服务器宕机。
解决方案:
1.再后端进行校验,非法请求参数进行拦截。
2.将数据库及缓存中都没有的数据,在缓存中以value为null进行保存,设置短一些的过期时间如10-30秒。
3.使用布隆过滤器,对数据是否存在进行判断。
缓存击穿:大量请求缓存中没有但是数据库中有的数据,恶意请求会导致大量请求到DB,造成数据库服务器宕机。
解决方案:
1.设置热点数据永不过期
2.接口限流熔断,降级。重要的接口进行保护,防止恶意刷接口。
3.加互斥锁
缓存雪崩:大量缓存key过期,请求会导致大量请求到DB,造成数据库服务器宕机。
解决方案:
1.热点数据永不过期
2.部分数据可以设置过期时间后加随机值
3.热点数据部署在不同的缓存数据库中
缓存设置大小一般为最大数量的15%-30%。
数据库和缓存一致性解决方案。
读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应。
更新的时候,先更新数据库,然后再删除缓存。
Redis的多线程部分只是用来处理网络数据的读写和协议解析,执行命令仍然是单线程顺序执行。
Redis性能优化
避免存储 bigkey,降低释放内存的耗时
淘汰策略改为随机淘汰,随机淘汰比 LRU 要快很多(视业务情况调整)
拆分实例,把淘汰 key 的压力分摊到多个实例上
如果使用的是 Redis 4.0 以上版本,开启 layz-free 机制,把淘汰 key 释放内存的操作放到后台线程中执行(配置 lazyfree-lazy-eviction = yes)
Redis问题定位
Redis常见面试问题
常规问题
什么是redis,为什么要使用它
redis一般有哪些使用场景
redis为什么快
? 数据类型和数据结构
redis有哪些数据类型
redis数据类型有哪些命令
谈谈redis的对象机制(redisObject)
redis数据类型有哪些底层数据结构
为什么要设计sds?
一个字符串类型的值能存储最大容量是多少?512M
为什么会设计Stream
Stream用在什么样场景
消息ID的设计是否考虑了时间回拨的问题
? 持久化和内存
Redis 的持久化机制是什么?各自的优缺点?一般怎么用?
Redis 过期键的删除策略有哪些
Redis 内存淘汰算法有哪些
Redis的内存用完了会发生什么? 如果达到设置的上限,Redis的写命令会返回错误信息(但是读命令还可以正常返回。)或者你可以配置内存淘汰机制,当Redis达到内存上限时会冲刷掉旧的内容。
Redis如何做内存优化?
Redis key 的过期时间和永久有效分别怎么设置?
EXPIRE 和 PERSIST 命令
Redis 中的管道有什么用?
一次请求/响应服务器能实现处理新的请求即使旧的请求还未被响应,这样就可以将多个命令发送到服务器,而不用等待回复,最后在一个步骤中读取该答复。
这就是管道(pipelining),是一种几十年来广泛使用的技术。例如许多 POP3 协议已经实现支持这个功能,大大加快了从服务器下载新邮件的过程。
? 事务
什么是redis事务
Redis事务相关命令
Redis事务的三个阶段
watch是如何监视实现的呢
为什么 Redis 不支持回滚
redis 对 ACID的支持性理解
Redis事务其他实现
基于Lua脚本,Redis可以保证脚本内的命令一次性、按顺序地执行,其同时也不提供事务运行错误的回滚,执行过程中如果部分命令运行错误,剩下的命令还是会继续运行完
基于中间标记变量,通过另外的标记变量来标识事务是否执行完成,读取数据时先读取该标记变量判断是否事务执行完成。但这样会需要额外写代码实现,比较繁琐
? 集群
? 主从复制
Redis集群的主从复制模型是怎样的?
全量复制的三个阶段?
为什么会设计增量复制?
增量复制的流程? 如果在网络断开期间,repl_backlog_size环形缓冲区写满之后,从库是会丢失掉那部分被覆盖掉的数据,还是直接进行全量复制呢?
为什么不持久化的主服务器自动重启非常危险呢?
为什么主从全量复制使用RDB而不使用AOF?
为什么还有无磁盘复制模式?
为什么还会有从库的从库的设计?
? 哨兵机制
Redis哨兵机制?哨兵实现了什么功能呢
哨兵集群是通过什么方式组建的?
哨兵是如何监控Redis集群的?
哨兵如何判断主库已经下线了呢?
哨兵的选举机制是什么样的?
Redis 1主4从,5个哨兵,哨兵配置quorum为2,如果3个哨兵故障,当主库宕机时,哨兵能否判断主库“客观下线”?能否自动切换?
主库判定客观下线了,那么如何从剩余的从库中选择一个新的主库呢?
新的主库选择出来后,如何进行故障的转移?
? Redis集群
说说Redis哈希槽的概念?为什么是16384个?
Redis集群会有写操作丢失吗?为什么?
Redis并不能保证数据的强一致性,这意味这在实际中集群在特定的条件下可能会丢失写操作。
? 应用场景
redis 客户端有哪些
Redisson、Jedis、lettuce等等,官方推荐使用Redisson。
Redisson是一个高级的分布式协调Redis客服端,能帮助用户在分布式环境中轻松实现一些Java的对象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)。
Redis如何做大量数据插入? Redis2.6开始redis-cli支持一种新的被称之为pipe mode的新模式用于执行大量数据插入工作。
redis实现分布式锁实现? 什么是 RedLock?
redis缓存有哪些问题,如何解决
redis和其它数据库一致性问题如何解决
redis性能问题有哪些,如何分析定位解决
? 新版本
Redis单线程模型? 在6.0之前如何提高多核CPU的利用率?
可以在同一个服务器部署多个Redis的实例,并把他们当作不同的服务器来使用,在某些时候,无论如何一个服务器是不够的, 所以,如果你想使用多个CPU,你可以考虑一下分片(shard)。
6.0版本中多线程