欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Redis緩存高可用集群詳解

 更新時間:2024年10月25日 14:42:38   作者:編程小菜吉  
Redis集群提供了哨兵模式和高可用集群模式兩種方案,前者適合低并發(fā),配置復(fù)雜,主從切換可能導(dǎo)致瞬斷;后者通過多主多從結(jié)構(gòu)提高可用性和性能,支持線性擴(kuò)展,配置簡單,搭建Redis集群至少需要三個主節(jié)點

一、Redis集群方案比較

1、哨兵模式

在redis3.0以前的版本要實現(xiàn)集群一般是借助哨兵sentinel工具來監(jiān)控master節(jié)點的狀態(tài),如果master節(jié)點異常,則會做主從切換,將某一臺slave作為master,哨兵的配置略微復(fù)雜,并且性能和高可用性等各方面表現(xiàn)一般,特別是在主從切換的瞬間存在訪問瞬斷的情況,而且哨兵模式只有一個主節(jié)點對外提供服務(wù),沒法支持很高的并發(fā),且單個主節(jié)點內(nèi)存也不宜設(shè)置得過大,否則會導(dǎo)致持久化文件過大,影響數(shù)據(jù)恢復(fù)或主從同步的效率

2、高可用集群模式

redis集群是一個由多個主從節(jié)點群組成的分布式服務(wù)器群,它具有復(fù)制、高可用和分片特性。

Redis集群不需要sentinel哨兵也能完成節(jié)點移除和故障轉(zhuǎn)移的功能。需要將每個節(jié)點設(shè)置成集群模式,這種集群模式?jīng)]有中心節(jié)點,可水平擴(kuò)展,據(jù)官方文檔稱可以線性擴(kuò)展到上萬個節(jié)點(官方推薦不超過1000個節(jié)點)。

redis集群的性能和高可用性均優(yōu)于之前版本的哨兵模式,且集群配置非常簡單

二、Redis高可用集群搭建

redis集群需要至少三個master節(jié)點,我們這里搭建三個master節(jié)點,并且給每個master再搭建一個slave節(jié)點,總共6個redis節(jié)點,這里用三臺機(jī)器部署6個redis實例,每臺機(jī)器一主一從,搭建集群的步驟如下:

1、在第一臺服務(wù)器建立兩個節(jié)點

mkdir -p /usr/local/redis-cluster
mkdir 8001 8004

2、第一個節(jié)點的redis.conf配置

改配置的時候記得檢查原來的配置,查找的快捷鍵:Esc+“/+關(guān)鍵詞”+回車(按n找到下一個)

(1)基本配置

# 允許訪問的地址,默認(rèn)是127.0.0.1,會導(dǎo)致只能在本地訪問。修改為0.0.0.0則可以在任意IP訪問,生產(chǎn)環(huán)境不要設(shè)置為0.0.0.0
bind 0.0.0.0
# 守護(hù)進(jìn)程,修改為yes后即可后臺運行
daemonize yes
# 監(jiān)聽的端口
port 8001
# 指定數(shù)據(jù)文件存放位置,必須要指定不同的目錄位置,不然會丟失數(shù)據(jù)
dir /usr/local/redis-cluster/8001/
# 日志文件,默認(rèn)為空,不記錄日志,可以指定日志文件名
logfile "/usr/local/redis-cluster/8001/redis.log"
# 把pid進(jìn)程號寫入pidfile配置的文件
pidfile /var/run/redis_8001.pid
# 密碼,設(shè)置后訪問Redis必須輸入密碼
# requirepass whr
# 設(shè)置集群節(jié)點間訪問密碼,跟上面一致
# masterauth whr
# 設(shè)置為no,外圍機(jī)器可以訪問
protected-mode no
# 開啟aof快照
appendonly yes

(2)核心配置

# 啟動集群模式
cluster-enabled yes
# 集群節(jié)點信息文件,這里800x最好和port對應(yīng)上
cluster-config-file nodes-8001.conf
# 超時時間
cluster-node-timeout 10000

(1)把修改后的配置文件,copy到8004,修改端口號信息,可以用批量替換:

:%s/源字符串/目的字符串/g

(2)另外兩臺服務(wù)器也需要做上面幾步操作,第二臺機(jī)器用8002和8005,第三臺機(jī)器用8003和8006

3、啟動6個redis實例

ps -ef | grep redis 查看是否啟動成功

