這篇文章為大家帶來了關於Redis的相關知識,其中主要介紹了關於高可用架構搭建到原理分析的相關內容,下面一起來看一下,希望對大家有幫助。
推薦學習:Redis影片教學
#由於近期公司在做系統最佳化,前段時間將大表進行分錶後,現在又來搞redis了。關於redis,其中有一項要求就是將redis服務由阿里雲遷移到公司自己的伺服器中(由於公司性質原因)。剛好藉著這次機會,重新回顧redis的高可用叢集架構。 redis集群方式有三種,分別為主從複製模式,哨兵模式以及Cluster集群模式,一般情況下哨兵和Cluster集群用的相對多一些,下面就來簡單理解這三種模式。
在理解叢集架構前,先要介紹一下redis的持久化機制,因為在後面的叢集中會牽涉到持久化。 redis持久化是將快取在記憶體中的資料依照一些規則進行落盤,以防止在redis服務宕機時可以進行資料復原或是叢集架構中進行主從節點資料同步。 redis持久化的方式有RDB和AOF兩種,在4.0版本後新出了混合持久化模式。
RDB是redis預設開啟的持久化機制,其持久化方式是依照使用者設定的規則"X秒內至少發生過Y次改變"
,產生快照並落盤到dump.rdb二進位。預設情況下,redis配置了三種,分別為900秒內至少發生過1次緩存key的改動,300秒內至少發生過10次緩存key的改動以及60秒內至少發生過10000次改動。
除了redis自動快照持久化資料外,還有兩個指令可以幫助我們手動進行記憶體資料快照,這兩個指令分別為save
和bgsave
。
save:以同步的方式進行資料快照,當快取資料量大,會阻塞其他指令的執行,效率不高。
bgsave:以非同步的方式進行資料快照,有redis主執行緒fork出一個子程序來進行資料快照,不會阻塞其他指令的執行,效率較高。由於是採用非同步快照的方式,那麼就有可能發生在快照的過程中,有其他指令對資料進行了修改。為了避免這個問題reids採用了寫時複製(Cpoy-On-Write)的方式,因為此時進行快照的進程是由主線程fork出來的,所以享有主線程的資源,當快照過程中發生數據改動時,那麼該資料會被複製一份並產生副本數據,子程序會將改副本資料寫入到dump.rdb檔案中。
RDB快照是以二進位的方式進行儲存的,所以在資料復原時,速度會比較快,但是它有資料遺失的風險。假如設定的快照規則為60秒內至少發生100次資料改動,那麼在50秒時,redis服務由於某種原因突然宕機了,那在這50秒內的所有資料將會遺失。
AOF是Redis的另一種持久化方式,與RDB不同時是,AOF記錄每個更改資料的命令並保存到磁碟下的appendonly.aof檔案中,當redis服務重新啟動時,會載入該文將並再次執行檔案中儲存的命令,從而達到資料復原的效果。預設情況下,AOF是關閉的,可以透過修改conf設定檔來開啟。
# appendonly no 关闭AOF持久化 appendonly yes # 开启AOF持久化 # The name of the append only file (default: "appendonly.aof") appendfilename "appendonly.aof" # 持久化文件名
AOF提供了三種方式,可以讓指令儲存到磁碟。預設情況下,AOF採用appendfsync everysec
的方式進行指令持久化。
appendfsync always #每次有新的改写命令时,都会追加到磁盘的aof文件中。数据安全性最高,但效率最慢。 appendfsync everysec # 每一秒,都会将改写命令追加到磁盘中的aof文件中。如果发生宕机,也只会丢失1秒的数据。 appendfsync no #不会主动进行命令落盘,而是由操作系统决定什么时候写入到磁盘。数据安全性不高。
開啟AOF後需要重新啟動redis服務,當再次執行相關改寫指令時,aof檔案中會記錄操作的指令。
相對於RDB,雖然AOF的資料安全性更高,但隨著服務的持續運行,aof的檔案也會越來越大,等到下次恢復資料時,速度會越來越慢。如果RDB和AOF都開啟,在恢復資料時,redis會優先選擇AOF,畢竟AOF遺失的資料更少。
RDB | #AOF | |||
---|---|---|---|---|
復原效率 | 高 | 低 | ||
資料安全性 | 低 | ##高|||
低 | 高 |
IP | 主/从节点 | 端口 | 版本 |
---|---|---|---|
192.168.36.128 | 主 | 6379 | 5.0.14 |
192.168.36.130 | 从 | 6379 | 5.0.14 |
192.168.36.131 | 从 | 6379 | 5.0.14 |
修改redis.conf文件中的replicaof,配置主节点的ip和端口号,并且开启从节点只读。
./src/redis-server redis.conf
3. 依次启动从节点36.130,36.131机器中的redis服务
./src/redis-server redis.conf
启动成功后可以看到日志中显示已经与Master节点建立的连接。如果出现与Master节点的连接被拒,那么先检查Master节点的服务器是否开启防火墙,如果开启,可以开放6379端口或者关闭防火墙。如果防火墙被关闭但连接仍然被拒,那么可以修改Master节点服务中的redis.conf文件。将bing 127.0.0.1修改为本机对外的网卡ip或者直接注释掉即可,然后重启服务器即可。
全部节点启动成功后,Master节点可以查看从节点的连接状态,offset偏移量等信息。
info replication # 主节点查看连接信息
全量数据同步主从节点之间的数据同步是通过建立socket长连接来进行传输的。当Slave节点启动时,会与Master节点建立长连接,并且发送psync同步数据命令。当Master节点收到psync命令时,会执行pgsave进行rdb内存数据快照(这里的rdb快照与conf文件中是否开启rdb无关),如果在快照过程中有新的改写命令,那么Master节点会将这些命令保存到repl buffer缓冲区中。当快照结束后,会将rdb传输给Slave节点。Slave节点在接收到rdb后,如果存在旧数据,那么会将这些旧数据清除并加载rdb。加载完成后会接受master缓存在repl buffer中的新命令。在这些步骤全部执行完成后,主从节点已经算连接成功了,后续Master节点的命令会不断的发送到Slave节点。如果在高并发的情况下,可能会存在数据延迟的情况。
部分数据同步
部分数据同步发生在Slave节点发生宕机,并且在短时间内进行了服务恢复。短时间内主从节点之间的数据差额不会太大,如果执行全量数据同步将会比较耗时。部分数据同步时,Slave会向Master节点建立socket长连接并发送带有一个offset偏移量的数据同步请求,这个offset可以理解数据同步的位置。Master节点在收到数据同步请求后,会根据offset结合buffer缓冲区内新的改写命令进行位置确定。如果确定了offset的位置,那么就会将这个位置往后的所有改写命令发送到Slave节点。如果没有确定offset的位置,那么会再次执行全量数据同步。比如,在Slave节点没有宕机之前命令已经同步到了offset=11这个位置,当该节点重启后,向Master节点发送该offset,Master根据offset在缓冲区中进行定位,在定位到11这个位置后,将该位置往后的所有命令发送给Slave。在数据同步完成后,后续Master节点的命令会不断的发送到该Slave节点
优点
缺点
哨兵模式對主從複製進行了進一步最佳化,獨立出單獨的哨兵程序用於監控主從架構中的伺服器狀態,一旦發生宕機,哨兵會在短時間內選出新的Master節點並進行主從切換。不僅如此,在多哨兵的節點下,每個哨兵都會互相監控,監控哨兵節點是否宕機。
#IP | ##主/從節點#端口 | 哨兵連接埠 | 版本 | |
---|---|---|---|---|
主 | #6379 | 26379 | 5.0.14 | |
從 | 6379 | 26379 | 5.0.14 | |
從 | #6379 | #26379 | #5.0.14 |
IP | 主/從節點 | 連接埠 | 版本 |
---|---|---|---|
192.168.36.128 | - | 6379 | 5.0.14 |
#192.168.36.128 | - | 6380 | 5.0.14 |
192.168.36.130 | #- | # 6379 | 5.0.14 |
192.168.36.130 | - | 6380 | |
192.168.36.131 | - | 6379 | |
##192.168. 36.131 | - | 6380 |
为了看起来不是那么混乱,可以为cluster新建一个文件夹,并将redis的文件拷贝到cluster文件夹中,并修改文件夹名为redis-6379,reids-6380。
新建完成后,修改每个节点的redis.conf配置文件,找到cluster相关的配置位置,将cluster-enable更改为yes,表示开启集群模式。开启后,需要修改集群节点连接的超时时间cluster-node-timeout,节点配置文件名cluster-config-file等等,需要注意的是,同一台机器上面的服务节点记得更改端口号。
在每个节点都配置完成后,可以依次启动各节点。启动成功后,可以查看redis的进程信息,后面有明显的标识为[cluster]。
现在虽然每个节点的redis都已经正常启动了,但是每个节点之间并没有任何联系啊。所以这个时候还需要最后一步,将各节点建立关系。在任意一台机器上运行下面的命令-- cluster create ip:port,进行集群创建。命令执行成功后,可以看到槽位的分布情况和主从关系。
./src/redis-cli --cluster create 192.168.36.128:6379 192.168.36.128:6380 192.168.36.130:6379 192.168.36.130:6380 192.168.36.131:6379 192.168.36.131:6380 --cluster-replicas 1复制代码
cluster成功启动后,可以在代码中简单的测试一下,这里的代码依旧采用哨兵模式中的测试代码,只是将sentinel相关的信息注释掉并加上cluster的节点信息即可。
spring: redis: cluster: nodes: 192.168.36.128:6379,192.168.36.128:6380,192.168.36.130:6379,192.168.36.130:6380,192.168.36.131:6379,192.168.36.131:6380# sentinel:# master: mymaster# nodes: 192.168.36.128:26379,192.168.36.130:26379,192.168.36.131:26379 timeout: 3000 lettuce: pool: max-active: 80 min-idle: 50
Cluster模式下由于存在多个Master节点,所以在存储数据时,需要确定将这个数据存储到哪台机器上。上面在启动集群成功后可以看到每台Master节点都有自己的一个槽位(Slots)范围,Master[0]的槽位范围是0 - 5460,Master[1]的槽位范围是5461 - 10922,Master[2]的槽位范围是10922 - 16383。redis在存储前会通过CRC16方法计算出key的hash值,并与16383进行位运算来确定最终的槽位值。所以,可以知道确定槽位的方式就是 CRC16(key) & 16383
。计算出槽位后,此时在java服务端并不知道这个槽位对应到哪一台redis服务,其实在java服务端启动服务时会将redis的相关槽位和映射的ip信息进行一个本地缓存,所以知道槽位后,就会知道对应槽位的ip。
cluster模式中的选举与哨兵中的不同。当某个从节点发现自己的主节点状态变为fail状态时,便尝试进行故障转移。由于挂掉的主节点可能会有多个从节点,从而存在多个从节点竞争成为新主节点 。其选举过程大概如下:
从节点将自己记录的集群currentEpoch加1,并广播FAILOVER_AUTH_REQUEST信息,通知集群中的所有节点,需要进行重新选举了。
其他节点收到该信息,但只有master节点会进行响应,判断请求者的合法性,并发送 FAILOVER_AUTH_ACK,对每一个epoch只发送一次ack。
发送通知的从节点会收集各master主节点返回的FAILOVER_AUTH_ACK。
如果该从节点收到的ack数过半,那么该节点就会被选举为新的Master主节点。成为主节点后,广播通知其他小集群节点
优点:
有多个主节点,做到去中心化。
数据可以槽位进行分布存储
扩展性更高,可用性更高。cluster集群中的节点可以在线添加或删除,官方推荐节点数不超1000。当部分Master节点不可用时,整个集群任然可以正常工作。
缺点:
数据通过异步复制,不保证数据的强一致性
Slave节点在集群中充当冷备,不能缓解读压力
reids作為當下非常流行的一款中間件,它可以用作緩存,減少DB的壓力,提高系統的效能。也可以用作分散式鎖保證並發安全性。也可以用作MQ訊息佇列,減少系統的耦合度。它支援單機模式,主從複製,哨兵以及Cluster模式。每個模式都有自己的優點和缺點,在實際專案中可以根據自己的業務需求以及並發程度來進行選擇。
推薦學習:Redis影片教學
以上是Redis高可用架構搭建到原理分析的詳細內容。更多資訊請關注PHP中文網其他相關文章!