首页天道酬勤redis集群高并发读取(redis高并发读写)

redis集群高并发读取(redis高并发读写)

admin 12-03 20:42 440次浏览

00-1010缓存架构技术:Redis MongDB,阿里P7面试必跳。美团酷:MySQL Java Redis算法网络Linux等。我说不清楚

00-1010作为一名Java程序员,在面试过程中,缓存相关的问题是无法避免的,我一定会问他们,比如缓存一致性、缓存雪崩、击穿穿透等。说到缓存,Redis是不可或缺的。面试的时候也被问到了很多关于Redis的知识,但是Redis的功能太强大了,一时半会儿也掌握不了,因为一些高级的功能或者知识一般都用不到。

因此,如果你不给出一个好的答案,人们会认为你不知道你通常使用的工具,自然会很酷。其实我早就有这个打算,打算总结一下Redis的知识,也是因为对Redis没有很好的了解,所以一直没有开始。准备这次慢慢总结。

推荐学习

Redis是用C语言编写的开源NoSQL数据库,基于内存,支持各种数据结构进行持久化。它快速的原因有几个:

基于内存的高性能操作;数据结构设计高效,比如String由动态字符数组组成,zset内部的跳转表;采用单线程,避免了线程的上下文切换和线程竞争导致的死锁。采用I/O复用模式,无阻塞IO;官网显示,单个Redis的QPS可以达到10w,在一台服务器上使用Redis,单核就足够了。但是目前服务器都是多核CPU,想要不浪费资源,提高效率,可以在一台服务器上部署多个Redis实例。

00-1010虽然单个Redis的性能很好,但是Redis的单个节点不能保证不会挂机。毕竟单个节点的Redis是有上限的,人们要在单个节点上读写,所以无法处理,所以为了保证高可用性,通常会做成集群。

前言

Redis官方支持主从同步,也支持从同步。从同步也可以理解为主从同步,只是从同步的主节点是主从的另一个从节点。

对于主从同步集群,主节点负责提供写操作,而从节点负责支持读操作。

00-1010如果从节点第一次与主节点连接,

然后是同步请求psync将首先发送给主服务器;主节点接收同步请求,启动fork主子进程开始完全同步,然后生成RDB文件;此时,主节点还会将新的写请求保存到缓冲区中。从节点接收到RDB文件后,首先清除旧数据,然后将RDB中的数据加载到内存中;等到从节点同步RDB文件后,再同步缓冲区中的写请求。这里需要注意的一点是,主节点的缓冲区是有限的,内部结构是一个循环数组,当数组满的时候会覆盖最早的数据。

因此,如果缓冲区中的数据由于网络或其他原因被覆盖,那么在从节点完成处理主节点的RDB文件之后,它必须制作RDB文件的完整副本,以确保主节点和从节点之间的数据一致性。

如果不设置合理的缓冲空间,就会造成RDB复制的无限循环。

当主从之间的数据同步完成后,后续主节点的每次写操作都会同步到从节点,从而进行增量同步。

随着负载不断上升,主从之间的延迟变大,因此出现了上述的从同步。主节点首先同步到一些从节点,然后从节点同步其他从节点。

从Redis中的2.8.18开始,支持无盘复制。主节点遍历内存中的数据,并通过套接字将数据发送给从节点。像以前一样,从节点首先将数据存储在磁盘文件中,然后一次加载它。

"text-align: left">另外由于主从同步是异步的,所以从Redis3.0之后出现了同步复制,就是通过wait命令来进行控制,wait命令有两个参数,第一个是从库数量,第二个是等待从库的复制时间,如果第二个参数设置为0,那么就是代表要等待所有从库都复制完才去执行后面的命令。但是这样就会存在一个隐患,当网络异常后,wait命令会一直阻塞下去,导致Redis不可用。

dldzp(Sentinel)

dldzp可以监控Redis集群的健康状态,当主节点挂掉之后,选举出新的主节点。客户端在使用Redis的时候会先通过Sentinel来获取主节点地址,然后再通过主节点来进行数据交互。当主节点挂掉之后,客户端会再次向Sentinel获取主节点,这样客户端就可以无感知地继续使用了。