4、關(guān)閉防火墻(也可以開放每一個reids所對應(yīng)的端口號)

# systemctl stop firewalld # 臨時關(guān)閉防火墻
# systemctl disable firewalld # 禁止開機(jī)啟動

5、用redis-cli創(chuàng)建整個redis集群

任意找一臺機(jī)器,輸入下面的指令:

redis-cli -a whr --cluster create --cluster-replicas 1 192.168.92.201:8001 192.168.92.202:8002 192.168.92.203:8003 192.168.92.201:8004 192.168.92.202:8005 192.168.92.203:8006

(1)-a whr: 密碼是whr

(2)–cluster-replicas 1:每一個master下面都有一個從節(jié)點(默認(rèn)會將我們命令中的前三個設(shè)置為主節(jié)點,從節(jié)點是隨機(jī)的。

這里的三個段表示我們我們的三個主節(jié)點分別對應(yīng)這三個段,每當(dāng)我們set一個值時,會先計算這個key的hash值,根據(jù)這個位桶數(shù)組取模判斷是放在哪個節(jié)點中,三個節(jié)點的數(shù)據(jù)互相不重復(fù)。

6、驗證集群

(1)連接任意一個客戶端:redis-cli -a whr -c -h 192.168.92.201 -p 8001 (-a訪問服務(wù)端密碼,-c表示集群模式,-h指定ip地址,-p指定端口號)

(2)查看集群信息:cluster info

(3)查看節(jié)點列表:cluster nodes

(4)關(guān)閉集群(需要逐個進(jìn)行關(guān)閉):./redis-cli -a ale -c -h 192.168.231.134 -p 9001 shutdown

三、Java操作集群

1、引入相關(guān)的依賴

        <dependency>
            <groupId>redis.clients</groupId>
            <artifactId>jedis</artifactId>
            <version>2.9.0</version>
        </dependency>

2、案例

public class JedisClusterTest {

    public static void main(String[] args) {
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(20);
        config.setMaxIdle(10);
        config.setMinIdle(5);
        Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
        jedisClusterNode.add(new HostAndPort("192.168.92.201", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.92.202", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.92.203", 8003));
        jedisClusterNode.add(new HostAndPort("192.168.92.201", 8004));
        jedisClusterNode.add(new HostAndPort("192.168.92.202", 8005));
        jedisClusterNode.add(new HostAndPort("192.168.92.203", 8006));
       JedisCluster jedisCluster = null;
        try {
        		//connectionTimeout:指的是連接一個url的連接等待時間
            	//soTimeout:指的是連接上一個url,獲取response的返回等待時間
            jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10,'whr', config);
            System.out.println(jedisCluster.set("nihao","halou"));
            System.out.println(jedisCluster.get("nihao"));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
       		 if (jedisCluster != null) {
                jedisCluster.close();
            }
        }
    }
}

四、SpringBoot操作集群

1、引入相關(guān)的依賴

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-pool2</artifactId>
</dependency>

2、springboot項目核心配置

server:
  port: 8080

spring:
  redis:
    database: 0
    timeout: 3000
    password: whr
    cluster:
      nodes: 192.168.92.201:8001,192.168.92.202:8002,192.168.92.203:8003,192.168.92.201:8004,192.168.92.202:8005,192.168.92.203:8006
   lettuce:
      pool:
        max-idle: 50
        min-idle: 10
        max-active: 100
        max-wait: 1000

3、案例

@RestController
public class IndexController {

    private static final Logger logger = LoggerFactory.getLogger(IndexController.class);

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("/test_cluster")
    public void testCluster() throws InterruptedException {
       stringRedisTemplate.opsForValue().set("nihao", "666");
       System.out.println(stringRedisTemplate.opsForValue().get("nihao"));
    }
}

五、Redis集群原理分析

(1)Redis Cluster 將所有數(shù)據(jù)劃分為 16384 個 slots(槽位),每個節(jié)點負(fù)責(zé)其中一部分槽位。槽位的信息存儲于每個節(jié)點中。

(2)當(dāng) Redis Cluster 的客戶端來連接集群時,它也會得到一份集群的槽位配置信息并將其緩存在客戶端本地。這樣當(dāng)客戶端要查找某個 key 時,可以直接定位到目標(biāo)節(jié)點

(3)同時因為槽位的信息可能會存在客戶端與服務(wù)器不一致的情況,還需要糾正機(jī)制來實現(xiàn)槽位信息的校驗調(diào)整。

