0%

Redis面经

Redis系统的理解和介绍。

[1] 主要参考了库森的总结十分全面

文章的结构也基本是库森文章的简化。

先说明redis是什么、有什么优点、使用场景是什么

然后具体谈谈redis的一些特性 比如数据类型、持久化、事务、单线程

使用redis可能带来的问题:缓存淘汰策略、缓存一致性、缓存穿透、缓存雪崩

结构和模式:主从复制、哨兵模式、集群模式;

最后是Redis实际使用的优化

1 Redis概述

1.1 Redis是什么?它的优缺点?【重要】

Redis本质上是一个Key-Value键值对的非关系型数据库,整个数据库加载在内存中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。Redis最大的特点就是性能好,每秒可以处理超过 10万次读写操作。

优点:

  • 读写性能极高, Redis能读的速度是110000次/s,写的速度是81000次/s
  • 数据结构丰富,除了支持string类型外,还支持hash、set、zset、list等数据结构。
  • 支持数据持久化,支持AOF和RDB两种持久化方式。
  • 支持事务, Redis的所有操作都是原子性的,一般通过MULTI和EXEC将指令打包实现事务。
  • 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。

缺点:

  • 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。(因为内存根本放不下海量数据嘛)
  • 主机宕机,宕机前有部分数据未能及时同步到从机,切换主机后可能导致数据不一致的问题,降低了系统的可用性。(缓存一致性问题)

1.2 Redis的常用场景有哪些?

1、缓存(定期删除、淘汰策略是为缓存准备的)

缓存现在几乎是所有中大型网站都在用的必杀技,合理的利用缓存不仅能够提升网站访问速度,还能大大降低数据库的压力。Redis提供了键过期功能,也提供了灵活的键淘汰策略,所以,现在Redis用在缓存的场合非常多。

2、分布式会话

集群模式下,在应用不多的情况下一般使用容器自带的session复制功能就能满足,当应用增多相对复杂的系统中,一般都会搭建以Redis等内存数据库为中心的session服务,session不再由容器管理,而是由session服务及内存数据库管理。(就是说session放在redis中、也就是类似无状态登录嘛)

3、分布式锁

在很多互联网公司中都使用了分布式技术,分布式技术带来的技术挑战是对同一个资源的并发访问,如全局ID、减库存、秒杀等场景,并发量不大的场景可以使用数据库的悲观锁、乐观锁来实现,但在并发量高的场合中,利用数据库锁来控制资源的并发访问是不太理想的,大大影响了数据库的性能。可以利用Redis的setnx功能来编写分布式的锁,如果设置返回1说明获取锁成功,否则获取锁失败,实际应用中要考虑的细节要更多。

4、 社交网络

点赞、踩、关注/被关注、共同好友等是社交网站的基本功能,社交网站的访问量通常来说比较大,而且传统的关系数据库类型不适合存储这种类型的数据,Redis提供的哈希、集合等数据结构能很方便的的实现这些功能。如在微博中的共同好友,通过Redis的set能够很方便得出。

5、排行榜

很多网站都有排行榜应用的,如京东的月度销量榜单、商品按时间的上新排行榜等。Redis提供的有序集合数据类构能实现各种复杂的排行榜应用。

1.3 关系型数据库和非关系型数据库的区别【理解背】

  • 关系型数据库:

    • 关系型数据库的最大特点就是事务的一致性:传统的关系型数据库读写操作都是事务的,具有ACID的特点
    • 关系型数据库为了维护一致性所付出的巨大代价就是其读写性能比较差
    • 关系数据库的另一个特点就是其具有固定的表结构,因此,其扩展性较差
  • 非关系型数据库 not only SQL

    • 指非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统
    • 面向高性能并发读写的key-value数据库
    • 面向可扩展性的分布式数据库

数据的持久存储,尤其是海量数据的持久存储,还是需要一种关系数据库

2 Redis的数据结构、持久化、事务 和单线程

redis最基本的一些特性

2.1 Redis的数据结构【重要】

有五种常用数据类型:String、Hash、Set、List、SortedSet。以及三种特殊的数据类型:Bitmap、HyperLogLog、Geospatial ,其中HyperLogLog、Bitmap的底层都是 String 数据类型,Geospatial 的底层是 Sorted Set 数据类型。