dldzp集群工作过程,主节点挂掉之后会选举出新的主节点,然后监控挂掉的节点,当挂掉的节点恢复后,原先的主节点就会变成从节点,从新的主节点那里建立主从关系。

集群分片(Redis Cluster)

Redis Cluster是Redis官方推荐的集群模式,Redis Cluster将所有数据划分到16384个槽(slots)中,每个节点负责一部分槽位的读写操作。

存储

Redis Cluster默认是通过CRC16算法获取到key的hash值,然后再对16384进行取余(CRC16(key)%16384),获取到的槽位在哪个节点负责的范围内(这里一般是会有一个槽位和节点的映射表来进行快速定位节点的,通常使用bitmap来实现),就存储在哪个节点上。

重定向

当Redis Cluster的客户端在和集群建立连接的时候,也会获得一份槽位和节点的配置关系(槽位和节点的映射表),这样当客户端要查找某个key时,可以直接定位到目标节点。

但是当客户端发送请求时,如果接收请求的节点发现该数据的槽位并不在当前节点上,那么会返回MOVED指令将正确的槽位和节点信息返回给客户端,客户接着请求正确的节点获取数据。

一般客户端在接收到MOVED指令后,也会更新自己本地的槽位和节点的映射表,这样下次获取数据时就可以直接命中了。这整个重定向的过程对客户端是透明的。

数据迁移

当集群中新增节点或删除节点后,节点间的数据迁移是按槽位为单位的,一个槽位一个槽位的迁移,当迁移时原节点状态处于:magrating,目标节点处于:importing。

在迁移过程中,客户端首先访问旧节点,如果数据还在旧节点,那么旧节点正常处理,如果不在旧节点,就会返回一个-ASK + 目标节点地址的指令,客户端收到这个-ASK指令后,向目标节点执行一个asking指令(告诉新节点,必须处理客户端这个数据),然后再向目标节点执行客户端的访问数据的指令。

容错

Redis Cluster可以为每个主节点设置多个从节点,当单个主节点挂掉后,集群会自动将其中某个从节点提升为主节点,若没有从节点,那么集群将处于不可用状态。Redis提供了一个参数:cluster-require-full-coverage,用来配置可以允许部分节点出问题后,还有其他节点在运行时可以正常提供服务。

另外一点比较特殊的是,Cluster中当一个节点发现某个其他节点出现失联了,这个时候问题节点只是PFail(Possibly-可能下线),然后它会把这个失联信息广播给其他节点,当一个节点接收到某个节点的失联信息达到集群的大多数时,就可以将失联节点标记为下线,然后将下线信息广播给其他节点。若失联节点为主节点,那么将立即对该节点进行主从切换。

Redis高可用就先说到这里吧,后面其实还有Codis,但是目前Cluster逐渐流行起来了,Codis的竞争力逐渐被蚕食,而且对新版本的支持,更新的也比较慢,所以这里就不说它了,感兴趣的可以自己去了解一下,国人开源的Redis集群模式Codis。

持久化

Redis持久化的意义在于,当出现宕机问题后,能将数据恢复到缓存中,它提供了两种持久化机制:一种是快照(RDB),一种是AOF日志。

快照是一次全量备份,而AOF是增量备份。快照是内存数据的二进制序列化形式,存储上非常紧凑,而AOF日志记录的是内存数据修改的指令记录文本。

快照备份(RDB)

因为Redis是单线程的,所以在做快照持久化的时候,通常有两个选择,save命令,会阻塞线程,直到备份完成;bgsave会异步的执行备份,其实是fork出了一个子进程,用子进程去执行快照持久化操作,将数据保存在一个.rdb文件中。

子进程刚刚产生的时候,是和父进程共享内存中的数据的,但是子进程做持久化时,是不会修改数据的,而父进程是要持续提供服务的,所以父进程就会持续的修改内存中的数据,这个时候父进程就会将内存中的数据,Copy出一份来进行修改。

父进程copy的数据是以数据页为单位的(4k一页),对那一页数据进行修改就copy哪一页的数据。

