Redis相关知识点整理
1、Redis是什么?
在web应用发展的初期,关系型数据库倍受关注。因为当时的web站点访问量和并发量不高,交互少。在后来随着访问量的提升,使用关系型数据库的web站点都开始在性能上出现瓶颈。而这个瓶颈的源头都是在磁盘的读写上。磁盘的读写速度速度比起高并发业务下的访问量来说要慢的多,而对着互联网的发展,导致对web应用的性能有了更高的需求,主要体现在:
- 低延迟的读写速度:应用可以快速反应用户的请求
- 支持海量的数据和流量:对于搜索这样的大型应用而言,需要利用PB级别的数据和应对百万级别的流量
- 大规模的集群管理:系统管理员希望分布式应用能更简单的部署和管理
- 庞大运营成本的考量:系统管理员希望分布式应用能简单的部署和管理
为了克服这一问题,NoSQL应运而生,同时以高性能,可扩展性强,高可用等优点广泛受到开发人员和仓库管理人员的青睐。
Redis是什么?Redis是现在最受欢迎的NoSQL数据库之一,Redis是一个使用ANSIC编码的开源数据库,包含多种数据结构,支持网络,基于内存,可选持久性的键值对存储数据库,特性:
- 基于内存运行,性能高效
- 支持分布式,理论上可以无限扩展
- key-value存储系统
- ...
相对于其他数据库类型,Redis具备的特点是:
- 操作具有原子性
- 持久化
- 高并发读写
2、Redis的应用场景
- Redis的应用场景包括:缓存系统(热点数据,高频读,低频写),计数器。消息队列系统,排行榜,社交网络和实时系统
3、Redis的数据类型和主要特性
- Redis提供的数据类型包括五种自由类型和一种自定义类型,这5种自有类型包括:Stirng类型,哈希类型,列表类型,集合类型,和顺序集合类型。
- String类型:它是一个二进制安全的字符串,意味着它不仅能存储字符串,还能存储图片视频等多种类型,最大长度支持521M
- Hash类型:该类型是有field和关联的value组成的map。其中,field和value都是字符串类型的。
- 列表类型:该类型是一个插入顺序排序的字符串元素集合,基于双链表实现
- Set集合类型:是一种无顺序的集合,List是有序的且唯一
- 顺序集合类型:zset是一种有序集合类型,每个元素都会关联一个double类型的分数权值,通过这个权值可以为集合中的成员进行从小到大的排序,与set类型一样,其底层也是通过这个哈希表实现的
4、Redis简单动态字符串
基于c语言中传统字符串的缺陷,Redis自己构建了一种名为简单动态字符串的抽象类型,SDS几乎贯穿了Redis的所有数据结构。
5、事务
Redis本身的每条语句是原子性的,而且对多个语句提供了事务的支持。
- 命令序列化
- 原子性
- 三阶段:开始事务-命令入队-执行事务
6、Redis常见的问题-击穿
- 什么叫缓存的击穿:当Redis获取某一个key时,由于key不存在,而必须向DB发起一次请求的行为,叫做Redis击穿
引发击穿的原因:
- 第一次访问
- 恶意访问不存在的key
- key过期
合理的规避方案
- 服务器启动时提前进行写入
- 规范key的命名,通过中间件拦截
- 对于高频访问的key,设置合理的TTL或永不过期
7、Redis常见的问题-雪崩
- 什么叫缓存的雪崩:Redis缓存层由于某种原因宕机后,所有的请求会涌向存储层,短时间内的高并发会导致存储层挂机,称之为Redis雪崩
合理的规避方案:
- 使用Redis集群
- 限流
8、除Redis之外还有什么NoSQL型数据库
MemCache
- 是一个与Redis非常相似的数据库,但是他的数据结构没有Redis丰富。是一个分布式的告诉缓存系统,被许多网站用于提升网站的访问速度,对于一些大型的需要被频繁访问数据库的网站访问速度提升十分显著
- Mongo
9、Redis集群
- Redis集群有三种集群模式,分别是主从模式,Sentinel模式,Cluster模式
10、主从模式
主从模式是三种模式中最简单的一种,在主从赋值中,数据库分为两类,主数据库和从数据库(master和slave),特点有:
- 主数据库可以进行读写操作,当读写操作导致数据变化后会自动将数据同步给从数据库
- 从数据库一般都是只读的,并且只接受从主数据库同步过来的数据
- 一个master可以拥有多个slave,一个slave只能有一个master
- slave挂了不影响其他slave的读和master的读和写,重新启动后将数据从master中同步过来
- master挂掉之后,不影响算啦测的读,但是redis不再提供写服务,master重启后会重新对外提供
- master挂了之后,不会在slave中选一个master
工作机制:
- 当slave启动后,主动向master发送SYNC命令。master接收到SYNC命令后在后台保存快照(RDB持久化),和缓存保存快照这段时间的命令,然后将保存的快照文件和缓存的命令发送给slave,slave接受到快照文件和命令后会加载快照文件和缓存的执行命令
- 复制初始化之后,master每次接受到的写命令都会同步发送给slave,保证主从数据一致。
安全设置:
- 当master设置密码后,客户端访问master需要密码,启动slave需要密码,在配置文件中配置即可,客户端访问slave不需要密码
- 、缺点:从上面可以看出,master节点在主从模式中唯一,若master挂掉,则redis无法对外提供写服务
- 主从模式的搭建
11、Sentinel模式(哨兵模式)
- 主从模式的弊端就是不具备高可用性,当主机挂掉之后,Redis不再对外提供写入操作,因此哨兵机制由此而生
哨兵就是用来监控redis集群的状况,特点如下
- 哨兵模式是建立在主从模式的基础上,如果只有一个redis节点,哨兵机制就没有任何意义
- 当master挂掉之后,哨兵会在slave中选择额一个阶段作为master,并自动修改他们的配置文件,其他slave节点的属性会被修改,至少slaveof属性会更新
- 当master启动之后,它将不再是master而是作为slave接收新的master同步数据
- 哨兵机制因为也是一个进程,也有挂掉的时候,所以sentinel也会启动多个形成一个sentinel集群
- 当多个sentinel配置的时候,他们之间也会互相监控
- 当主从模式配置密码时,sentinel也会同步将配置信息修改到配置文件中,不需要担心
- 一个sentinel或sentinel集群可以管理多个主从redis,多个sentinel也可以监控同一个redis
- sentinel最好不要和redis部署在同一台机器上,不然redis服务器挂掉之后,sentinel也挂了
工作机制
- 每个sentinel以每秒钟一次的频率向他所知的master及其他sentinel实例发送一个PING命令
- 如果一个实例距离最后一次有效回复PING的命令时间超过down-after-milliseconds 选项所指定的值,这个实例会被sentinel标记为主观下线(就是,我每秒钟会叫你一次,设定一个时间,若这个时间内你还没有回复我,则我认为你已经死了)
- 如果一个master被标记为主观下线,则正在监视这个master的所有sentinel会每秒一次的频率确定master的确进入了主观下线状态
- 当有足够数量的sentinel(大于等于配置文件指定的值)则在指定的时间范围内认为master的确进入的主观下线的状态,会被标记为客观下线(我叫你不回答,其他人叫你也不回答,则由可能宕机状态变为客观上的宕机状态)
- 在一般情况下,没个sentinel会以每10s一次的评率向它一直的所有master,slave发送INFO命令
- 当master被sentinel标记为客观下线时,sentinel向下线的master的所有slave发送INFO的评率会从10s一次转换成1s一次
- 若没有足够数量的sentinel同意master已经下线,master的下线状态就会移除,这个时候若master向sentinel的PING命令就有返回值,master的主观下线状态就会被移除
当使用sentinel模式的时候,客户端就不用直接连接redis,而是连接sentinel中的ip和port,由sentinel来提供具体的可提供服务的redis实现,这样当master节点挂掉之后,sentinel就会感知,并将新的节点告知使用者.之后即使原来的节点重启,也只能作为slave节点.
12、Cluster模式
- sentinel模式可以满足一般的生产需求,具备高可用性,但是当数据量过大到一台服务器放不下的情况时,主从模式或者哨兵模式就不能满足需求了,这个时候需要对数据的存储进行分片,将数据存储到多个redis实例中,cluster模式的出现就是为了解决单机redis容量有限的问题,所以redis的数据根据一定的队则分配到多个机器上
- cluster可以说是sentinel模式和主从模式的结合体,通过cluster可以实现主从和master重选功能,如果配置两个副本和三个分片的话,就需要六个redis实例,因为redis的数据是根据一定的规则分配到cluster的不同机器的,当数据量过大时,可以新增机器进行扩容
- 使用集群,只需要将redis配置文件中的cluster-enable配置打开即可,每个集群中至少需要三个主数据库才能正常运行,性增节点也非常方便
cluster集群的特点
- 多个redis节点网络互联,数据共享
- 所有的节点都是一主一从(也可以是一主多从)其中从库不提供服务,仅作为备用
- 不支持同时处理多个key,因为redis需要将key均匀的分布在每个节点上,并发量很高的情况下同时创建key-value会降低性能并导致不可预测的行为
- 支持在线增加和删除节点
- 客户端可以连接任何一个主节点进行读写
- redis-cluster是去中心化的,连接哪个节点都可以获取数据和设置数据(主节点),从节点只是作为备份存在,一般不提供服务
注:redis-cluster是redis的分布式解决方案,有效的解决了redis分布式方面的需求,redis-cluster一般由多个节点组成,节点数量至少为6个才能保证组成完整高可用集群.其中,三个主节点,三个从节点,单个主节点会分配槽,处理客户端的命令请求,而从节点会在主节点故障之后,顶替主节点
13、数据分片策略
- 分布式存储方案中最重要的一点就是数据分片,shading
- 为了使得集群能够水平扩展,首要解决的问题就是如何将整个数据集按照一定的规则分配到多个节点上,长用的数据分片方法有:范围分片,哈希分片,一致性哈希算法和虚拟哈希槽
- 范围分片:范围分片假设数据是有序,将顺序相临近的数据放在一起,可以很好的支持变俩操作,这种分片模式的缺点是按照顺序写的时候会存在热点(即缓存在同一个片上),当日志在写入的时候,一般的日志都是按照时间排序的,这个时候时间是单调递增的,这个时候写入的热点永远在最后一个分片上。
- redis-cluster采用哈希槽分区,所有的键根据哈希函数映射到0-16383个整数槽内,计算公式slot=CRC16(KEY) & 16383.每一个节点负责维护一部分槽及所映射的键值数据
虚拟槽分区的特点
- 解耦数据和槽之间的关系,简化了节点的扩容和收缩难度
- 节点自身维护槽的映射关系,不需要客户端或代理服务器维护槽分区的元数据
- 支持节点,槽和键之间的映射查询
14、集群扩容
- 当一个 Redis 新节点运行并加入现有集群后,我们需要为其迁移槽和数据。首先要为新节点指定槽的迁移计划,确保迁移后每个节点负责相似数量的槽,从而保证这些节点的数据均匀。
- 首先启动一个 Redis 节点,记为 M4。
- 使用 cluster meet 命令,让新 Redis 节点加入到集群中。新节点刚开始都是主节点状态,由于没有负责的>槽,所以不能接受任何读写操作,后续我们就给他迁移槽和填充数据。
- 对 M4 节点发送 cluster setslot { slot } importing { sourceNodeId } 命令,让目标节点准备导入槽的数据。 >4) 对源节点,也就是 M1,M2,M3 节点发送 cluster setslot { slot } migrating { targetNodeId } 命令,让源节>点准备迁出槽的数据。
- 源节点执行 cluster getkeysinslot { slot } { count } 命令,获取 count 个属于槽 { slot } 的键,然后执行步骤>六的操作进行迁移键值数据。
- 在源节点上执行 migrate { targetNodeIp} " " 0 { timeout } keys { key... } 命令,把获取的键通过 pipeline 机制>批量迁移到目标节点,批量迁移版本的 migrate 命令在 Redis 3.0.6 以上版本提供。
- 重复执行步骤 5 和步骤 6 直到槽下所有的键值数据迁移到目标节点。
- 向集群内所有主节点发送 cluster setslot { slot } node { targetNodeId } 命令,通知槽分配给目标节点。为了>保证槽节点映射变更及时传播,需要遍历发送给所有主节点更新被迁移的槽执行新节点。
15、收缩集群
收缩节点就是将 Redis 节点下线,整个流程需要如下操作流程。
- 首先需要确认下线节点是否有负责的槽,如果是,需要把槽迁移到其他节点,保证节点下线后整个集群槽节点映射的完整性。
- 当下线节点不再负责槽或者本身是从节点时,就可以通知集群内其他节点忘记下线节点,当所有的节点忘记改节点后可以正常关闭。
- 下线节点需要将节点自己负责的槽迁移到其他节点,原理与之前节点扩容的迁移槽过程一致。
- 迁移完槽后,还需要通知集群内所有节点忘记下线的节点,也就是说让其他节点不再与要下线的节点进行 Gossip 消息交换。
- Redis 集群使用 cluster forget { downNodeId } 命令来讲指定的节点加入到禁用列表中,在禁用列表内的节点不再发送 Gossip 消息。
16、故障转移
- 当 Redis 集群内少量节点出现故障时通过自动故障转移保证集群可以正常对外提供服务。
- 当某一个 Redis 节点客观下线时,Redis 集群会从其从节点中通过选主选出一个替代它,从而保证集群的高可用性。这块内容并不是本文的核心内容,感兴趣的同学可以自己学习。
- 但是,有一点要注意。默认情况下,当集群 16384 个槽任何一个没有指派到节点时整个集群不可用。执行任何键命令返回 CLUSTERDOWN Hash slot not served 命令。当持有槽的主节点下线时,从故障发现到自动完成转移期间整个集群是不可用状态,对于大多数业务无法忍受这情况,因此建议将参数 cluster-require-full-coverage 配置为 no ,当主节点故障时只影响它负责槽的相关命令执行,不会影响其他主节点的可用性。
参考文章:
https://www.jianshu.com/p/0a8...
https://blog.csdn.net/miss118...
https://www.cnblogs.com/power...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。