五种常用的数据类型【重要】:

1、String:String是最常用的一种数据类型,普通的key- value 存储都可以归为此类。其中Value既可以是数字也可以是字符串。使用场景:常规key-value缓存应用。常规计数: 微博数, 粉丝数。

2、Hash:Hash 是一个键值(key => value)对集合。Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值。(类似hashmap)

3、Set:Set是一个无序的天然去重的集合,即Key-Set。此外还提供了交集、并集等一系列直接操作集合的方法,对于求共同好友、共同关注什么的功能实现特别方便。(类似hashset)

4、List:List是一个有序可重复的集合,其遵循FIFO的原则,底层是依赖双向链表实现的,因此支持正向、反向双重查找。通过List,我们可以很方面的获得类似于最新回复这类的功能实现。(类似linkedlist)

5、SortedSet:类似于java中的TreeSet,是Set的可排序版。此外还支持优先级排序,维护了一个score的参数来实现。适用于排行榜和带权重的消息队列等场景。

三种特殊的数据类型

1、Bitmap:位图,Bitmap想象成一个以位为单位数组,数组中的每个单元只能存0或者1,数组的下标在Bitmap中叫做偏移量。使用Bitmap实现统计功能,更省空间。如果只需要统计数据的二值状态,例如商品有没有、用户在不在等,就可以使用 Bitmap,因为它只用一个 bit 位就能表示 0 或 1。

2、Hyperloglog。HyperLogLog 是一种用于统计基数的数据集合类型,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定的、并且是很小的。每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。场景:统计网页的UV(即Unique Visitor,不重复访客,一个人访问某个网站多次,但是还是只计算为一次)。要注意,HyperLogLog 的统计规则是基于概率完成的,所以它给出的统计结果是有一定误差的,标准误算率是 0.81%。

3、Geospatial :主要用于存储地理位置信息,并对存储的信息进行操作,适用场景如朋友的定位、附近的人、打车距离计算等。

2.2 Redis 的持久化【重要】

Redis 是内存数据库,如果不将内存中的数据库状态保存到磁盘,那么一旦服务器进程退出,服务器中的数据库状态也会消失。Redis 不同于 Memcached 的很重要一点就是,Redis 支持持久化。

Redis 支持两种不同的持久化操作。Redis 的一种持久化方式叫快照(snapshotting,RDB),另一种方式是只追加文件(append-only file, AOF)

  • 快照:(数据可能丢失)

快照就是根据设置的时间间隔和更新次数来判断是否进行数据的备份,设置命令是save 900 1(就是指900秒内如果至少有一个key进行了修改,就进行持久化的操作)。快照的备份通过单独创建子进程来完成,备份过程中主进程不进行任何的IO操作,确保了极高的性能。适合于对大规模数据的恢复

快照的缺点是:1创建子进程会占用一定的内存空间;2 最后一次持久化之后的数据可能丢失

  • AOF:(修复速度慢)

AOF持久化是记录每一次修改redis数据的命令。AOF默认是关闭的,可以在配置文件中开启,一般有三个选项:每次修改都写入AOF文件、每秒一次写入AOF文件、由操作系统决定何时同步。AOF的实时性更好,但如果选择每次修改都写入时,可能会降低redis的性能;建议选择每秒同步一次,这样Redis 性能几乎没受到任何影响。而且这样即使出现系统崩溃,用户最多只会丢失一秒之内产生的数据。

AOF的缺点是,AOF文件的大小远远大于 数据文件,AOF的修复速度也比数据文件慢!

2.3 Redis 的事务【重要】

Redis事务的简单理解就是将多个命令打包、放入一个队列中、然后一起执行所有命令。因为某条命令执行失败不会影响其他命令,所以Redis的事务严格来说并不是原子性的。

