FIFTEEN------Redis

196 阅读12分钟

1、Redis 是什么?都有哪些使用场景?
Remote Dictionary Server(远程字典服务器)是完全开源免费的,用C语言编写的,遵守BSD协议,是一个高性能的(key-value)分布式内存数据库,基于内存运行并支持持久化的NoSQL数据库(NoSQL数据库的产生就是为了解决大规模数据集合带来的挑战,包括超大规模数据的存储。)

Redis的特点:

Redis 支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再
次加载进行使用。

Redis 不仅仅支持简单的 key-value 类型的数据,同时还提供 list,set,zset,
hash 等数据结构的存储。

速度快,因为数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作
的时间复杂度都是 O1)

支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,
要么全部不执行

2、Redis 有哪些功能?

支持数据缓存功能

支持分布式锁的功能

支持数据持久化

支持事务

支持消息队列 

3、Redis 和 Memecached [Mem/cached]有什么区别?

Memcached所有的值均是简单的字符串,Redis支持更为丰富的数据类型

Redis的速度比Memcached快很多

Redis可以持久化其数据

4、Redis 为什么是单线程的?
(官方文档)因为 cpu 不是 Redis 的瓶颈,Redis 的瓶颈最有可能是机器内存或者网络带宽。既然单线程容易实现,而且 cpu 又不会成为瓶颈,那就顺理成章地采用单线程的方案了。
采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗。
而且单线程并不代表就慢 nginx 和 nodejs 也都是高性能单线程的代表。

5、Redis 支持的数据类型有哪些?
Redis 支持五种数据类型:String(字符串)、Hash(哈希)、List(列表)、Set(集合)、SortSet(有序集合)。 6、Redis 支持的 Java 客户端都有哪些?
Jedis、Redisson 、lettuce [ˈletɪs]等等

7、怎么保证缓存和数据库数据的一致性?

合理设置缓存的过期时间。

新增、更改、删除数据库操作时同步更新 Redis,可以使用事物机制来保证数据的一致性。

8、Redis 持久化有几种方式以及各自的优缺点?
Redis 提供两种持久化机制或者说有两种策略: RDB 和 AOF 机制:
• RDB(Redis Database)(快照持久化)

是指用快照的方式记录 Redis 数据库的所有数据,在某个时间点将数据写入一个临时文件dump.rdb,持久化
结束后,用这个临时文件替换上次持久化的文件,达到数据恢复。

• AOF(Append Only File)(文件追加)

当Redis服务器执行写命令的时候,将执行的写命令保存到AOF文件中。

RDB的优缺点:

只有一个文件 dump.rdb,方便持久化

数据安全性低。RDB 是间隔一段时间进行持久化,如果持久化之间 redis 
发生故障,会发生数据丢失。

AOF的优缺点:

通过 append 模式写文件,即使中途服务器宕机,可以通过 redis-check-aof
工具解决数据一致性问题。
AOF 机制的 rewrite 模式,AOF 文件没被 rewrite 之前(文件过大时会对命令
进行合并重写),可以删除其中的某些命令(比如误操作的 flushall)

AOF 文件比 RDB 文件大,且恢复速度慢
数据集大的时候,比 rdb 启动效率低。

9、说一说Sentinel哨兵机制 [ˈsentɪnl]


当主节点宕机了,整个集群就没有可写的节点了。由于从节点上备份了主节点的所有数据,那在主节点宕机的情况下,如果能够将从节点变成一个主节点,就可以解决这个问题了 这就是Sentinel哨兵的作用!

哨兵的任务:Redis 的 Sentinel 系统用于管理多个 Redis 服务器(instance), 该系统执行以下三个任务:

• 监控: Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。

• 提醒: 当被监控的某个 Redis 服务器出现问题时, 
		Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。

• 自动故障迁移: 当一个主服务器不能正常工作时,
			   Sentinel 会开始一次自动故障迁移操作, 它会进行选举,
               将其中一个从服务器升级为新的主服务器, 并让失效主服务器
               的其他从服务器改为复制新的主服务器; 当客户端试图连接失效的主服务器时, 
               集群也会向客户端返回新主服务器的地址, 使得集群可以使用新主服务器代替失效服务器。
               

10、什么是 Redis 集群,集群的原理是什么?
在哨兵模式中,仍然只有一个Master节点。当并发写请求较大时,哨兵模式并不能缓解写压力。 我们知道只有主节点才具有写能力,那如果在一个集群中,能够配置多个主节点,就可以缓解写压力了,这就是redis-cluster集群模式! [ˈklʌstə(r)] Redis集群是Redis提供的分布式数据库方案,集群通过分片进行数据共享,提供复制和故障转移功能。
一个Redis集群通常由多个节点组成,最初每个节点都是独立的,当通过CLUSTER MEET <ip> <port>命令将各个独立的节点连接起来之后,它们就组成了一个集群。 (一个节点其实就是一个运行在集群模式下的Redis服务器。其所提供的功能与普通的Redis服务器一致的)
Redis集群通过分片的方式来保存数据库中的键值对,集群中的整个数据库被分为16384个槽,数据库中的每个键都属于这16384个槽的其中一个。

