1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Redis集群搭建及原理

        共 8880字,需瀏覽 18分鐘

         ·

        2021-06-12 11:16

        一、哨兵模式

        在 redis3.0之前,redis使用的哨兵架構(gòu),它借助 sentinel 工具來監(jiān)控 master 節(jié)點的狀態(tài);如果 master 節(jié)點異常,則會做主從切換,將一臺 slave 作為 master。

        哨兵模式的缺點

        (1)當(dāng)master掛掉的時候,sentinel 會選舉出來一個 master,選舉的時候是沒有辦法去訪問Redis的,會存在訪問瞬斷的情況;若是在電商網(wǎng)站大促的時候master給掛掉了,幾秒鐘損失好多訂單數(shù)據(jù);

        (2)哨兵模式,對外只有master節(jié)點可以寫,slave節(jié)點只能用于讀。盡管Redis單節(jié)點最多支持10W的QPS,但是在電商大促的時候,寫數(shù)據(jù)的壓力全部在master上。

        (3)Redis的單節(jié)點內(nèi)存不能設(shè)置過大,若數(shù)據(jù)過大在主從同步將會很慢;在節(jié)點啟動的時候,時間特別長;(從節(jié)點上有主節(jié)點的所有數(shù)據(jù))

        二、Redis集群

        1、Redis集群的介紹

        Redis集群是一個由多個主從節(jié)點群組成的分布式服務(wù)集群,它具有復(fù)制、高可用和分片特性。Redis集群不需要sentinel哨兵也能完成節(jié)點移除和故障轉(zhuǎn)移的功能。需要將每個節(jié)點設(shè)置成集群模式,這種集群模式?jīng)]有中心節(jié)點,可水平擴展,據(jù)官方文檔稱可以線性擴展到上萬個節(jié)點(官方推薦不超過1000個節(jié)點)。redis集群的性能和高可用性均優(yōu)于之前版本的哨兵模式,且集群配置非常簡單。

        2、Redis集群的優(yōu)點

        (1)Redis集群有多個master,可以減小訪問瞬斷問題的影響;

        若集群中有一個master掛了,正好需要向這個master寫數(shù)據(jù),這個操作需要等待一下;但是向其他master節(jié)點寫數(shù)據(jù)是不受影響的。

        (2)Redis集群有多個master,可以提供更高的并發(fā)量;

        (3)Redis集群可以分片存儲,這樣就可以存儲更多的數(shù)據(jù);

        3、Redis集群的搭建

        Redis的集群搭建最少需要3個master節(jié)點,我們這里搭建3個master,每個下面掛一個slave節(jié)點,總共6個Redis節(jié)點;(3臺機器,每臺機器一主一從)

        第1臺機器:192.168.1.1   8001端口  8002端口

        第2臺機器:192.168.1.2   8001端口  8002端口

        第3臺機器:192.168.1.3   8001端口  8002端口

        第一步:創(chuàng)建文件夾

        mkdir -p /usr1/redis/redis-cluster/8001 /usr1/redis/redis-cluster/8002
        復(fù)制代碼

        第二步:將redis安裝目錄下的 redis.conf 文件分別拷貝到8001目錄下

        cp /usr1/redis-5.0.3/redis.conf /usr1/redis/redis-cluster/8001
        復(fù)制代碼

        第三步:修改redis.conf文件以下內(nèi)容

        port 8001 daemonize yes
        pidfile "/var/run/redis\_8001.pid" #指定數(shù)據(jù)文件存放位置,必須要指定不同的目錄位置,不然會丟失數(shù)據(jù) dir /usr1/redis/redis-cluster/8001/ #啟動集群模式
        cluster\-enabled yes

        #集群節(jié)點信息文件,這里800x最好和port對應(yīng)上
        cluster\-config-file nodes-8001.conf

        # 節(jié)點離線的超時時間
        cluster\-node-timeout 5000 #去掉bind綁定訪問ip信息
        #bind 127.0.0.1 #關(guān)閉保護模式
        protected\-mode no

        #啟動AOF文件
        appendonly yes

        #如果要設(shè)置密碼需要增加如下配置:
        #設(shè)置redis訪問密碼
        requirepass redis\-pw

        #設(shè)置集群節(jié)點間訪問密碼,跟上面一致
        masterauth redis\-pw
        復(fù)制代碼

        第四步,把上面修改好的配置文件拷貝到8002文件夾下,并將8001修改為8002:

        cp /usr1/redis/redis-cluster/8001/redis.conf /usr1/redis/redis-cluster/8002 cd /usr1/redis/redis-cluster/8002/ vim redis.conf

        #批量修改字符串
        :%s/8001/8002/g
        復(fù)制代碼

        第五步,將本機(192.168.1.1)機器上的文件拷貝到另外兩臺機器上

        scp /usr1/redis/redis-cluster/8001/redis.conf  [email protected]:/usr1/redis/redis-cluster/8001/
        scp /usr1/redis/redis-cluster/8002/redis.conf [email protected]:/usr1/redis/redis-cluster/8002/
        scp /usr1/redis/redis-cluster/8001/redis.conf [email protected]:/usr1/redis/redis-cluster/8001/
        scp /usr1/redis/redis-cluster/8002/redis.conf [email protected]:/usr1/redis/redis-cluster/8002/
        復(fù)制代碼

        第六步,分別啟動這6個redis實例,然后檢查是否啟動成功

        /usr1/redis/redis-5.0.3/src/redis-server /usr1/redis/redis-cluster/8001/redis.conf /usr1/redis/redis-5.0.3/src/redis-server /usr1/redis/redis-cluster/8002/redis.conf   
        ps -ef | grep redis
        復(fù)制代碼

        第七步,使用 redis-cli 創(chuàng)建整個 redis 集群(redis5.0版本之前使用的ruby腳本 redis-trib.rb)

        運行以上命令,完成搭建

        /usr1/redis/redis-5.0.3/src/redis-cli -a redis-pw --cluster create --cluster-replicas 1 192.168.1.1:8001 192.168.1.1:8002 192.168.1.2:8001 192.168.1.2:8002 192.168.1.3:8001 192.168.1.3:8002
        復(fù)制代碼

        說明

        -a :密碼;

        --cluster-replicas 1:表示1個master下掛1個slave;--cluster-replicas 2:表示1個master下掛2個slave。

        擴展

        查看幫助命令:src/redis‐cli --cluster help

        create:創(chuàng)建一個集群環(huán)境host1:port1 ... hostN:portN
        call:可以執(zhí)行redis命令
        add\-node:將一個節(jié)點添加到集群里,第一個參數(shù)為新節(jié)點的ip:port,第二個參數(shù)為集群中任意一個已經(jīng)存在的節(jié)點的ip:port
        del\-node:移除一個節(jié)點
        reshard:重新分片
        check:檢查集群狀態(tài)
        復(fù)制代碼

        第八步,驗證集群

        (1)連接任意一個客戶端

        /usr1/redis/redis-5.0.3/src/redis-cli -a redis-pw -c -h 192.168.1.1 -p 8001
        復(fù)制代碼

        說明:‐a表示服務(wù)端密碼;‐c表示集群模式;-h指定ip地址;-p表示端口號

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

        (3) 查看節(jié)點列表:  cluster nodes  slave 對應(yīng)的 master 從上面也可以看到;

        從上面可以看到 slave掛在哪個 master 下面;

        在 /usr1/redis/redis-cluster/8001/nodes-8001.conf 文件中存儲了節(jié)點信息;

        (4)進行數(shù)據(jù)操作驗證;

        (5)關(guān)閉集群則需要逐個進行關(guān)閉,使用命令:

        /usr/local/redis‐5.0.3/src/redis‐cli ‐a redis-pw ‐c ‐h 192.168.1.1 ‐p 8001 shutdown /usr/local/redis‐5.0.3/src/redis‐cli ‐a redis-pw ‐c ‐h 192.168.1.1 ‐p 8002 shutdown
        ......
        復(fù)制代碼

        注意:在創(chuàng)建集群的時候,需要把所有節(jié)點機器上的防火關(guān)閉,保證 Redis的服務(wù)端口和集群節(jié)點通信的 gossip 端口能通;

        systemctl stop firewalld # 臨時關(guān)閉防火墻

        systemctl disable firewalld # 禁止開機啟動

         4、Redis集群原理分析

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

        當(dāng)Redis Cluster 的客戶端來連接集群時,它也會得到一份集群的槽位配置信息,并將其緩存在客戶端本地。這樣當(dāng)客戶端要查找某個 key 時,可以直接定位到目標(biāo)節(jié)點。同時因為槽位的信息可能會存在客戶端與服務(wù)器不一致的情況,還需要糾正機制來實現(xiàn)槽位信息的校驗調(diào)整。

        槽位定位算法

         Cluster 默認會對 key 值使用 crc16 算法進行 hash 得到一個整數(shù)值,然后用這個整數(shù)值對 16384 進行取模來得到具體槽位。

        HASH_SLOT = CRC16(key) % 16384

        跳轉(zhuǎn)重定位

           當(dāng)客戶端向一個節(jié)點發(fā)出了指令,首先當(dāng)前節(jié)點會計算指令的 key 得到槽位信息,判斷計算的槽位是否歸當(dāng)前節(jié)點所管理;若槽位不歸當(dāng)前節(jié)點管理,這時它會向客戶端發(fā)送一個特殊的跳轉(zhuǎn)指令攜帶目標(biāo)操作的節(jié)點地址,告訴客戶端去連這個節(jié)點去獲取數(shù)據(jù)??蛻舳耸盏街噶詈蟪颂D(zhuǎn)到正確的節(jié)點上去操作,還會同步更新糾正本地的槽位映射表緩存,后續(xù)所有 key 將使用新的槽位映射表。

        Redis集群節(jié)點之間的通信機制

        維護集群的元數(shù)據(jù)有集中式和 gossip兩種方式,Redis 的集群節(jié)點之間的通信采取 gossip 協(xié)議進行通信

        (1)集中式:

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

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

        (2)gossip:

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

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

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

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

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

          網(wǎng)絡(luò)抖動就是非常常見的一種現(xiàn)象,突然之間部分連接變得不可訪問,然后很快又恢復(fù)正常。
        為解決這種問題,Redis Cluster 提供了一種選項  cluster--node--timeout ,表示當(dāng)某個節(jié)點失聯(lián)的時間超過了配置的 timeout時,才可以認定該節(jié)點出現(xiàn)故障,需要進行主從切換。如果沒有這個選項,網(wǎng)絡(luò)抖動會導(dǎo)致主從頻繁切換 (數(shù)據(jù)的重新復(fù)制)。

        Redis集群選舉原理

        當(dāng) slave 發(fā)現(xiàn)自己的 master 變?yōu)?fail 狀態(tài)時,便嘗試進行 FailOver,以期成為新的 master。由于掛掉的 master 有多個 slave,所以這些 slave 要去競爭成為 master 節(jié)點,過程如下:

        (1)slave1,slave2都 發(fā)現(xiàn)自己連接的 master 狀態(tài)變?yōu)?Fail;

        (2)它們將自己記錄的集群 currentEpoch(選舉周期) 加1,并使用 gossip 協(xié)議去廣播 FailOver_auth_request 信息;

        (3)其他節(jié)點接收到slave1、salve2的消息(只有master響應(yīng)),判斷請求的合法性,并給 slave1 或 slave2 發(fā)送 FailOver_auth_ack(對每個 epoch 只發(fā)一次ack);在一個選舉周期中,一個master只會響應(yīng)第一個給它發(fā)消息的slave;

        (4)slave1 收集返回的 FailOver_auth_ack,它收到超過半數(shù)的 master 的 ack 后變成新 master;(這也是集群為什么至少需要3個master的原因,如果只有兩個master,其中一個掛了之后,只剩下一個主節(jié)點是不能選舉成功的)

        (5)新的master節(jié)點去廣播 Pong 消息通知其他集群節(jié)點,不需要再去選舉了。

        從節(jié)點并不是在主節(jié)點一進入 FAIL 狀態(tài)就馬上嘗試發(fā)起選舉,而是有一定延遲,一定的延遲確保我們等待FAIL狀態(tài)在集群中傳播,slave如果立即嘗試選舉,其它masters或許尚未意識到FAIL狀態(tài),可能會拒絕投票。

        延遲計算公式: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ā)起選舉(理論上)

        Redis集群為什么至少需要三個master節(jié)點,并且推薦節(jié)點數(shù)為奇數(shù)?
        因為新master的選舉需要大于半數(shù)的集群master節(jié)點同意才能選舉成功,如果只有兩個master節(jié)點,當(dāng)其中一個掛了,是達不到選舉新master的條件的。
        奇數(shù)個master節(jié)點可以在滿足選舉該條件的基礎(chǔ)上節(jié)省一個節(jié)點,比如三個master節(jié)點和四個master節(jié)點的集群相比,大家如果都掛了一個master節(jié)點都能選舉新master節(jié)點,如果都掛了兩個master節(jié)點都沒法選舉新master節(jié)點了,所以奇數(shù)的master節(jié)點更多的是從節(jié)省機器資源角度出發(fā)說的。

        集群是否完整才能對外提供服務(wù)
        當(dāng)redis.conf的配置cluster-require-full-coverage為no時,表示當(dāng)負責(zé)一個插槽的主庫下線且沒有相應(yīng)的從庫進行故障恢復(fù)時,集群仍然可用,如果為yes則集群不可用。

         5、Java 操作 Redis 集群

        方式一(Jedis):

        (1)引入jedis的maven坐標(biāo)

        <dependency\>
        <groupId\>redis.clients</groupId\>
        <artifactId\>jedis</artifactId\>
        <version\>2.9.0</version\>
        </dependency\>
        復(fù)制代碼

        (2)Java編寫的代碼,如下:

        public class JedisClusterTest { public static void main(String\[\] args) throws IOException {

        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.1.1", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.1.1", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.1.2", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.1.2", 8002));
        jedisClusterNode.add(new HostAndPort("192.168.1.3", 8001));
        jedisClusterNode.add(new HostAndPort("192.168.1.3", 8002));
        JedisCluster jedisCluster \= null; try { //connectionTimeout:指的是連接一個url的連接等待時間 //soTimeout:指的是連接上一個url,獲取response的返回等待時間
        jedisCluster = new JedisCluster(jedisClusterNode, 6000, 5000, 10, "redis-pw", config);
        System.out.println(jedisCluster.set("name", "zhangsan"));
        System.out.println(jedisCluster.get("name"));
        } catch (Exception e) {
        e.printStackTrace();
        } finally { if (jedisCluster != null) {
        jedisCluster.close();
        }
        }
        }
        }
        復(fù)制代碼

        方式二:SpringBoot 整合 Redis

        (1)引入maven坐標(biāo)

        <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\>
        復(fù)制代碼

        (2)配置文件

        server:
        port: 8080 spring:
        redis:
        database: 0 timeout: 3000 password: redis\-pw
        cluster:
        nodes: 192.168.0.61:8001,192.168.0.62:8002,192.168.0.63:8003,192.168.0.61:8004,192.168.0.62:8005,192.168.0.6
        3:8006 lettuce:
        pool:
        max‐idle: 50 min‐idle: 10 max‐active: 100 max‐wait: 1000
        復(fù)制代碼

        (3)java代碼,如下:

        @RestController public class TestController { private static final Logger logger = LoggerFactory.getLogger(TestController.class);

        @Autowired private StringRedisTemplate stringRedisTemplate;

        @RequestMapping("/test\_cluster") public void testCluster() throws InterruptedException {
        stringRedisTemplate.opsForValue().set("user:name", "wangwu");
        System.out.println(stringRedisTemplate.opsForValue().get("user:name"));
        }
        }
        復(fù)制代碼

        作者:風(fēng)止雨歇 鏈接:www.cnblogs.com/yufeng218/p…來源:cnblogs




        瀏覽 65
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            免费福利在线视频 | 久久日免费视频 | 桥本爱实大尺度三级 | 国产精彩视频 | 中国一级淫片 | 唐山熟女工棚嗷嗷叫 | 黄色在线播放国产 | www.激情五月天.com | 一区二区三区国产精品 | 亚洲电影欧美片日韩 |