1、槽位定位算法

Cluster 默認(rèn)會對 key 值使用 crc16 算法進(jìn)行 hash 得到一個整數(shù)值,然后用這個整數(shù)值對 16384 進(jìn)行取模來得到具體槽位:HASH_SLOT = CRC16(key) &(16384-1)

2、跳轉(zhuǎn)重定位

當(dāng)客戶端向一個錯誤的節(jié)點發(fā)出了指令,該節(jié)點會發(fā)現(xiàn)指令的 key 所在的槽位并不歸自己管理,這時它會向客戶端發(fā)送一個特殊的跳轉(zhuǎn)指令攜帶目標(biāo)操作的節(jié)點地址,告訴客戶端去連這個節(jié)點去獲取數(shù)據(jù)。

客戶端收到指令后除了跳轉(zhuǎn)到正確的節(jié)點上去操作,還會同步更新糾正本地的槽位映射表緩存,后續(xù)所有 key 將使用新的槽位映射表。

3、Redis集群節(jié)點間的通信機(jī)制

redis cluster節(jié)點間采取gossip協(xié)議進(jìn)行通信維護(hù)集群的元數(shù)據(jù)(集群節(jié)點信息,主從角色,節(jié)點數(shù)量,各節(jié)點共享的數(shù)據(jù)等)有兩種方式:集中式和gossip

3.1、集中式

很多中間件都會借助zookeeper集中式存儲元數(shù)據(jù)。

(1)優(yōu)點:元數(shù)據(jù)的更新和讀取,時效性非常好,一旦元數(shù)據(jù)出現(xiàn)變更立即就會更新到集中式的存儲中,其他節(jié)點讀取的時候立即就可以立即感知到;

(2)缺點:所有的元數(shù)據(jù)的更新壓力全部集中在一個地方,可能導(dǎo)致元數(shù)據(jù)的存儲壓力。

3.2、gossip

gossip協(xié)議包含多種消息,包括ping,pong,meet,fail等等。

(1)meet:某個節(jié)點發(fā)送meet給新加入的節(jié)點,讓新節(jié)點加入集群中,然后新節(jié)點就會開始與其他節(jié)點進(jìn)行通信;

(2)ping:每個節(jié)點都會頻繁給其他節(jié)點發(fā)送ping,其中包含自己的狀態(tài)還有自己維護(hù)的集群元數(shù)據(jù),互相通過ping交換元數(shù)據(jù)(類似自己感知到的集群節(jié)點增加和移除,hash slot信息等);

(3)pong: 對ping和meet消息的返回,包含自己的狀態(tài)和其他信息,也可以用于信息廣播和更新;

(4)fail: 某個節(jié)點判斷另一個節(jié)點fail之后,就發(fā)送fail給其他節(jié)點,通知其他節(jié)點,指定的節(jié)點宕機(jī)了。

優(yōu)點:元數(shù)據(jù)的更新比較分散,不是集中在一個地方,更新請求會陸陸續(xù)續(xù),打到所有節(jié)點上去更新,有一定的延時,降低了壓力;

缺點:元數(shù)據(jù)更新有延時可能導(dǎo)致集群的一些操作會有一些滯后。

補(bǔ)充知識:

  • gossip通信的10000端口每個節(jié)點都有一個專門用于節(jié)點間gossip通信的端口,就是自己提供服務(wù)的端口號+10000,比如8001,那么用于節(jié)點間通信的就是18001端口。
  • 每個節(jié)點每隔一段時間都會往另外幾個節(jié)點發(fā)送ping消息,同時其他節(jié)點接收到ping消息之后返回pong消息。

4、Redis集群選舉原理

當(dāng)slave發(fā)現(xiàn)自己的master變?yōu)镕AIL狀態(tài)時,便嘗試進(jìn)行Failover,以期成為新的master。

由于掛掉的master可能會有多個slave,從而存在多個slave競爭成為master節(jié)點的過程, 其過程如下:

  • (1)slave發(fā)現(xiàn)自己的master變?yōu)镕AIL
  • (2)將自己記錄的集群currentEpoch加1,并廣播FAILOVER_AUTH_REQUEST 信息
  • (3)其他節(jié)點收到該信息,只有master響應(yīng),判斷請求者的合法性,并發(fā)送FAILOVER_AUTH_ACK,對每一個epoch只發(fā)送一次ack
  • (4)嘗試failover的slave收集master返回的FAILOVER_AUTH_ACK
  • (5)slave收到超過半數(shù)master的ack后變成新Master(這里解釋了集群為什么至少需要三個主節(jié)點,如果只有兩個,當(dāng)其中一個掛了,只剩一個主節(jié)點是不能選舉成功的)
  • (6)slave廣播Pong消息通知其他集群節(jié)點。