子进程由于数据没有变化就会一直地去遍历数据,进程持久化操作了,这就是只保留了创建子进程的时候的快照。

那么RDB是在什么时候触发的呢?

# save <seconds> <changes> save 60 10000 save 300 10

上这段配置就是在redis.conf文件中配置的,第一个参数是时间单位是秒,第二个参数执行数据变化的次数。意思就是说:300秒之内至少发生10次写操作、60秒之内发生至少10000次写操作,只要满足任一条件,均会触发bgsave

增量日志备份(AOF)

Redis在接收到客户端请求指令后,会先进行校验,校验成功后,立即将指令存储到AOF日志文件中,就是说,Redis是先记录日志,再执行命令。这样即使命令还没执行突然宕机了,通过AOF日志文件也是可以恢复的。

AOF重写

AOF日志文件,随着时间的推移,会越来越大,所以就需要进行重写瘦身。AOF重写的原理就是,fork一个子进程,对内存进行遍历,然后生成一系列的Redis指令,然后序列化到一个新的aof文件中。然后再将遍历内存阶段的增量日志,追加到新的aof文件中,追加完成后立即替换旧的aof文件,这样就完成了AOF的瘦身重写。

fsync

因为AOF是一个写文件的IO操作,是比较耗时。所以AOF日志并不是直接写入到日志文件的,而是先写到一个内核的缓存中,然后通过异步刷脏,来将数据保存到磁盘的。

由于这个情况,就导致了会有还没来得及刷脏然后就宕机了,导致数据丢失的风险。

所以Redis提供了一个配置,可以手动地来选择刷脏的频率。

always:每一条AOF记录都立即同步到文件,性能很低,但较为安全。everysec:每秒同步一次,性能和安全都比较中庸的方式,也是redis推荐的方式。如果遇到物理服务器故障,可能导致最多1秒的AOF记录丢失。no:Redis永不直接调用文件同步,而是让操作系统来决定何时同步磁盘。性能较好,但很不安全。

AOF默认是关闭的,需要在配置文件中手动开启。

# 只有在“yes”下,aof重写/文件同步等特性才会生效 appendonly yes ## 指定aof文件名称 appendfilename appendonly.aof ## 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec appendfsync everysec ## 在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no” no-appendfsync-on-rewrite no ## aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb” auto-aof-rewrite-min-size 64mb

Redis4.0混合持久化

Redis4.0提供了一种新的持久化机制,就是RDB和AOF结合使用,将rdb文件内容和aof文件存在一起,AOF中保存的不再是全部数据了,而是从RDB开始的到结束的增量日志。

这样在Redis恢复数据的时候,可以先假装RDB文件中的内容,然后在顺序执行AOF日志中指令,这样就将Redis重启时恢复数据的效率得到了大幅度提升。

结尾

恩,这次就先总结到这里吧,后面会继续总结Redis相关知识,LRU、LFU、内存淘汰策略,管道等等。

作者:纪莫

原文链接:https://www.cnblogs.com/jimoer/p/14204650.html

极速赛车五码稳赢技巧,后面其实还有Codis,但是目前Cluster逐渐流行起来了,Codis的竞争力逐渐被蚕食,而且对新版本的支持,更新的也比较慢,所以这里就不说它了,感兴趣的可以自己去了解一下,国人开源的Redis集群模式Codis。

持久化

Redis持久化的意义在于,当出现宕机问题后,能将数据恢复到缓存中,它提供了两种持久化机制:一种是快照(RDB),一种是AOF日志。

快照是一次全量备份,而AOF是增量备份。快照是内存数据的二进制序列化形式,存储上非常紧凑,而AOF日志记录的是内存数据修改的指令记录文本。

快照备份(RDB)

因为Redis是单线程的,所以在做快照持久化的时候,通常有两个选择,save命令,会阻塞线程,直到备份完成;bgsave会异步的执行备份,其实是fork出了一个子进程,用子进程去执行快照持久化操作,将数据保存在一个.rdb文件中。

