Redis常见面试题总结
1. AOF 与 RDB 的区别?
   AOF:redis会将每一个请求都记录在日志文件中,当redis重启时,会读取日志文件,将请求重新执行一遍,以恢复数据到最新状态,aof默认关闭,通过appendonly yes开启
				  aof有三种策略:1)aof always:每一条请求都会写入日志,这样会保证数据不丢失,但是会影响redis的效率
								  2)aof everysec:每秒将请求写入日志一次,对redis性能影响较小,但是redis宕机的时候会丢失一秒的数据
								  3)aof sync:redis定时将请求写入日志,默认一分钟,对性能几乎无影响,但是会丢失数据比较多	
			  aof重写:配置aof重写策略,当aof日志文件增长一定大小时,redis将会fork一个子进程重写日志文件,将文件保留可以恢复最新数据的最小大小
			  优点:1)开启aof always时,可以保证数据不丢失,及时是aof everysec,也只会丢失一秒数据
				    2)即使断电,也可以通过工具修复日志
				    3)写入错误的redis命令时,可以通过删除错误命令,执行aof日志命令恢复数据
			  缺点:对性能影响比RDB大,恢复速度较慢          
			  RDB:redis会定期保存数据快照到rdb文件中,当redis重启时,读取数据快照恢复数据,默认开启rdb策略
				  通过 sava [second] [changes] 来配置rdb快照策略,可以配置多条来实行多级快照保存策略,可以通过BGSAVE来手动处罚rdb快照保存
			  rdb会在保存时,fork一个进程来将数据写入临时文件,当写入完毕时,用临时文件替换上次持久化文件,对redis几乎无影响,比aof高效,但是最后一次的数据会丢失
			  优点:1)由于是通过fork子进程来操作,对redis影响很小
				    2)恢复文件的速度比aof快
				    3)每次快照会保存完整的数据快照,可以作为灾备手段
			  缺点:1)会丢失最后一次的数据
				    2)当数据较多时,cpu不给力,子进程执行快照会耗时较长,影响redis对外服务能力
			  推荐使用rdb + aof everysec组合的持久化方式
		2. Redis集群有哪几种?
			  1)主从模式:一个master,多个slave,支持主从复制,支持读写分离
				    优点:slave可以分担master的读压力,master挂了后,slave依然可读
				    缺点:master挂了之后,slave不会选举出新master,难以扩容,不推荐使用这个模式
			  2)哨兵模式:通过哨兵来监控master和slave,master挂了之后会选举出slave
				    优点:继承主从模式的优点,并且更加健壮,可用性更高
				    缺点:同样难以扩容
			  3)集群模式:redis3.0之后支持redis集群,可以在多台机器上部署多台master(每个master存储一部分数据),每个master有多个slave,当某个master挂了后,redis cluster会从slave中选举出新master
		3. Redis选举流程?
			  1)Redis的某个slave节点发现自己的主节点变为FAIL状态时,会尝试选举成为新的master节点(持有最新数据的slave节点会首先发起选举)
			  2)该slave节点会广播一条消息给其他master节点
			  3)其他master节点接收消息之后,会判断请求者的合法性,若合法,会发送确认消息给该slave节点(若其他master节点未接到要求选举slave节点的master节点的FAIL消息,会拒绝投票)
			  4)当slave节点收到超过半数的选票之后,会成为master节点,若选举失败,会开始下一轮选举
			  5)新的master节点会继承原master节点的hash槽
			  6)新的master节点会广播消息告诉其他节点自己成为了master节点
			  7)新master节点开始处理槽相关的请求
		4. Redis Cluster数据分片?
			  Redis Cluster通过hash槽分片存储数据,共有16384个hash槽,每个节点拥有一部分hash槽,key通过CRC16算法来确认hash值,映射到相应的节点上
			如果增加节点,会从现有节点分配hash槽到新节点,如果删除节点,会将删除节点的hash槽分配给剩余节点
			Redis Cluster没有自己实现hash槽的分配与计算,需要客户端自己实现,客户端可以根据机器CPU能力来分配hash槽区间大小
		5. 了解一致性hash吗? 为什么不用一致性hash?
			  一致性hash是将节点映射在一个2^32大小的圆环上,key通过hash,得到在圆环上单的位置,数据存储在顺时针的下一个节点上,
			当节点有变更时,知会影响节点与下一个节点间的数据。
			  为什么不用:实际情况中节点一般较少,一致性hash当节点较少时,会出现数据倾斜,数据分布不均匀,
					而且节点少时,当节点出现变化情况下,节点中的数据映射影响很大。
		6. Redis如何保证slots迁移过程中的数据正常读写
			  当节点A的数据迁移到节点B中时,会将节点A标记为Migrating(迁移)状态,将节点B标记为importing(导入中)状态,节点的槽映射不做修改
			当有数据访问节点A时,如果数据还在节点A上,会直接返回数据,如果不存在,返回一个ACK转向消息
			客户端收到ACK消息,转而访问转向所指定节点B,先发送一个ACKING请求,再发送真正的请求
			客户端收到节点B返回的数据后,不会改变槽映射关系
			等待节点A所有slots都迁移到节点B后,再次有请求访问节点A,会返回一个MOVED消息,将映射永久指向节点B
		7. Redis 是什么实现主从同步的?怎么保证数据一致性?
			  Redis master节点可以执行读写命令,slave节点只能执行读命令,主从同步分为三种
			  1)初次全量复制
				  当一个slave节点启动时,会向master节点发送sync命令,master节点接收命令后开始执行bgsva,保存rdb快照,将rdb快照发送给slave节点,
				并将同步期间的写命令缓存起来,slave节点接收rdb快照后,载入数据,然后master节点会发送缓存的写命令,slave节点执行缓存的写命令。
			  2)命令传播
				  master节点每次执行写命令后,会将命令发送给slave节点,slave节点执行命令进行同步
			  3)重新复制
				  当slave节点断开连接重连后,会发送偏移量给master节点,master节点首先会判断该slave节点是否之前是自己的从节点,如果不是,进行全量复制
				如果是,会比较和自己的偏移量,如果不一致,会从积压缓冲区将偏移量之后的命令发送给slave,slave执行命令进行同步
		8. Redis 的过期策略都有哪些?Redis 怎么删除过期数据的?
			  定时删除:在给key设置过期时间的同时,给key加一个定时器,当key过期的时候删除它
				    优点:可以及时删除key,保证内存释放
				    缺点:消耗性能,每个设置过期的key都需要一个定时器
			  惰性删除:当取到过期key的时候,删除key,返回null
				    优点:对性能无影响
				    缺点:当过期key长时间没有被取时,会发生内存泄露
			  定期删除:固定频率去删除过期的key
				    优点:在内存处理方面优于惰性删除,在cpu处理方面优于定时删除
				    缺点:并不会检查所有的key是否过期,而是随机选择一部分key,可能存在很多key过期没有被删除
			  Redis采用定期删除+惰性删除的策略
		9. Redis内存淘汰策略?
			  noeviction:内存不足时,新写入操作会报错
			  allkeys lru:内存不足时,移除所有key中最近最少使用的(推荐使用)
			  volatile lru:内存不足时,移除设置了过期时间的key中,最近最少使用的(当redis又当缓存,又当持久层时使用)
			  allkeys random:内存不足时,在所有key中随机移除一个
			  volatile random:内存不足时,在设置了过期时间的key中随机移除一个
			  volatile ttl:内存不足时,在设置了过期时间的key中,移除剩余过期时间最短的key
		10. 热点Key问题的怎么发现与解决?
			  如何发现:
				  1)凭借业务经验,提前预估热key
				  2)在客户端进行收集,在操作redis前,加一行代码进行统计
				  3)用proxy层进行收集,不是所有项目的redis架构都有proxy层
				  4)自己写程序抓包分析,开发成本高,维护苦难,容易丢包
				  5)用redis自带命令:monitors命令和hotkeys命令,会影响redis性能
			如何解决:
				  1)利用二级缓存
					    发现之后,利用jvm做二级缓存,将热key存在hashmap中,后面的请求都从hashmap中取
				  2)备份热key
					    将热key备份到多个redis节点中,请求过来的时候分散到多个节点去取
		11. 为啥 Redis 单线程模型也能效率这么高? 
			  读110000tps,写81000tps
			  原因:1、单线程操作,避免了上下文的切换;
				    2、纯内存操作,减少IO
				    3、使用了非阻塞多路复用IO模型:Redis client根据不同操作产生不同的soket,redis服务端有一段IO多路复用程序,将soket置入队列中,
						然后文件事件分派器依次从队列中取,分发给不同的事件处理器处理
		12. 什么是缓存穿透和雪崩,如何解决缓存穿透和雪崩? 
			  缓存穿透是:用户请求了一个在数据库中不存在的数据,导致缓存层失效,请求直接打到数据库,并发量大的情况下会打垮数据库
			  解决:1、当查询数据库不存在时,给这条数据设置一条空值的缓存,避免后续请求都打到数据库;
				    2、使用布隆过滤器实现,布隆过滤器内部通过一个bitmap,将所有存在的key都存在map中,每次请求都查找map中是否存在key,不存在则查看
			  缓存击穿:缓存设置了过期时间,在过期时间失效的一刻,恰好大量请求打过来,由于新的请求还来不及写入缓存,导致所有请求打到数据库,进而打垮数据库
			  解决:1、将热点数据设为永不失效
				    2、给请求数据库的操作加锁,单机用synchronized或ReentrantLock,分布式集群环境可以用redis做分布式锁
			  缓存雪崩:在同一时刻,大量缓存集中失效,导致大量请求直接打到数据库,使数据库被打垮
			  解决:给key设置过期时间的时候加上随机数,使过期时间随机分布
		13. 怎么高效的批量删除 Redis上面的 KEY ?
			  redis本身不提供批量删除功能,可以通过keys、scan加xargs组合命来来实现批量删除
			  1)redis-cli -h xxx.xxx.xxx -p xxxx --raw keys "ops-coffee-*" | xargs redis-cli del
				    会导致redis阻塞,不推荐使用
			  2)redis-cli -h xxx.xxx.xxx -p xxxx --scan --pattern "*-coffee-*" | xargs -L 2000 redis-cli del
				    scan渐进式删除,会将操作分批执行,不会阻塞redis