如果說從節(jié)點們都平票了怎么辦,平票就需要重新選舉,重新走一次上面的流程,那如果每一次都平票了怎么辦,其實這種問題redis有自己的一個解決辦法,那就是每一個從節(jié)點不是一旦感知到主節(jié)點沒有響應(yīng)就直接發(fā)的,而是會有一個延遲算法,在這個時間經(jīng)過之后,才會向外發(fā)送請求,自薦自己要當(dāng)主節(jié)點。

歷史版本有一個延遲時間算法:

DELAY = 500ms + random(0 ~ 500ms) + SLAVE_RANK * 1000ms

SLAVE_RANK表示此slave已經(jīng)從master復(fù)制數(shù)據(jù)的總量的rank。Rank越小代表已復(fù)制的數(shù)據(jù)越新。這種方式下,持有最新數(shù)據(jù)的slave將會首先發(fā)起選舉(理論上)

5、Redis集群為至少需要三個master節(jié)點,并且推薦節(jié)點數(shù)為奇數(shù)(也可以偶數(shù))的原因

因為新master的選舉需要大于半數(shù)的集群master節(jié)點同意才能選舉成功,如果只有兩個master節(jié)點,當(dāng)其中一個掛了,是達(dá)不到選舉新master的條件的。

奇數(shù)個master節(jié)點可以在滿足選舉該條件的基礎(chǔ)上節(jié)省一個節(jié)點,比如三個master節(jié)點和四個master節(jié)點的集群相比,大家如果都掛了一個master節(jié)點都能選舉新master節(jié)點,如果都掛了兩個master節(jié)點都沒法選舉新master節(jié)點了,所以奇數(shù)的master節(jié)點更多的是從節(jié)省機(jī)器資源角度出發(fā)說的。

6、Redis集群對批量操作命令的支持

對于類似mset,mget這樣的多個key的原生批量操作命令,redis集群只支持所有key落在同一slot的情況,如果有多個key一定要用mset命令在redis集群上操作,則可以在key的前面加上{XX},這樣參數(shù)數(shù)據(jù)分片hash計算的只會是大括號里的值,這樣能確保不同的key能落到同一slot里去,

示例如下:

mset {user1}:1:name zhuge {user1}:1:age 18

六、Redis集群相關(guān)的問題

1、網(wǎng)絡(luò)抖動

真實世界的機(jī)房網(wǎng)絡(luò)往往并不是風(fēng)平浪靜的,它們經(jīng)常會發(fā)生各種各樣的小問題。比如網(wǎng)絡(luò)抖動就是非常常見的一種現(xiàn)象,突然之間部分連接變得不可訪問,然后很快又恢復(fù)正常。

為解決這種問題,Redis Cluster 提供了一種選項cluster-node-timeout,表示當(dāng)某個節(jié)點持續(xù) timeout 的時間失聯(lián)時,才可以認(rèn)定該節(jié)點出現(xiàn)故障,需要進(jìn)行主從切換,若是該節(jié)點在這個時間段又恢復(fù)正常,則不需要主從切換。如果沒有這個選項,網(wǎng)絡(luò)抖動會導(dǎo)致主從頻繁切換 (數(shù)據(jù)的重新復(fù)制)。

2、集群腦裂數(shù)據(jù)丟失問題

redis集群沒有過半機(jī)制會有腦裂問題,網(wǎng)絡(luò)分區(qū)導(dǎo)致腦裂后多個主節(jié)點對外提供寫服務(wù),一旦網(wǎng)絡(luò)分區(qū)恢復(fù),會將其中一個主節(jié)點變?yōu)閺墓?jié)點,這時會有大量數(shù)據(jù)丟失。

規(guī)避方法可以在redis配置里加上參數(shù)(這種方法不可能百分百避免數(shù)據(jù)丟失,參考集群leader選舉機(jī)制)

min-replicas-to-write 1  //寫數(shù)據(jù)成功最少同步的slave數(shù)量,這個數(shù)量可以模仿大于半數(shù)機(jī)制配置,
                        //比如集群總共三個節(jié)點可以配置1,加上leader就是2,超過了半數(shù)