Redis 可以通过 MULTIEXECDISCARDWATCH 等命令来实现事务(transaction)功能。

  • 使用 MULTI命令后可以输入多个命令。Redis 不会立即执行这些命令,而是将它们放到队列,当调用了EXEC命令将执行所有命令。
  • 你也可以通过 DISCARD 命令取消一个事务,它会清空事务队列中保存的所有命令。
  • WATCH 命令用于监听指定的键,当调用 EXEC 命令执行事务时,如果一个被 WATCH 命令监视的键被修改的话(在本事务外被修改),整个事务都不会执行,直接返回失败。

Redis事务之所以不支持回滚(以实现原子性)是因为认为错误的指令应该在开发过程就发现,而不应该出现在生产环境中。因为不用支持回滚、Redis的设计可以保持简单和高效。Watch命令的监视功能类似于乐观锁,发现了key被其他事务修改之后,可以是队列中后面的命令失效。

2.4 Redis单线程【略重要】

1 Redis为何选择单线程?【重要】

Redis6.0引入多线程I/O,只是用来处理网络数据的读写和协议的解析,而执行命令依旧是单线程。

在Redis 6.0以前,Redis的核心网络模型选择用单线程来实现。简单的原因就是大多数请求都是 I/O 密集型的,而不会是 CPU 密集型的。Redis的执行速度是非常快的,Redis真正的性能瓶颈常常在于网络 I/O,因此Redis选择了单线程的 I/O 多路复用来实现它的核心网络模型。(多路复用思想也存在于http2.0中)

主要的原因还包括:

  • 单线程避免过多的上下文切换开销

  • 避免数据同步机制的开销

  • 简单可维护

总而言之,Redis选择单线程可以说是一种权衡的选择:在保证足够的性能的前提下,使用单线程保持代码的简单和可维护性。

2 Redis6.0又支持多线程主要原因:

  • 可以充分利用服务器 CPU 资源,目前主线程只能利用一个核(单线程浪费了cpu等待网络IO的时间)
  • 多线程任务可以分摊 Redis 同步 IO 读写负荷

3 IO 多路复用机制【了解】

多个 socket 会产生不同的事件,不同的事件对应着不同的操作,IO 多路复用程序监听着这些 Socket,当这些 Socket 产生了事件,IO 多路复用程序会将这些事件放到一个队列中,通过这个队列,以有序、同步、每次一个事件的方式向文件时间分派器中传送。当事件处理器处理完一个事件后,IO 多路复用程序才会继续向文件分派器传送下一个事件。

3 Redis 缓存可能带来的问题及解决

使用redis可能带来的问题:过期key删除、缓存淘汰策略、缓存一致性、缓存穿透、缓存雪崩。

1 使用缓存、缓存的容量是有限的,如果使缓存中始终存“热点的数据”,这是首先要考虑的。也就是放什么样的数据到缓存中、以及如何淘汰数据(淘汰策略)

2 缓存和数据库存在着一个同步的问题,如何保证缓存一致性(读写顺序!!)

3 某些极端的攻击,引发的缓存穿透、缓存雪崩问题应该如何解决

3.1 Redis过期键的删除策略

通过expire或pexpire命令,客户端可以以秒或毫秒的精度为数据库中的某个键设置生存时间。

Redis的过期删除策略就是:惰性删除和定期删除两种策略配合使用。

1、惰性删除

设置该key 过期时间后,我们不去管它,当需要该key时,我们在检查其是否过期,如果过期,我们就删掉它,反之返回该key。

优点:对 CPU友好,只会在使用该键时才会进行过期检查

缺点:对内存不友好,不用的键就会一直存在内存中

2、定期删除

每隔一段时间,我们就对一些key进行检查,删除里面过期的key。

优点:对CPU和内存都友好

缺点:难以确定删除操作执行的时长和频率。可能出现过期了还没有被删除的问题。

3.2 Redis缓存淘汰策略【略重要】

设置了过期时间的数据由过期键的删除策略负责删除(也可以通过淘汰策略)

如果没有设置过期时间的数据(很多),通过淘汰策略来删除。当Redis的内存超过最大允许的内存之后,Redis会触发内存淘汰策略,删除一些不常用的数据