子进程刚刚产生的时候,是和父进程共享内存中的数据的,但是子进程做持久化时,是不会修改数据的,而父进程是要持续提供服务的,所以父进程就会持续的修改内存中的数据,这个时候父进程就会将内存中的数据,Copy出一份来进行修改。

父进程copy的数据是以数据页为单位的(4k一页),对那一页数据进行修改就copy哪一页的数据。

子进程由于数据没有变化就会一直地去遍历数据,进程持久化操作了,这就是只保留了创建子进程的时候的快照。

那么RDB是在什么时候触发的呢?

# save <seconds> <changes> save 60 10000 save 300 10

上这段配置就是在redis.conf文件中配置的,第一个参数是时间单位是秒,第二个参数执行数据变化的次数。意思就是说:300秒之内至少发生10次写操作、60秒之内发生至少10000次写操作,只要满足任一条件,均会触发bgsave

增量日志备份(AOF)

Redis在接收到客户端请求指令后,会先进行校验,校验成功后,立即将指令存储到AOF日志文件中,就是说,Redis是先记录日志,再执行命令。这样即使命令还没执行突然宕机了,通过AOF日志文件也是可以恢复的。

AOF重写

AOF日志文件,随着时间的推移,会越来越大,所以就需要进行重写瘦身。AOF重写的原理就是,fork一个子进程,对内存进行遍历,然后生成一系列的Redis指令,然后序列化到一个新的aof文件中。然后再将遍历内存阶段的增量日志,追加到新的aof文件中,追加完成后立即替换旧的aof文件,这样就完成了AOF的瘦身重写。

fsync

因为AOF是一个写文件的IO操作,是比较耗时。所以AOF日志并不是直接写入到日志文件的,而是先写到一个内核的缓存中,然后通过异步刷脏,来将数据保存到磁盘的。

由于这个情况,就导致了会有还没来得及刷脏然后就宕机了,导致数据丢失的风险。

所以Redis提供了一个配置,可以手动地来选择刷脏的频率。

always:每一条AOF记录都立即同步到文件,性能很低,但较为安全。everysec:每秒同步一次,性能和安全都比较中庸的方式,也是redis推荐的方式。如果遇到物理服务器故障,可能导致最多1秒的AOF记录丢失。no:Redis永不直接调用文件同步,而是让操作系统来决定何时同步磁盘。性能较好,但很不安全。

AOF默认是关闭的,需要在配置文件中手动开启。

# 只有在“yes”下,aof重写/文件同步等特性才会生效 appendonly yes ## 指定aof文件名称 appendfilename appendonly.aof ## 指定aof操作中文件同步策略,有三个合法值:always everysec no,默认为everysec appendfsync everysec ## 在aof-rewrite期间,appendfsync是否暂缓文件同步,"no"表示“不暂缓”,“yes”表示“暂缓”,默认为“no” no-appendfsync-on-rewrite no ## aof文件rewrite触发的最小文件尺寸(mb,gb),只有大于此aof文件大于此尺寸是才会触发rewrite,默认“64mb”,建议“512mb” auto-aof-rewrite-min-size 64mb

Redis4.0混合持久化

Redis4.0提供了一种新的持久化机制,就是RDB和AOF结合使用,将rdb文件内容和aof文件存在一起,AOF中保存的不再是全部数据了,而是从RDB开始的到结束的增量日志。

这样在Redis恢复数据的时候,可以先假装RDB文件中的内容,然后在顺序执行AOF日志中指令,这样就将Redis重启时恢复数据的效率得到了大幅度提升。

结尾

恩,这次就先总结到这里吧,后面会继续总结Redis相关知识,LRU、LFU、内存淘汰策略,管道等等。

作者:纪莫

原文链接:https://www.cnblogs.com/jimoer/p/14204650.html

Java设计模式之原型模式怎么实现【Java 框架学习】自学笔记(更新至 类与对象)vue安装less-loader依赖失败如何解决iOS实现电商购物车界面示例MongoDB查询连接数及限制方法UCloud优刻得与奇安信集团携手战略合作
java 连接redis集群(redis持久化方式) 集群式和分布式(分布式数据库和集群)
相关内容