注意:這個配置在一定程度上會影響集群的可用性,比如slave要是少于1個,這個集群就算leader正常也不能提供服務(wù)了,需要具體場景權(quán)衡選擇

3、集群是否完整才能對外提供服務(wù)

當(dāng)redis.conf的配置cluster-require-full-coverage為no時,意思是大集群里面有好多小集群,當(dāng)有一個小集群的主節(jié)點掛掉之后,已經(jīng)沒有從節(jié)點給它頂上的時候,說明這個小集群已經(jīng)癱瘓掉,當(dāng)上面的配置為no時,整個的集群還是可用的,如果為yes,整個集群就不能用了。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 如何用redis?setNX命令來加鎖

    如何用redis?setNX命令來加鎖

    這篇文章主要介紹了如何用redis?setNX命令來加鎖,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • redis使用watch秒殺搶購實現(xiàn)思路

    redis使用watch秒殺搶購實現(xiàn)思路

    這篇文章主要為大家詳細(xì)介紹了redis使用watch秒殺搶購的實現(xiàn)思路,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-02-02
  • 使用Redis防止重復(fù)發(fā)送RabbitMQ消息的方法詳解

    使用Redis防止重復(fù)發(fā)送RabbitMQ消息的方法詳解

    今天遇到一個問題,發(fā)送MQ消息的時候需要保證不會重復(fù)發(fā)送,注意不是可靠到達(dá),這里保證的是不會生產(chǎn)多條一樣的消息,所以本文主要介紹了使用Redis防止重復(fù)發(fā)送RabbitMQ消息的方法,需要的朋友可以參考下
    2025-01-01
  • Redis分布式鎖實例分析講解

    Redis分布式鎖實例分析講解

    分布式鎖是控制分布式系統(tǒng)不同進(jìn)程共同訪問共享資源的一種鎖的實現(xiàn)。如果不同的系統(tǒng)或同一個系統(tǒng)的不同主機(jī)之間共享了某個臨界資源,往往需要互斥來防止彼此干擾,以保證一致性
    2022-12-12
  • 使用Redis實現(xiàn)向量相似度搜索

    使用Redis實現(xiàn)向量相似度搜索

    在自然語言處理領(lǐng)域,有一個常見且重要的任務(wù)就是文本相似度搜索,所以本文為大家介紹一下如何利用Redis實現(xiàn)向量相似度搜索,解決文本、圖像和音頻之間的相似度匹配問題,需要的可以了解下
    2023-07-07
  • 基于Redis實現(xiàn)基本搶紅包算法詳解

    基于Redis實現(xiàn)基本搶紅包算法詳解

    [key, value]的緩存數(shù)據(jù)庫, Redis官方性能描述非常高, 所以面對高并發(fā)場景, 使用Redis來克服高并發(fā)壓力是一個不錯的手段, 本文主要基于Redis來實現(xiàn)基本的搶紅包系統(tǒng)設(shè)計,感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • redis啟動和退出命令行簡單操作步驟

    redis啟動和退出命令行簡單操作步驟

    Redis是一種鍵值存儲數(shù)據(jù)庫,用戶可以使用它來存儲和檢索大量的鍵值數(shù)據(jù),下面這篇文章主要給大家介紹了關(guān)于redis啟動和退出命令行的相關(guān)資料,需要的朋友可以參考下
    2024-03-03
  • Redis生成分布式系統(tǒng)全局唯一ID的實現(xiàn)

    Redis生成分布式系統(tǒng)全局唯一ID的實現(xiàn)

    在互聯(lián)網(wǎng)系統(tǒng)中,并發(fā)越大的系統(tǒng),數(shù)據(jù)就越大,數(shù)據(jù)越大就越需要分布式,本文主要介紹了Redis生成分布式系統(tǒng)全局唯一ID的實現(xiàn),感興趣的可以了解一下
    2021-10-10
  • redis事務(wù)常用操作詳解

    redis事務(wù)常用操作詳解

    在本篇文章里小編給大家分享了關(guān)于redis事務(wù)常用操作的相關(guān)知識點內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2019-07-07
  • Redis慢日志的實現(xiàn)示例

    Redis慢日志的實現(xiàn)示例

    慢查詢?nèi)罩臼荝edis提供的一個用于觀察系統(tǒng)性能的功能,本文主要介紹了Redis慢日志的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-04-04

最新評論