11、说说 Redis 哈希槽的概念?
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,Redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 取模,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。
使用哈希槽的好处就在于可以方便的添加或移除节点。

12、Redis 集群的主从复制模型是怎样的?[ˈmɑːstə(r)]、[sleɪv] 主从复制模型特点:

• 主节点Master可读、可写

• 从节点Slave只读(read-only)

因此,主从模型可以提高读的能力,在一定程度上缓解了写的能力。因为能写仍然只有Master节点一个,可以将读的操作全部移交到从节点上,变相提高了写能力。

13、Redis 集群之间是如何复制的?
Redis 2.8 版本以前,Redis 通过同步(sync)和指令传播(command propagate)两个操作完成同步

• 同步(sync):将从节点的数据库状态更新至与主节点的数据库状态一致
• 指令传播(command propagate):主节点数据被修改,会主动向从节点发送执行的写指令,
从节点执行之后,两个节点数据状态又保持一致

2.8 版本开始新增 PSYNC 指令,PSYNC 具有两种模式:

完整重同步(full resynchronization),与 sync 过程基本一致
部分重同步(partial resynchronization),借助主从服务器的复制偏移量、
主服务器的复制积压缓冲区、服务器运行 ID ,完成主从节点断开连接后,从节点重连主节点后,
条件允许,主节点将连接断开期间执行的写指令发送给从节点,从节点接收并执行写指令,
将数据库更新至主节点当前状态。

14、怎么测试Redis的连通性?6379\color{red}{6379}
• 使用 ping 指令,如
• Java 代码对 Redis 连通性测试,可以使用 Redis 客户端类库包里的 api 发送 ping 指令

15、Redis 的key 过期时间和永久有效分别怎么设置?
使用过期时间expire 和永久有效persist命令。[ɪkˈspaɪə(r)]、 [pəˈsɪst]

如EXPIRE key 100(设置了过期时间,100秒后,key将自动被删除)
persist : 设置成永不过期,格式是:persist key值

16、说一说Redis 的回收策略(淘汰策略)
当Redis所用内存达到maxmemory上限时会触发相应的溢出控制策略。具体策略受maxmemory-policy参数控制,Redis支持6种策略:
当内存不足以容纳新写入数据时:

• noeviction:默认策略,新写入操作会报错

• 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)中任意选择数据淘汰

17、什么是缓存雪崩?以及解决办法
如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩。
解决方案:

• 要保证redis的高可用,可以使用主从+哨兵或redis cluster,避免服务器不可用;

• 使用本地ehcache缓存+hystrix限流/降级,当redis查询不到结果,可以从本地缓存中查询,
  如果还是查不到,就要从数据库中查询,不过这里要有一层限流,防止数据库宕死;

•  使用redis的持久化RDB+AOF组合策略,防止缓存丢失并且可以快速恢复数据;

• 需要给redis缓存中的key值设置过期时间时,尽量不要设置同一时间,如果业务场景允许可以将缓存时间加个随机数。

18、什么是缓存穿透?以及解决办法
缓存穿透是指查询一个一定不存在的数据。由于缓存不命中,并且出于容错考虑,如果从数据库查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,失去了缓存的意义。

解决方案:

• 对请求参数做校验,例如可以用正则;

• 当我们从数据库找不到数据后,我们也将这个空对象设置到缓存里边去。下次再请求的时候,就可以从缓存里边获取了。

• 可以引入布隆过滤器(Bloom filter),过滤一些异常的请求,提前拦截,不合法就不让这个请求到数据库层

19、使用过 Redis 分布式锁么,它是怎么实现的?

  1. 为什么要使用分布式锁?

     总结来说就是分布式系统要访问共享资源,为了避免并发访问资源带来错误,我们为共享资源添加一把锁,
     让各个访问互斥,保证并发访问的安全性,这就是使用分布式锁的原因。
    
  2. Redis中分布式锁的实现

     只要使用setnx指令对某个key上锁就行
     setnx lock test //上锁
     del lock test //解锁
     当某个key没有被占用的时候,setnx指令会返回1,否则返回0,这就是Redis中分布式锁的使用原理。
     我们还可以在上锁之后使用expire指令给锁设置过期时间
    

当然我们还可以在上锁之后使用expire指令给锁设置过期时间。

20、说一说Redis 常见性能问题和解决方案

• 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内

• Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件
-----Master写内存快照,save命令调度rdbSave函数,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,
     会间断性暂停服务,所以Master最好不要写内存快照。
-----Master AOF持久化,如果不重写AOF文件,这个持久化方式对性能的影响是最小的,但是AOF文件会不断增大,
     AOF文件过大会影响Master重启的恢复速度。
     
• 尽量避免在压力很大的主库上增加从库

21、MySQL 里有 2000w 数据,redis 中只存 20w 的数据,如何保证 redis 中的数据都是热点数据?
Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略。Redis 提供 6 种数据淘汰策略。

22、如果有大量的 key 需要设置同一时间过期,一般需要注意什么?
如果大量的 key 过期时间设置的过于集中,到过期的那个时间点,redis 可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。