Redisv4.0前提供 6种数据淘汰策略

  • volatile-lru:利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used )
  • volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰
  • volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰
  • allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key(这个是最常用的
  • allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰
  • no-eviction:禁止驱逐数据,也就是说当内存不足以容纳新写入数据时,新写入操作会报错。这个应该没人使用吧!【居然是默认】

Redisv4.0后增加以下两种

  • volatile-lfu:从已设置过期时间的数据集(server.db[i].expires)中挑选最不经常使用的数据淘汰(LFU(Least Frequently Used)算法,也就是最频繁被访问的数据将来最有可能被访问到)
  • allkeys-lfu:当内存不足以容纳新写入数据时,在键空间中,移除最不经常使用的key。

3.3 缓存不一致问题及解决

缓存不一致问题一般出现于要更新数据库的时候。处理缓存不一致问题主要有两种方案:

1 先删除缓存,后更新数据库

2 先更新数据库,后删除缓存

其他的方案诸如: 先更新数据库在更新缓存,并发会有脏数据进缓存。 先更新缓存在更新数据库,可能更缓存成功、更数据库失败照成不一致问题。

1 先删除缓存,后更新数据库

该方案也会出问题,此时来了两个请求,请求 A(更新操作) 和请求 B(查询操作)

  1. 请求A进行写操作,删除缓存
  2. 请求B查询发现缓存不存在
  3. 请求B去数据库查询得到旧值
  4. 请求B将旧值写入缓存
  5. 请求A将新值写入数据库

就是查询操作B可能将数据库中旧值更新到缓存中,照成缓存不一致

解决办法就是“延时双删”,步骤如下(就是两次删除一次更新、更新后记得延时一下)

1
2
3
1)先淘汰缓存 
2)再写数据库(这两步和原来一样)
3)休眠1秒,再次淘汰缓存

这么做,可以将1秒内所造成的缓存脏数据,再次删除。确保读请求B结束后,写请求A可以删除读请求造成的缓存脏数据。

2 先更新数据库,后删除缓存

这一种情况也会出现问题,比如更新数据库成功了,但是在删除缓存的阶段出错了没有删除成功,那么此时再读取缓存的时候每次都是错误的数据了。

解决办法是利用消息队列,确保消息操作能够可靠的被消费。

1
2
3
4
1 请求 A 先对数据库进行更新操作
2 在对 Redis 进行删除操作的时候发现报错,删除失败
3 此时将Redis 的 key 作为消息体发送到消息队列中
4 系统接收到消息队列发送的消息后再次对 Redis 进行删除操作

3.4 缓存穿透的问题及解决【重要】

缓存穿透是指用户请求的数据在缓存中不存在即没有命中,同时在数据库中也不存在,导致用户每次请求该数据都要去数据库中查询一遍。如果有恶意攻击者不断请求系统中不存在的数据,会导致短时间大量请求落在数据库上,造成数据库压力过大,甚至导致数据库承受不住而宕机崩溃。

image-20210707115232430

解决缓存穿透问题,最基本的就是首先做好参数校验,一些不合法的参数请求直接抛出异常信息返回给客户端。

解决方法:除了基本的参数校验方法外,还有缓存无效key和布隆过滤器

1 缓存无效key(将无效的key缓存到redis中)

当出现Redis查不到数据,数据库也查不到数据的情况,我们就把这个key保存到Redis中,设置value=”null”,并设置其过期时间极短,后面再出现查询这个key的请求的时候,直接返回null,就不需要再查询数据库了。这种方式可以解决请求的 key 变化不频繁的情况。(当key变化频繁时无法解决问题)

2 布隆过滤器(就是多加一层布隆过滤器的判断,不在布隆过滤器中就直接返回null)

布隆过滤器是一个非常神奇的数据结构,通过它我们可以非常方便地判断一个给定数据是否存在于海量数据中。

具体是这样做的:把所有可能存在的请求的值都存放在布隆过滤器中,当用户请求过来,先判断用户发来的请求的值是否存在于布隆过滤器中。不存在的话,直接返回请求参数错误信息给客户端,存在的话才会走下面的流程。

布隆过滤器可能出现小概率的误判的情况。总结来说就是: 布隆过滤器说某个元素存在,小概率会误判。布隆过滤器说某个元素不在,那么这个元素一定不在。

