Redis知识点总结

1.为什么不直接使用语言中的字典映射来缓存而是用Redis?

当然如果只是将少量数据保存作为缓存并且没有持久化的需求,那么完全可以用Map做缓存。

Redis相较于语言的映射的优势:

  1. Redis 可以用几十 G 内存来做缓存,Map 不行,一般 JVM 也就分几个 G 数据就够大了。
  2. Redis 的缓存可以持久化,Map 是内存对象,程序一重启数据就没了。
  3. Redis 可以实现分布式的缓存,各个实例共用一份缓存数据,Map 只能存在创建它的程序里,不具有一致性。
  4. Redis 可以处理每秒百万级的并发,是专业的缓存服务,Map 只是一个普通的对象。
  5. Redis 缓存有过期机制,Map 本身无此功能。
  6. Redis 有丰富的 API,Map 就简单太多了。
  7. Redis 是C语言写的,稳定性和性能更好。

参考回答

2.redis的持久化方式RDB和AOF的区别?

本质上,RDB(Redis DataBase)是保存数据本身,而AOF(Append-only file)是保存执行的命令。

  1. aof文件比rdb更新频率高,优先使用aof还原数据。
  2. aof比rdb更安全也更大
  3. rdb性能比aof好
  4. 如果两个都配了优先加载AOF
  • RDB每次保存都需要复制整个数据库的数据,开销太大,还会有停顿,保存频率低了可能会丢失数据;
  • AOF执行的命令越来越多,AOF文件也会越来越大,之后还原起来就会很花时间,也会有很多冗余。

参考博客

3.redis支持的数据类型?

  • 字符串
  • 列表
  • 哈希
  • 集合
  • 有序集合

参考博客

4.Redis有哪些架构模式?

  • 单机版
    简单,但是容量、处理能力都有限,且无法高可用。

  • 主从复制
    保持主从节点的数据一致,读操作可以丢给从服务器,降低了主服务器的读压力;写操作还是要在主服务器上,不能解决主服务器的写压力。同时,当主服务器挂了,还可以通过哨兵让一个从服务器称为新的主服务器,所以具有一定高可用性。

  • 哨兵
    Redis sentinel 是一个分布式系统中监控 redis 主从服务器,并在主服务器下线时自动进行故障转移。 其中三个特性:

    • 监控(Monitoring): Sentinel 会不断地检查你的主服务器和从服务器是否运作正常。
    • 提醒(Notification): 当被监控的某个 Redis 服务器出现问题时, Sentinel 可以通过 API 向管理员或者其他应用程序发送通知。
    • 自动故障迁移(Automatic failover): 当一个主服务器不能正常工作时, Sentinel 会开始一次自动故障迁移操作。
      所以,还是没有解决主服务器的写压力,切换主从的时候会丢失数据。但是满足了高可用性,自动的故障检测。
  • 集群(代理型)
    算是上面哨兵+主从复制的优化形式,通过一个代理节点来分发命令,实现均衡负载,数据的分片之类的。弥补了上面主服务器写压力大的问题。但是需要维护代理服务器。

  • 集群(直连型)
    没有代理,无中心结构,所有节点一起保存整个数据库,每个节点负责数据库的一段,各自协调。优点是:

    • 无中心架构,不存在哪个节点的瓶颈问题,没有上面那个代理节点;
    • 数据按照槽存储在不同节点,节点之间数据共享,还可以动态调整槽的分布;
    • 可扩展性,可以线性扩展到1000个节点,节点可以动态添加和删除;
    • 高可用性,部分节点不可用的时候,集群任然可用,槽可以迁移,还能用从节点做数据的备份;
    • 实现故障的自动转移,公共投票机制完成主从切换。

    缺点是资源隔离性差,数据异步复制,不好保证其一致性。

5.什么是一致性哈希算法?什么是哈希槽?

如何保证当系统的节点数目发生变化时仍然能够对外提供良好的服务,这是值得考虑的,尤其实在设计分布式缓存系统时,如果某台服务器失效,对于整个系统来说如果不采用合适的算法来保证一致性,那么缓存于系统中的所有数据都可能会失效(即由于系统节点数目变少,客户端在请求某一对象时需要重新计算其hash值(通常与系统中的节点数目有关),由于hash值已经改变,所以很可能找不到保存该对象的服务器节点),因此一致性hash就显得至关重要。

参考博客

Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点数量大致均等的将哈希槽映射到不同的节点。

在集群节点分片的时候,就会将所有 16384 个哈希槽分配到各个节点中。

参考博客

6.Redis常用命令

参考博客

7.Redis分布式锁

分布式锁:多机数据库下,当多个进程不在同一个系统中,用分布式锁控制多个进程对资源的访问。

先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!
参考博客
参考博客

8.Redis异步队列

一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
缺点是,在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
利用发布订阅模式,可以实现生产一次,消费多次。

9.什么是缓存穿透?如何避免?

缓存穿透:一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

解决方法:

  1. 对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。
  2. 对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

什么是bitmap?
参考博客

10.什么是缓存雪崩?何如避免?

缓存雪崩:当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

解决方法:

  1. 在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。
  2. 做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期。
  3. 不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。
原文地址:https://www.cnblogs.com/lippon/p/14171693.html