分布式系统设计一个非常关键的问题:单点问题
如果某个服务器程序,只有一个节点(只搞一个物理服务器,来部署这个服务器程序)
1.可用性问题:如果这个机器挂了,意味着服务就中断了
2.性能/支持的并发量也是比较有限的
引入分布式系统,主要也就是为了解决上述的单点问题
在分布式系统中,往往希望有多个服务器来部署redis服务,从而构成一个redis集群,此时就可以让这个集群给整个分布式系统中其他的服务,提供更稳定/更高效的数据存储功能~
在分布式系统中,希望使用多个服务器来部署redis,存在以下几种redis部署方式
1.主从模式
2.主从+哨兵模式
3.集群模式
1.主从模式
在若干个redis节点中,有的是主节点,有的是从节点,假设有三个物理服务器(称为三个节点)其中可以把其中一个节点,作为主节点,另外两个节点作为从节点,从节点需要听主节点的(从节点上的数据要跟随主节点变化;从节点数据要和主节点保持一致)
本来,在主节点上保存一堆数据,引入从节点之后,就是要把主节点上面的数据,复制出来,放到从节点中,后续,主节点这边对于数据有任何修改,都会把这样的修改给同步到从节点上
Redis主从模式中,从节点的数据,不允许修改!!只能读取数据。
引入更多的计算资源,自然能够支持的并发量也就大幅度提高了
之前假如只是单个redis服务器节点,此时这个机器挂了,整个redis就挂了,上述这个主从结构,这个redis就不容易挂了,如果挂了某个从节点,没有啥影响,继续从主节点或者其他从节点读取数据,得到效果完全相同,如果挂掉的是主节点,还是有一定影响的,从节点只能够读数据,如果需要写数据,就没的写了
主从模式,主要是针对读操作进行并发量&可用性的提高
而写操作的话,无论是可用性还是并发,都非常依赖主节点,主节点又不能搞多个,实际业务场景中,读操作就是比写操作更加频繁~
主从结构,是分布式系统中比较经典的结构,不仅redis,mysql支持
如何配置redis主从结构,需要启动多个redis服务器,正常来说每个redis服务器程序,应该在当主机上(才是分布式)redis-server默认端口6379
如何指定redis-server端口
1.可以启动程序的时候,通过命令行来指定端口号--port选项
2.也可以直接在配置文件中,来设定端口。
把两个配置文件的端口号和daemonize来标记了。
daemonize:yes 按照后台进程的方式来运行
修改之后,需要按照下述命令
redis-server ./slave1.conf
redis-server ./slave2.conf
目前这几个节点只是各自为政,要想要配置成主从结构,就需要使用slaveof
修改了配置文件,一直持久生效的。
此处加上slaveof以6379为主机
kill-9 128381 端口号这种停止redis-server的方式,是和咱们之前通过redis-server的方式搭配的,而如果是使用service redis-server start这种方式启动的,就必须使用service redis-server stop来停止的
Could not connect to Redis at 127.0.0.1:6380: Connection refusednot connected> exit解决方法
下面这个命令,第一句话相当于告诉redis以这个配置文件启动redis
我们可以看到,从节点无法添加数据
主节点插入111
从节点获取到值
主节点会收到源源不断的修改数据的请求,从数据就需要从主节点这里同步修改这些修改请求,从节点和主节点之间的数据同步,不是瞬间完成的
主节点offset(另一个6381懒得启动了),下面的master_repl_offset :992说明主节点和从节点同步一致,当然从节点也可以再挂从节点
Slave no one(直接在redis客户端的命令)
但是当从节点断开现有的主从复制,从节点断开主从关系,他就不在从属于其他节点了,里面已经有的数据,是不会抛弃的!,但是后续主节点如果针对数据进行修改,那么从节点无法再去同步数据了,当然他只是命令上的操作,真正的永久还是应该修改配置文件(我的意思是永久的断开)
当然如果我们修改配置文件,也能让从节点修改数据,但是!!!加入允许从节点修改,但是主节点是无法感知的从节点的操作,这样就会导致数据不一致
主节点和从节点通过网络来传输TCP,
TCP内部支持nagle算法
开启,就会增加tcp的传输延迟,节省了网络带宽
关闭,就会减少tcp传输延迟,增加了网络带宽 目的和tcp捎带应答一样的,合并小的tcp数据报,减少了包的个数。
repl-disable-tcp-nodelay这个选项可以用于在主从同步通信过程中,关闭tcpd nagle算法
从节点更快速的主节点进行同步。
实际开发中,读请求远大于写请求
数据同步命令:psync命令,完成数据同步的过程
psync不需要手动执行
redis服务器会在建立好主从关系后,自动执行psync
psync replicationid offset:
replicationid主节点生成的复制id,即使是同一个节点,每次重启生成的replication id都是不同的,从节点和主节点建立了复制关系,就会从主节点这边获取到replication id
一般情况下relid2这个是用不上的,如果A和B通信过程中出现了一些网络抖动,则B认为A挂了,B自己会成为主节点(给自己生成一个replid)
offset偏移量:主节点和从节点都会维护偏移量(整数),主节点的偏移量,主节点会收到很多修改操作的命令,每个命令要占据几个字节,主节点把这些修改命令,每个字节数进行增加。
offset写作-1,就是获取全量数据,写作具体的正整数,则是从当千篇一律位置来进行获取
啥时候进行全量复制
1.首次和主节点进行数据同步
2.主节点不方便进行部分复制的时候
啥时候进行部分复制
从节点之前已经从主节点上复制过数据了,因为网络抖动或者从节点重启了
从节点需要重新从主节点这边同步数据,此时看看能不能只同步一小部分(大部分的数据是一致的)
rdb文件是二进制的格式,比较节省空间,
采用bgsave,不能采用以往的rdb文件,而是必须要重新生成一下,已有的rdb文件可能会和当前最新的数据存在较大差异~。在主节点生成rdb文件和传输rdb文件过程中,还会收到很多新的修改操作,新修改的数据,也必须要同步给从节点,当从节点收完了主节点发来的rdb之后,主节点就会把这些新修改的操作也发送给从节点。
主节点进行全量复制的时候,也支持无硬盘模式,生成的rdb二进制数据,不是直接保存到文件中了,而是直接进行网络传输(省下来一次读硬盘和写硬盘的操作,虽然无硬盘,但是网络传输也是没法省略的,提升不大)
从节点,之前也是先把收到rdb数据,写入到硬盘中,然后再加载,现在也可以省略这个过程,直接把收到的数据进行加载了。
replication id VS runId(两个不同的id)
info replication -replication id
info server -runId 长度相同格式也非常相似
runId是每个节点都不相同-支持哨兵这个功能
replid是具有主从关系的节点,是相同的
下面这四个是描述积压缓冲区的,这个缓冲区是用来存储尚且没有发过去的数据
如果replicationId不一样,则说明他不是原来的,需要全量复制,假如一样,offset再去判定,从节点在网络波动这一块同步数据的进度是如何?如果确实是在积压缓冲区之内,此时就可以直接进行部分复制,就只把最近这段时间的数据给复制过去即可,如果确实当前从节点进度已经超出积压缓冲区的范围了,找不齐拉下的东西,那么就全量复制。
实时复制:
从节点,已经和主节点,同步好数据了(从节点这一刻已经和主节点数据一致了,但是之后,主接待您这边会源源不断的收到新的修改数据的请求,主节点上的数据就会随之改变,也需要能够同步给从节点,从节点和主节点之间会建立TCP长连接,然后主节点把自己收到的修改数据的请求,通过上述连接,发送给从节点,从节点在根据这些修改请求,修改内存中的数据->(如果这里从接待您级别很多,延时也会上升
进行实时复制的时候,保证连接处于可用状态
心跳包机制
(主节点:默认每隔10s发送一个ping,从节点收到返回一个pong)
从节点:默认每隔1s给主节点发送一个特定请求,就会上报当前从节点复制数据的进度(offset)
小结论
主从复制解决的问题:单个redis,可用性不高,性能有限
主从复制的特点:
1.Redis通过复制功能实现主节点的多个副本
2.主节点用来写,从节点用来读,这样可以降低主节点的访问压力
3.复制支持多个拓扑结构,可以适当场景选择合适的拓扑结构
4.复制分为全量复制,部分复制和实时复制
5.主从节点之间通过心跳包机制保证主从节点通信正常和数据一致性。
主从复制配置的过程
1.主节点配置不需要改动
2.从节点在配置文件中加入slaveof主节点ip 主节点端口号的形式即可
主从复制的缺点
1.从机多了,复制数据的延时很明显
2.主机挂了,从机不会升级成主机,只能通过人工干预的方式恢复
补充:对于从节点晋升成主节点的问题
1.从节点主动和主节点断开连接
slaveof no one 这个时候,从节点可以晋升成主节点
2.主节点挂了
这个时候,从节点,不会晋升成主节点的,必须通过人工干预的方式,恢复主节点
补充:关于redis主节点无法重启的问题
主从节点配置我们可以看到,是共用一个aof文件的,从节点是通过手动启动的方式运行的,此时root用户启动redis服务器,于是生成的aof文件也就是root用户文件
通过service redis-server start启动redis服务器,是通过一个redis这样的用户来启动的,所属的是redis用户,而不是root用户,权限暴露的低,redis按照读的方式,redis server需要可读可写的方式打开这个aof文件,而这个文件对于root以外的用户只有读的权限,因此
通过service redis-server start启动的redis服务器无法打开这个文件
解决方案:
把三个redis服务器生成的文件也给区分开~,更靠谱的是,直接把三个redis服务器的工作目录区分开~(修改配置文件中的dir选项)
1.停止之前的redis服务器
2.删除之前工作目录下,已经生成的aof文件或者也可以通过chown命令,修改一下redis所属于的用户
3.给从节点创建出新的目录~,用来作为从节点的工作目录~并且修改从节点的配置文件,设定成新的目录为工作目录。