布隆过滤器的原理是根据哈希函数对是元素值进行计算,映射到数组中来判断是否存在。

3.5 缓存雪崩的问题及解决【重要】

缓存在同一时间大面积的失效,后面的请求都直接落到了数据库上,造成数据库短时间内承受大量请求。可能导致宕机。

缓存雪崩的原因

  • 系统的缓存模块出了问题比如宕机导致不可用。造成系统的所有访问,都要走数据库。
  • 有一些被大量访问数据(热点缓存)在某一时刻大面积失效,导致对应的请求直接落到了数据库上。

缓存雪崩的解决办法:

  • 针对 Redis 服务不可用的情况:

    • 采用 Redis 集群,避免单机出现问题整个缓存服务都没办法使用。
    • 限流,避免同时处理大量的请求。
  • 针对热点缓存失效的情况:

    • 设置不同的失效时间比如随机设置缓存的失效时间。
    • 缓存永不失效。

4 Redis的主从、哨兵、集群

Redis的应用模式比如主从复制、哨兵模式、redis集群。。感觉这部分比较难

主从复制原理?

被选举为master的标准?

集群是如何实现数据分布的?优点

集群的通信机制

4.1 主从复制架构

Redis主从复制是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(Master/Leader),后者称为从节点(Slave/Follower)。

主从机的特点:

  • 主机可以写,从机不能写只能读!主机中的所有信息和数据,都会自动在从机中保存!

  • 主机断开连接,从机依旧连接到主机的。主机后面如果回来了,从机依旧可以直接获取到该主机写的信息!

  • 如果从机重启了(命令行来配置的主从的情况),就会变回主机(默认)!只要(重新设置)变为从机,立马就会从主机中获取值!

    • 只要是重新连接master,一次完全同步(全量复制)将被自动执行!

复制原理:

Slave 启动成功连接到 master 后会发送一个sync同步命令。Master 接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后,master将传送整个数据文件到slave,并完成一次完全同步。

  • 全量复制:(全部复制)
  • 增量复制:(复制更新的部分)

缺点:

如果主机因为故障断开了连接,我们只能手动配置主机、从机。升级为哨兵模式就是为了解决这个问题,实现自动配置主从!!

4.2 哨兵模式架构

主机故障之后,自主配置新主机从机!!

哨兵模式能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。哨兵是一个独立的进程,作为进程,它会独立运行。

==其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。==

优点:

  1. 哨兵集群,基于主从复制模式,所有的主从配置优点,它全有
  2. 主从可以切换,故障可以转移,系统的可用性就会更好
  3. 哨兵模式就是主从模式的升级,手动到自动,更加健壮!

缺点:

  1. Redis 不好线扩容的,集群容量一旦到达上限,在线扩容就十分麻烦!
  2. 实现哨兵模式的配置其实是很麻烦的,实现起来相对复杂!

4.3 Redis集群架构(Redis Cluster)

哨兵模式虽然已经高可用了,但是备份太多相同的数据,是浪费内存的操作。

Cluster 集群模式,实现了 Redis 的分布式存储,对数据进行分片,也就是说每台 Redis 节点上存储不同的内容。(也能够缓解内存数据库不能存海量数据的缺点)

Redis Cluster集群节点最小配置6个节点以上(3主3从),其中主节点提供读写操作,从节点作为备用节点,不提供请求,只作为故障转移使用。

Redis Cluster采用虚拟槽分区,所有的键根据哈希函数映射到0~16383个整数槽内,每个节点负责维护一部分槽以及槽所印映射的键值数据。

优点:

  • 无中心架构;
  • 可扩展性:可线性扩展到1000多个节点,节点可动态添加或删除;
  • 高可用性:部分节点不可用时,集群仍可用。通过增加Slave做standby数据副本,能够实现故障自动failover,节点之间通过gossip协议交换状态信息,用投票机制完成Slave到Master的角色提升;
  • 降低运维成本,提高系统的扩展性和可用性。

缺点(缺点也有很多):

  • Client实现复杂
  • 数据通过异步复制,不保证数据的强一致性。
  • 多个业务使用同一套集群时,无法根据统计区分冷热数据,资源隔离性较差,容易出现相互影响的情况。
  • Slave在集群中充当“冷备”,不能缓解读压力
  • Key批量操作限制,如使用mset、mget目前只支持具有相同slot值的Key执行批量操作。
  • Key事务操作支持有限,只支持多key在同一节点上的事务操作,当多个Key分布于不同的节点上时无法使用事务功能。
  • Key作为数据分区的最小粒度,不能将一个很大的键值对象如hash、list等映射到不同的节点。
  • 不支持多数据库空间,单机下的Redis可以支持到16个数据库,集群模式下只能使用1个数据库空间,即db 0。

4.4 几个常问的问题【重要】

1 Redis哨兵是怎么工作的?主观下线、客观下线

  • 每个Sentinel以每秒钟一次的频率向它所知的Master,Slave以及其他 Sentinel 实例发送一个 PING 命令。如果监测到某个Master回复时间超过指定的值,就认为这个Master宕机了,标记为主观下线的状态
  • 其他Sentinel发送命令确认这个Master是否真的进入了宕机状态。如果有足够多的Sentinel认为这个Master确实主观下线了,那么Master会被标记为客观下线
  • 足够多的Sentinel同意Master客观下线之后,就会相互沟通,从选举出一个从节点作为新的Master。其他从节点转移到这个新的主节点上来。

2 新被选举为master的标准是什么?

  • 跟master断开连接的时长。 如果一个slave跟master断开连接已经超过了down-after-milliseconds的10倍,外加master宕机的时长,那么slave就被认为不适合选举为master.

  • slave优先级。 按照slave优先级进行排序,slave priority越低,优先级就越高

  • 复制offset。 如果slave priority相同,那么看replica offset,哪个slave复制了越多的数据,优先级就越高

  • run id 如果上面两个条件都相同,那么选择一个run id比较小的那个slave。

5 Redis的其他问题(优化)

1 Redis如何做内存优化?

  • 控制key的数量。当使用Redis存储大量数据时,通常会存在大量键,过多的键同样会消耗大量内存。Redis本质是一个数据结构服务器,它为我们提供多种数据结构,如hash,list,set,zset 等结构。使用Redis时不要进入一个误区,大量使用get/set这样的API,把Redis当成Memcached使用。对于存储相同的数据内容利用Redis的数据结构降低外层键的数量,也可以节省大量内存。
  • 缩减键值对象,降低Redis内存使用最直接的方式就是缩减键(key)和值(value)的长度。
    • key长度:如在设计键时,在完整描述业务情况下,键值越短越好。
    • value长度:值对象缩减比较复杂,常见需求是把业务对象序列化成二进制数组放入Redis。首先应该在业务上精简业务对象,去掉不必要的属性避免存储无效数据。其次在序列化工具选择上,应该选择更高效的序列化工具来降低字节数组大小。

2 如果现在有个读超高并发的系统,用Redis来抗住大部分读请求,你会怎么设计?

如果是读高并发的话,先看读并发的数量级是多少,因为Redis单机的读QPS在万级,每秒几万没问题,使用一主多从+哨兵集群的缓存架构来承载每秒10W+的读并发,主从复制,读写分离。

使用哨兵集群主要是提高缓存架构的可用性,解决单点故障问题。主库负责写,多个从库负责读,支持水平扩容,根据读请求的QPS来决定加多少个Redis从实例。如果读并发继续增加的话,只需要增加Redis从实例就行了。

如果需要缓存1T+的数据,选择Redis cluster模式,每个主节点存一部分数据,假设一个master存32G,那只需要n*32G>=1T,n个这样的master节点就可以支持1T+的海量数据的存储了。

Redis单主的瓶颈不在于读写的并发,而在于内存容量,即使是一主多从也是不能解决该问题,因为一主多从架构下,多个slave的数据和master的完全一样。假如master是10G那slave也只能存10G数据。所以数据量受单主的影响。 而这个时候又需要缓存海量数据,那就必须得有多主了,并且多个主保存的数据还不能一样。Redis官方给出的 Redis cluster 模式完美的解决了这个问题。

-------------感谢阅读没事常来-------------