国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JAVA面試題分享五百六十五:為啥Redis用哈希槽,不用一致性哈希?

這篇具有很好參考價值的文章主要介紹了JAVA面試題分享五百六十五:為啥Redis用哈希槽,不用一致性哈希?。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

首先,從使用hash取模數(shù)據(jù)分片開始說起

無論是哈希槽,還是一致性hash,都屬于hash取模數(shù)據(jù)分片。

先從經(jīng)典的hash取模數(shù)據(jù)分片說起

假如 Redis集群的節(jié)點數(shù)為3個,使用經(jīng)典的hash取模算法進(jìn)行數(shù)據(jù)分片,實際上就是一個節(jié)點一個數(shù)據(jù)分片,分為3片而已。

每次請求使用 hash(key) % 3 的方式計算對應(yīng)的節(jié)點,或者進(jìn)行 分片的路由。

經(jīng)典哈希取模分片的問題和對策:

哈希取模分片有一個核心問題:對擴(kuò)容不友好,擴(kuò)容的時候數(shù)據(jù)遷移規(guī)模太大。

比如,把節(jié)點從3個擴(kuò)展到4個, 具體如下:

原來的分片路由算法是:hash(key) % 3

現(xiàn)在的分片路由算法是:hash(key) % 4

分片路由算法調(diào)整之后,那么,大量的key需要進(jìn)行節(jié)點的遷移。

換句話,即當(dāng)增加或減少節(jié)點時,原來節(jié)點中的80%以上的數(shù)據(jù),可能會進(jìn)行遷移操作,對所有數(shù)據(jù)重新進(jìn)行分布。

如何應(yīng)對呢?

規(guī)避的措施之一:如果一定要采用哈希取模分片,建議使用多倍擴(kuò)容的方式,這樣只需要適移50%的數(shù)據(jù)。例如以前用3個節(jié)點保存數(shù)據(jù),擴(kuò)容為比以前多一倍的節(jié)點即6個節(jié)點來保存數(shù)據(jù),這樣移動50%的數(shù)據(jù)即可。

規(guī)避的措施之一:采用一致性hash分片方法。

redis為什么使用哈希槽而不用一致性哈希,JAVA 面試題分享,Redis 面試題分享,java,redis,哈希算法

哈希取模分片優(yōu)點:

  • 配置簡單:對數(shù)據(jù)進(jìn)行哈希,然后取余

哈希取模分片缺點:

  • 數(shù)據(jù)節(jié)點伸縮時,導(dǎo)致大量數(shù)據(jù)遷移

  • 遷移數(shù)量和添加節(jié)點數(shù)據(jù)有關(guān),建議翻倍擴(kuò)容

一致性hash算法

如果redis使用一致性hash算法進(jìn)行數(shù)據(jù)分片,那么核心會涉及到的兩個階段:

  • 第一階段,需要完成key到slot槽位之間的映射。

  • 第二階段,需要完成slot槽位到 redis node節(jié)點之間的映射。

首先看第一階段。

第一階段,需要完成key到slot槽位之間的映射

第一階段,使用了哈希取模的方式,不同的是: ?對 2^32 這個固定的值進(jìn)行取模運算。

注意,這里的取模的除數(shù),是 2^32 , 相當(dāng)于 ?2^32個槽位, 英文是 slot 。

通過這個槽位的計算,可以確定 key => slot 之間的映射關(guān)系。

第二階段,需要完成slot槽位到 redis node節(jié)點之間的映射。

第二階段,需要完成slot槽位到 redis node節(jié)點之間的映射。

如何完成 slot ?槽位到node 節(jié)點之間的映射呢?

這里,需要 采用一種特殊的結(jié)構(gòu):Hash槽位環(huán)。

Hash槽位環(huán)

把一致哈希算法是對 2^32 ?slot 槽位虛擬成一個圓環(huán),環(huán)上的對應(yīng) 0~2^32 刻度,

如何完成 slot ?槽位到node 節(jié)點之間的映射呢?

假設(shè)有4個redis 節(jié)點, 可以把 2^32 ?slot 槽位環(huán)分成4段, 每一個redis 節(jié)點負(fù)責(zé)存儲一個slot分段

如何對每一個key進(jìn)行node 路由呢?

第一步?進(jìn)行slot槽位計算:每一個key進(jìn)行hash運算,被哈希后的結(jié)果 2^32 ?取模,獲得slot 槽位、

第二步?在hash槽位環(huán)上,按順時針去找最近的redis節(jié)點,這個key將會被保存在這個節(jié)點上。

一致性哈希原理:

將所有的數(shù)據(jù)用hash取模, 映射到 2^32個槽位。

把2^32個槽位 當(dāng)做一個環(huán),把N個redis 節(jié)點瞬時間放置在槽位環(huán)上,從而把槽位環(huán)分成N段,每redis 節(jié)點負(fù)責(zé)一個分段。

當(dāng)key在槽位環(huán)上路由的時候,按順時針去找最近的redis節(jié)點,這個key將會被保存在這個節(jié)點上。

來看一致性哈希 三個經(jīng)典場景:

經(jīng)典場景1:Key入環(huán)

下圖我們四個key(Key1/Key2/Key3)經(jīng)過哈希計算,放入下面環(huán)中,第一步是進(jìn)行hash計算,取模后得到slot槽位。

找到了slot槽位,相當(dāng)于已經(jīng)成功映射到哈希環(huán)上,

然后將槽位按順時針方向,找到離自己最近的redis節(jié)點上,將value存儲到那個節(jié)點上。

經(jīng)典場景2:新增redis節(jié)點

現(xiàn)在,需要對redis 節(jié)點進(jìn)行擴(kuò)容, 在redis1 和 redis2之間,新增加點redis 5。

具體的操作是:在hash槽位環(huán)上,把redis 5節(jié)點放置進(jìn)去

添加了新節(jié)點之后,對所有的redis 2上的數(shù)據(jù),進(jìn)行重新的檢查。

如果redis 2上的數(shù)據(jù),順時針方式最近的新節(jié)點不是redis 2而是 redis 5的話,需要進(jìn)行遷移,遷移到redis 5。

比如,上圖的key2,需要從redis 2遷移 redis 5。

而其他節(jié)點上的數(shù)據(jù),不受影響。比如redis1、redis3、redis4上的數(shù)據(jù)不受影響。上圖中,key1和key3不受影響

經(jīng)典場景3:刪除redis節(jié)點

假設(shè),刪除hash環(huán)上的節(jié)點redis 2

那么存儲在redis 2節(jié)點上的key2,將會重新映射找到離它最近的節(jié)點redis3,如下圖

另外,key1、key3不受影響。

經(jīng)典哈希取模與一致性hash的對比:

前面講到,假設(shè)Redis 集群使用經(jīng)典哈希取模分片, 缺點是在數(shù)據(jù)節(jié)點伸縮時,導(dǎo)致大量數(shù)據(jù)遷移:

  • 最少50%的數(shù)據(jù)要遷移,這個是在翻倍擴(kuò)容場景

  • 一般有80%以上的數(shù)據(jù)要遷移。

假設(shè)Redis 集群使用一致性哈希取模分片, 通過上面的一致性哈希取模新增節(jié)點、一致性哈希取模刪除節(jié)點的分析之后, 可以得到:

  • 一致性hash在伸縮的時候, 需要遷移的數(shù)據(jù)不到25%(假設(shè)4個節(jié)點)。

  • 和普通hash取模分片相比, 一致性哈希取模分片需要 遷移的數(shù)據(jù)規(guī)??s小2倍以上。

一致性hash的數(shù)據(jù)不平衡(數(shù)據(jù)傾斜)問題

標(biāo)準(zhǔn)的一致性hash,存在一個大的問題:數(shù)據(jù)不平衡(數(shù)據(jù)傾斜)問題。

回顧一下,一致性hash算法的兩個階段:

  • 第一階段,需要完成key到slot槽位之間的映射。

  • 第二階段,需要完成slot槽位到 redis node節(jié)點之間的映射。

在這個兩階段中,數(shù)據(jù)不平衡(數(shù)據(jù)傾斜)問題的來源在第二階段:

  • 第一個階段,hash算法是均勻的。

  • 第二個階段,如果某個節(jié)點宕機(jī),那么就會出現(xiàn)節(jié)點的不平衡。

遷移之后,發(fā)生了 嚴(yán)重的數(shù)據(jù)傾斜,或者不平衡。Redis 3上4個key,而redis 1、redis 4上只有1個key。

這樣,redis2 上的數(shù)量很多,此時會導(dǎo)致節(jié)點壓力陡增。

旱澇不均。

那如何解決這個旱澇不均問題呢?答案是通過?虛擬節(jié)點。

什么是 虛擬節(jié)點?

虛擬節(jié)點?可以理解為邏輯節(jié)點,不是物理節(jié)點。?假設(shè)在hash環(huán)上,引入 32 個虛擬 reids節(jié)點。

如何找到物理節(jié)點呢??辦法是增加一次映射:虛擬節(jié)點到物理節(jié)點的映射。

假設(shè)加上一層 ?32 個虛擬 redis節(jié)點到 4個 ?redis 物理節(jié)點映射。一種非常簡單的map參考映射方案

假設(shè)物理節(jié)點 redis 3被移除,那么,把redis 3負(fù)責(zé)的邏輯節(jié)點,二次分配到其他三個物理節(jié)點就行了

無論如何,通過虛擬節(jié)點,就會大大減少了 一致性hash 算法的數(shù)據(jù)傾斜/數(shù)據(jù)不平衡。

一致性hash的簡易實現(xiàn)

可以使用TreeMap 來實現(xiàn)一致性hash,原因有二:

  • TreeMap的key是有序,

  • 使用TreeMap的ceilingEntry(K k) 方法,可以返回大于或等于給定參數(shù)K的鍵, 這就是映射到的節(jié)點。

TreeMap是一個小頂堆,默認(rèn)是根據(jù)key的自然排序來組織(比如integer的大小,String的字典排序)。底層是根據(jù)紅黑樹的數(shù)據(jù)結(jié)構(gòu)構(gòu)建的。

這里使用TreeMap的ceilingEntry(K key) 方法,該方法用來返回與該鍵至少大于或等于給定鍵,如果不存在這樣的鍵的鍵 - 值映射,則返回null相關(guān)聯(lián)。

一致性hash的簡易實現(xiàn),參考代碼如下:

package?com.th.treemap;

import?java.util.HashMap;
import?java.util.Iterator;
import?java.util.Map;
import?java.util.TreeMap;

public?class?ConsistentHash?{
????/**
?????*?假設(shè)我們一共初始化有8個節(jié)點(可以是ip,?就理解為ip吧);
?????*?把?1024個虛擬節(jié)點跟?8個資源節(jié)點相對應(yīng)
?????*/
????public?static?Map<Integer,?String>?nodeMap?=?new?HashMap<>();
????public?static?int?V_redisS?=?1024;?//?假設(shè)我們的環(huán)上有1024個虛擬節(jié)點
????static?TreeMap<Integer,?String>?virtualHashRingMap?=?new?TreeMap<>();
????private?static?final?Integer?REAL_redis_COUNT?=?8;
????static?{
????????nodeMap.put(0,?"redis_0");
????????nodeMap.put(1,?"redis_1");
????????nodeMap.put(2,?"redis_2");
????????nodeMap.put(3,?"redis_3");
????????nodeMap.put(4,?"redis_4");
????????nodeMap.put(5,?"redis_5");
????????nodeMap.put(6,?"redis_6");
????????nodeMap.put(7,?"redis_7");
?
?
????????for?(Integer?i?=?0;?i?<?V_redisS;?i++)?{
????????????//?每個虛擬節(jié)點跟其取模的余數(shù)的?redisMap?中的key相對應(yīng);
????????????//?下面刪除虛擬節(jié)點的時候,?就可以根據(jù)取模規(guī)則來刪除?TreeMap中的節(jié)點了;
????????????virtualHashRingMap.put(i,?nodeMap.get(i?%?REAL_redis_COUNT));
????????}
????}

????/**
?????*?輸入一個id
?????*
?????*?@param?value
?????*?@return
?????*/
????public?static?String?getRealServerredis(String?value)?{
????????//?1.?傳遞來一個字符串,?得到它的hash值
????????Integer?vredis?=?value.hashCode()?%?1024;
????????//?2.找到對應(yīng)節(jié)點最近的key的節(jié)點值
????????String?realredis?=?virtualHashRingMap.ceilingEntry(vredis).getValue();
?
?
????????return?realredis;
????}
?
????/**
?????*?模擬刪掉一個物理可用資源節(jié)點,?其他資源可以返回其他節(jié)點
?????*/
????public?static?void?dropBadredis(String?redisName)?{
????????int?redisk?=?-1;
????????//?1.?遍歷?redisMap?找到故障節(jié)點?redisName對應(yīng)的key;
????????for?(Map.Entry<Integer,?String>?entry?:?nodeMap.entrySet())?{
????????????if?(redisName.equalsIgnoreCase(entry.getValue()))?{
????????????????redisk?=?entry.getKey();
????????????????break;
????????????}
????????}
????????if?(redisk?==?-1)?{
????????????System.err.println(redisName?+?"在真實資源節(jié)點中無法找到,?放棄刪除虛擬節(jié)點!");
????????????return;
????????}
?
????????//?2.?根據(jù)故障節(jié)點的?key,?對應(yīng)刪除所有?chMap中的虛擬節(jié)點
????????Iterator<Map.Entry<Integer,?String>>?iter?=?virtualHashRingMap.entrySet().iterator();
????????while?(iter.hasNext())?{
????????????Map.Entry<Integer,?String>?entry?=?iter.next();
????????????int?key?=?entry.getKey();
????????????String?value?=?entry.getValue();
????????????if?(key?%?REAL_redis_COUNT?==?redisk)?{
????????????????System.out.println("刪除物理節(jié)點對應(yīng)的虛擬節(jié)點:?["?+?value?+?"?=?"?+?key?+?"]");
????????????????iter.remove();
????????????}
????????}
????}
?
????public?static?void?main(String[]?args)?{
????????//?1.?一個字符串請求(比如請求字符串存儲到8個節(jié)點中的某個實際節(jié)點);
????????String?requestValue?=?"技術(shù)自由圈";
????????//?2.?打印虛擬節(jié)點和真實節(jié)點的對應(yīng)關(guān)系;
????????System.out.println(virtualHashRingMap);
????????//?3.?核心:?傳入請求信息,?返回實際調(diào)用的節(jié)點信息
????????System.out.println(getRealServerredis(requestValue));
????????//?4.?刪除某個虛擬節(jié)點后
????????dropBadredis("redis_2");
????????System.out.println("==========刪除?redis_2?之后:?================");
????????System.out.println(getRealServerredis(requestValue));
????}
}

回顧下一致性 Hash 算法

接下來,簡單回顧下一致性 Hash 算法:

為了避免出現(xiàn)數(shù)據(jù)傾斜問題,一致性 Hash 算法引入了虛擬節(jié)點的機(jī)制。

虛擬節(jié)點和物理節(jié)點解耦,引入虛擬節(jié)點到物理節(jié)點之間的映射,最終每個物理節(jié)點在哈希環(huán)上會有多個虛擬節(jié)點存在,引入了虛擬節(jié)點的機(jī)制之后,數(shù)據(jù)定位算法不變,只是多了一步虛擬節(jié)點到實際節(jié)點的映射,例如定位到“redis-1-1”、“redis-1-2”、“redis-1-3”三個虛擬節(jié)點,都能映射到 ?redis-1 上。

引入虛擬節(jié)點,可以大大削弱甚至避免數(shù)據(jù)傾斜問題。在實際應(yīng)用中,通常將虛擬節(jié)點數(shù)設(shè)置為32甚至更大。

Redis為什么使用哈希槽而不用一致性哈希

回到正題,既然一致性hash那么完美,兩大優(yōu)點:

  • 既很少的數(shù)據(jù)遷移,

  • 又很少數(shù)據(jù)傾斜。

Redis為什么使用哈希槽而不用一致性哈希呢?

這個和redis 集群的架構(gòu)特點有關(guān)系, redis 集群的架構(gòu)特點,主要有兩點:

  • 去中心化

  • 方便伸縮 ?(自動伸縮、手動伸縮都可以)

Redis Cluster集群核心特點一:去中心化

關(guān)于分布式集群的設(shè)計,一般要考慮以下幾個方面:

  • 元數(shù)據(jù)存儲,包括 數(shù)據(jù)分片與存儲節(jié)點的映射關(guān)系等

  • 節(jié)點間通信,包括信息互通、健康狀態(tài)等

  • 擴(kuò)縮容,比如 考慮數(shù)據(jù)遷移情況

  • 高可用,當(dāng)節(jié)點出現(xiàn)故障時,能及時自動的進(jìn)行故障轉(zhuǎn)移

先看分布式集群的設(shè)計中的核心:元數(shù)據(jù)存儲 ?設(shè)計。

有兩種架構(gòu)模式:

  • 中心化的存儲架構(gòu)

  • 去中心化的存儲架構(gòu)

中心化的 元數(shù)據(jù)存儲架構(gòu)

首先,看中心化的 元數(shù)據(jù)存儲架構(gòu)

常見的中間組件來存儲元數(shù)據(jù),比如 zk、etcd、nacos 等等;

在客戶端看來,先從協(xié)調(diào)節(jié)點獲取元數(shù)據(jù),然后再負(fù)載均衡到某個服務(wù)節(jié)點

在kafka2.8版本開始嘗試從服務(wù)架構(gòu)中去掉zookeeper,到了3.0版本這個工作基本上完成,這是kafka的一個非常重要的里程碑。2.8.0版本將是第一個不需要ZooKeeper就可以運行Kafka的版本,而這也被稱為Kafka Raft Metadata mode(Kafka Raft 元數(shù)據(jù)模式),或許就是一個會被后人銘記的版本。

ZooKeeper是一個獨立的軟件,但是ZooKeeper使得Kafka整個系統(tǒng)變得復(fù)雜,因此官方?jīng)Q定使用內(nèi)部仲裁控制器來取代ZooKeeper。過去Kafka因為帶著ZooKeeper,因此被認(rèn)為擁有沉重的基礎(chǔ)設(shè)施,而在移除ZooKeeper之后,Kafka更輕巧更適用于小規(guī)模工作負(fù)載,輕量級單體程序適合用于邊緣以及輕量級硬件解決方案。

redis為什么使用哈希槽而不用一致性哈希,JAVA 面試題分享,Redis 面試題分享,java,redis,哈希算法

KRaft

2.8.0版本之后的Kafka集群,元數(shù)據(jù)管理,本質(zhì)上從中心化演進(jìn)到了去中心化,通過raft協(xié)議保證元數(shù)據(jù)寫入的數(shù)據(jù)一致性。

2.8版本之前zookeeper-based Kafka集群,集群有唯一的Controller,這個Controller是從所有的broker中選出,負(fù)責(zé)Watch Zookeeper、partition的replica的集群分配,以及l(fā)eader切換選舉等流程。

2.8.0版本之后with quorum kafka集群將其引入的共識協(xié)議稱為Event-driven consensus,quorum controller不是單個節(jié)點,而是一個小的集群,每個 controller 節(jié)點內(nèi)部維護(hù)RSM(replicated state machine),不像之前的zookeeper-based,controller 節(jié)點不需要首先訪問zookeeper獲取狀態(tài)信息。Kafka的元數(shù)據(jù)會通過raft一致性協(xié)議寫入quorum,并且系統(tǒng)會定期做snapshot。

KRaft中Controller可以被指定為奇數(shù)個節(jié)點(一般情況下3或5)組成raft quorum。controller節(jié)點中有一個active(選為leader),其他的hot standby。這個active controller集群負(fù)責(zé)管理Kafka集群的元數(shù)據(jù),通過raft協(xié)議達(dá)成共識。因此,每個controller都擁有幾乎update-to-date的Metadata,所以controller集群重新選主時恢復(fù)時間很短。

redis為什么使用哈希槽而不用一致性哈希,JAVA 面試題分享,Redis 面試題分享,java,redis,哈希算法

event-drive

集群的其他節(jié)點通過配置選項controller.quorum.voters獲取controller。zookeeper-based Kafka集群中,controller發(fā)送Metadata給其他的broker。現(xiàn)在broker需要主動向active controller拉取Metadata。一旦broker收到Metadata,它會將其持久化。這個broker持久化Metadata的優(yōu)化意味著一般情況下active controller不需要向broker發(fā)送完整的Metadata,只需要從某個特定的offset發(fā)送即可。但如果遇到一個新上線的broker,Controller可以發(fā)送snapshot給broker(類似raft的InstallSnapshot RPC)。

去中心化的 元數(shù)據(jù)存儲架構(gòu)

使用去中心化的方式,讓每個redis節(jié)點、甚至客戶端都維護(hù)一份元數(shù)據(jù)信息

集群間的redis 采用特定的一些通信協(xié)議(如raft協(xié)議、gossip協(xié)議)進(jìn)行信息交換,以保證集群數(shù)據(jù)整體一致性。

有關(guān)Raft 協(xié)議的內(nèi)容,請參見后面的 《附錄1:Raft 協(xié)議》

有關(guān)gossip協(xié)議的內(nèi)容,請參見后面的 《附錄2:gossip 協(xié)議》

redis ?client客戶端請求直連集群任意節(jié)點,

當(dāng)redis client訪問任意一個節(jié)點,該節(jié)點總能定向到正確的節(jié)點去處理(即使該請求不歸屬于它處理,但它知道誰能處理)。

去中心化場景如何保證元數(shù)據(jù)一致?

如果每個redis節(jié)點都要存儲一份元數(shù)據(jù)信息(分片與節(jié)點的映射關(guān)系),那么問題來了?

在數(shù)據(jù)更新時,必然可能存在一定的數(shù)據(jù)一致性的延遲,這就要求更高的節(jié)點間通信效率。如何保證呢?

問題1:redis 如何進(jìn)行數(shù)據(jù)分片的?

redis 集群的元數(shù)據(jù)信息,核心就是數(shù)據(jù)分片shard與節(jié)點的映射關(guān)系。

redis 如何進(jìn)行數(shù)據(jù)分片的?redis 本質(zhì)上也是 hash 之后取模分片。

第一步:hash。hash算法的功效,核心就是保證數(shù)據(jù)不傾斜,或者說保證分布均勻。那么,redis cluster 的hash算法,采用的是 crc16 哈希算法。

第二步:取模。就是槽位的數(shù)量, redis 集群的把數(shù)據(jù)分為16484 個細(xì)粒度分片,或者說 16484 個slot槽位。

redis cluster 采用 crc16 哈希算法,并使用固定長度的模 16384,其中,這 16484 個哈希分片也稱之為 哈希槽,然后將這些哈希槽盡可能均勻的分配給不同的服務(wù)節(jié)點。

redis cluster 哈希槽

redis cluster 還是采用hash取模分片,數(shù)據(jù)落在哪個分片(這里對應(yīng)到槽位)的算法為

?slot?=?Hash(key)?%?16484?

這里,使用固定長度的模 16384(2^14),這 16484 個哈希分片也稱之為 哈希槽,然后將這些哈希槽盡可能均勻的分配給不同的服務(wù)節(jié)點。具體如下圖:

集群將數(shù)據(jù)劃分為 16384 個槽位(哈希槽),每個Redis服務(wù)節(jié)點分配了一部分槽位。

從hash取模這個角度來說,redis hash 分片和一致性哈希是一樣的。

所不同的是:

  • 第一:槽位規(guī)模不同。redis 集群將數(shù)據(jù)劃分為 16384 (2^14)個槽位(哈希槽),一致性hash有 ?2^32個槽位。

  • 第二:hash slot和node 節(jié)點的映射關(guān)系不同。一致性hash是哈希環(huán)順時針映射, redis 哈希槽是靜態(tài)映射。

大家回顧一下,一致性hash 怎么 進(jìn)行hash slot和node 節(jié)點 映射的呢?

一致性hash的映射規(guī)則是,每個槽按照順時針方向找到最近的一個節(jié)點便是對應(yīng)所屬的存儲服務(wù)器,簡稱為順時針映射

而redis hash 分片,屬于靜態(tài)映射類型。直接把slot槽位靜態(tài)分配到redis 節(jié)點,當(dāng)然,靜態(tài)分配的時候需要盡可能保證均勻。

假定我們有三個服務(wù)節(jié)點,盡可能均勻分配之后,分配關(guān)系如下:

  • 節(jié)點 A 包含哈希槽從 0 到 5460.

  • 節(jié)點 B 包含哈希槽從 ?5461 到 10923.

  • 節(jié)點 C 包含哈希槽從 10924 到 16383.

增加節(jié)點

還記得我們搞集群的目的是啥?單機(jī)容量不足,需要擴(kuò)容成多機(jī)組成的集群,然后將數(shù)據(jù)盡可能的均分到各個節(jié)點。

redis cluster ,我們可以很容易的增加或者刪除節(jié)點,

新增一個節(jié)點4,redis cluster的這種做法是從各個節(jié)點的前面各拿取一部分slot(槽)到4上。

當(dāng)我們新增一個節(jié)點4 時,節(jié)點1、2、3的數(shù)據(jù)會遷移一部分到節(jié)點 4;實現(xiàn)4個節(jié)點 數(shù)據(jù)均勻:

此時服務(wù)1、2、3、4通過分配各自有了對應(yīng)的哈希槽,新增節(jié)點后集群會自動進(jìn)行哈希槽的重新平均分配,比如上圖中四個節(jié)點中每個節(jié)點的槽位數(shù)是:18384 / 4 = 4096。

當(dāng)然,還可以適當(dāng)調(diào)整,或者手動進(jìn)行分配。

具體來說,可以使用命令 【cluster addslots】為每個節(jié)點自定義分配槽的數(shù)量,手動調(diào)整的場景是:比如有些節(jié)點的機(jī)器性能好,內(nèi)存有128G,那就可以配置更多槽位。

減少節(jié)點

如果減少一個節(jié)點4,redis cluster同樣會自動進(jìn)行槽數(shù)量的重新計算。

當(dāng)我們刪除節(jié)點 4 時,節(jié)點4的slot數(shù)據(jù)會均勻的遷移到節(jié)點 1、節(jié)點 2、節(jié)點3。

刪除節(jié)點C之后,此時服務(wù)A、B節(jié)點中每個節(jié)點的槽位數(shù)是:18384 / 3 = 6128

和一致性哈希不同的是,redis cluster 集群節(jié)點全員參與,目標(biāo)是達(dá)到集群節(jié)點間數(shù)據(jù)盡可能均勻的效果。

對比之前,得到一個結(jié)論:

  • 一致性哈希 優(yōu)先考慮的是:如何實現(xiàn) 最少的數(shù)據(jù)遷移。

  • redis cluster ?哈希槽分片 優(yōu)先考慮的是:?如何 實現(xiàn)數(shù)據(jù)的均勻。

值得注意,redis 集群數(shù)據(jù)遷移是以哈希槽位單位,也就是說,同一個槽的數(shù)據(jù)只會遷移到一個目的節(jié)點。

問題2:redis 如何管理元數(shù)據(jù)的一致性

redis 采用?流言蜚語?協(xié)議,顧名思義,就像流言、八卦一樣,一傳十、十傳百這樣傳遞下去,直到所有節(jié)點的元數(shù)據(jù)信息達(dá)成一致。

有關(guān)gossip協(xié)議的內(nèi)容,請參見后面的 《附錄2:gossip 協(xié)議》

有關(guān)Raft 協(xié)議的內(nèi)容,請參見后面的 《附錄1:Raft 協(xié)議》

redis cluster 如何實現(xiàn) Gossip 協(xié)議的?

我們知道,每個集群節(jié)點都維護(hù)了集群其他節(jié)點的信息,其通信名單就是根據(jù)該列表來的。

首先,這個工作也是由周期性的時間事件來負(fù)責(zé)處理,每次從通信名單中隨機(jī)選擇 5 個節(jié)點,然后從這批名單中選擇最久未通信的節(jié)點。然后構(gòu)造?PING 請求,嘗試與其進(jìn)行通信,請求報文中會攜帶自己負(fù)責(zé)的那些哈希槽以及部分掌握的其他節(jié)點負(fù)責(zé)的哈希槽信息。

最后是接收?PONG?響應(yīng)報文,該報文和 PING 請求報文基本一致,包含的信息是對方節(jié)點處理的哈希槽以及掌握的部分其他節(jié)點信息,至于要發(fā)送多少其他節(jié)點的信息,這個可以通過一些參數(shù)來控制。

這樣一來一回,雙方的信息算是打通了,順便還打通了雙方掌握的集群其他節(jié)點的信息。

然后多幾個這樣的來回,集群信息就基本一致了。

總體來說,Gossip 協(xié)議 包括兩個部分:

  • 第一個部分是通訊報文:槽(slots)數(shù)據(jù)結(jié)構(gòu)實際上是一個二進(jìn)制數(shù)組,數(shù)組長度為 2048 個字節(jié),16384 個二進(jìn)制位,也就是 2k 大小。這里不包括其他的基礎(chǔ)報文數(shù)據(jù)。

  • 第二個部分是報文類型:集群節(jié)點通過 PING,PONG 方式(類似心跳報文)來傳遞集群的元數(shù)據(jù)信息,PING、PONG 都采用相同的數(shù)據(jù)結(jié)構(gòu)攜帶信息,一來一回便知曉了雙方的元數(shù)據(jù)信息,多個來回,整個集群元數(shù)據(jù)信息就一致了,這便是?Gossip 協(xié)議。

你也注意到了,上面的通信節(jié)點是隨機(jī)選擇的,如果某個節(jié)點一直未進(jìn)行通信,節(jié)點就無法打通?

沒錯,redis cluster 也是考慮了這種情況,所以會定期的選擇那些長時間沒有通信的節(jié)點,然后進(jìn)行上面的流程進(jìn)行通信。

客戶端如何感知槽位?

Redis cluster的主節(jié)點各自負(fù)責(zé)一部分slot,那么客戶端的請求的key是如何客戶端如何感知槽位?

如何定位到具體的節(jié)點,然后返回對應(yīng)的數(shù)據(jù)的。

首先,Redis-Cli客戶端的會連接到集群中的任何一個節(jié)點,比如redis 2節(jié)點,如下圖:

  1. redis 2節(jié)點 收到命令,首先檢查當(dāng)前key是否存在集群中的節(jié)點

    具體的計算步驟為:

  • step1?? hash 槽位:通過CRC16(key)/ 16384計算出slot

  • step2??檢查slot:?檢查該slot負(fù)責(zé)的節(jié)點是否本地存儲

  • step3??如果slot在本地,就直接就直接返回key對應(yīng)的結(jié)果

  • step4?? 如果slot不在本地,那么會 MOVED重定向(包含槽位和目標(biāo)地址 比如redis 3)給客戶端

  • step5??客戶端轉(zhuǎn)向至正確的節(jié)點(比如redis 3),并再次發(fā)送之前執(zhí)行的命令

問題:每執(zhí)行命令前都可能現(xiàn)在Redis節(jié)點上進(jìn)行MOVED重定向才能找到要執(zhí)行命令的節(jié)點,額外增加了IO開銷。

怎么提升性能呢?使用加了本地緩存的 smart客戶端。

smart客戶端

不過大多數(shù)開發(fā)語言的Redis客戶端都采用 Smart客戶端 支持集群協(xié)議,讓整個訪問就更高效。

smart客戶端,加了 元數(shù)據(jù)的本地緩存。

smart客戶端的主要特點:Redis客戶端在內(nèi)部維護(hù)哈希槽--節(jié)點的映射關(guān)系,這樣就可以在Smart客戶端實現(xiàn)鍵到節(jié)點的查找,避免了再進(jìn)行MOVED重定向。

本地緩存何時初始化呢?最開始的時候,redis會選擇一個運行節(jié)點,初始化槽和節(jié)點映射關(guān)系。

smart客戶端仍然需要MOVED和ASK命令

不過smart客戶端仍然需要MOVED和ASK命令配合,為啥呢?

通常在smart客戶端也需要緩存元數(shù)據(jù)信息(哈希槽與節(jié)點的對應(yīng)關(guān)系),實現(xiàn)更加高效的精準(zhǔn)定位具體的節(jié)點,然而,也很容易發(fā)生客戶端本地緩存更新不及時的情,仍然需要MOVED和ASK命令。

所以,為了保證客戶端不受此類元數(shù)據(jù)變更帶來的影響,cluster 提供了對應(yīng)的一些指令來處理,比如 MOVED、ASK 等指令。

當(dāng)客戶端收到這些指令后,會做出比如重定向、更新客戶端緩存等操作,我們具體來看看:

1)MOVED

當(dāng)節(jié)點發(fā)現(xiàn)鍵所在的槽并非由自己負(fù)責(zé)處理的時候,節(jié)點就會向客戶端返回一個 MOVED 錯誤,指引客戶端轉(zhuǎn)向至正在負(fù)責(zé)槽的節(jié)點。

MOVED 錯誤的格式為:

MOVED?<slot>?<ip>:<port>1.

其中 slot 為鍵所在的槽,而 ip 和 port 則是負(fù)責(zé)處理槽 slot 的節(jié)點的 IP 地址和端口號。

當(dāng)客戶端接收到節(jié)點返回的 MOVED 錯誤時,客戶端會根據(jù) MOVED 錯誤中提供的 IP 地址和端口號,轉(zhuǎn)向至負(fù)責(zé)處理槽 slot 的節(jié)點,并向該節(jié)點重新發(fā)送之前想要執(zhí)行的命令。

一個集群客戶端通常會與集群中的多個節(jié)點創(chuàng)建套接字連接,而所謂的節(jié)點轉(zhuǎn)向?qū)嶋H上就是換一個套接字來發(fā)送命令。

如果客戶端尚未與想要轉(zhuǎn)向的節(jié)點創(chuàng)建套接字連接,那么客戶端會先根據(jù) MOVED 錯誤提供的 IP 地址和端口號來連接節(jié)點,然后再進(jìn)行轉(zhuǎn)向。

2)ASK

在進(jìn)行重新分片期間,源節(jié)點向目標(biāo)節(jié)點遷移一個槽的過程中,可能會出現(xiàn)這樣一種特殊情況:被遷槽的一部分key還在源節(jié)點,而另一部分key則遷移到目標(biāo)節(jié)點。

當(dāng)客戶端向源節(jié)點發(fā)送一個與數(shù)據(jù)庫鍵有關(guān)的命令,并且命令要處理的數(shù)據(jù)庫鍵恰好就屬于正在被遷移的槽時:

  • 源節(jié)點會先在本地查找指定的鍵,如果找到的話,就直接執(zhí)行客戶端發(fā)送的命令。

  • 如果源節(jié)點本地沒找到,那么這個鍵已經(jīng)被遷移到了目標(biāo)節(jié)點,源節(jié)點將向客戶端返回一個 ASK 響應(yīng),指引客戶端轉(zhuǎn)向正在導(dǎo)入槽的目標(biāo)節(jié)點,

  • 客戶端收到ASK響應(yīng),再次發(fā)送之前想要執(zhí)行的命令。

客戶端將收到如下ASK 響應(yīng):

ASK?<slot>?<ip>:<port>1.

ASK 和 MOVED 都會導(dǎo)致客戶端轉(zhuǎn)向,它們有哪些區(qū)別?

  • MOVED 代表槽的負(fù)責(zé)權(quán)已經(jīng)完成從一個節(jié)點轉(zhuǎn)移到了另一個節(jié)點,在客戶端收到關(guān)于槽 i 的MOVED 之后,客戶端槽位映射關(guān)系緩存關(guān)系也會刷新,客戶端本地的槽位映射關(guān)系刷新之后,后面節(jié)點關(guān)于槽 i 的請求可以直接發(fā)往 MOVED 所指向的節(jié)點。

  • ASK 只是兩個節(jié)點在遷移槽的過程中使用的一種臨時措施:在客戶端收到關(guān)于槽 i 的 ASK 之后,客戶端只會在接下來的一次命令請求中,將命令請求發(fā)送至 ASK 所指示的節(jié)點;客戶端槽位映射關(guān)系緩存關(guān)系不會刷新,因此,流程上還是會走「原節(jié)點 -> ASK 重定向目標(biāo)節(jié)點」這一流程。

問題3:為什么Redis Cluster哈希槽數(shù)量是16384 (16K)?

前面講到 redis 哈希與一致性hash所不同的是:

  • 第一:槽位規(guī)模不同。

    redis 集群將數(shù)據(jù)劃分為 16384 個槽位(哈希槽),一致性hash有 ?2^32 個槽位。

  • 第二:hash slot和node 節(jié)點的映射關(guān)系不同。

    一致性hash是哈希環(huán)順時針映射, redis 哈希槽是靜態(tài)映射。

問題是:一致性哈希算法是對2的32次方取模,而哈希槽是對2的14次方取模。為啥Redis 不設(shè)置 2的32次方 個槽位呢?

為啥 16384 (16K) 個槽位, redis 給出的主要原因是:

  • 1:網(wǎng)絡(luò)帶寬的因素:

    Redis節(jié)點間通信時,心跳包會攜帶節(jié)點的所有槽信息,通過這些槽位元數(shù)據(jù)來更新配置。

    所以,槽位數(shù)量不能太多,如果太多,那么通訊的報文就太大了。reids 采用 16384 個插槽,一個槽位占用一個二進(jìn)制為,16384 ?(16384/8=2048)占通訊報文空間 2KB; ?反過來,如果采用 65536 個插槽,占空間 8KB (65536/8)。

  • 2:當(dāng)集群擴(kuò)展到1000個節(jié)點時,也能確保每個master節(jié)點有足夠的插槽,每個節(jié)點16384 /1024=16個槽位,也足夠了

  • 3:Redis Cluster 不太可能擴(kuò)展到超過 1000 個主節(jié)點,太多可能導(dǎo)致網(wǎng)絡(luò)擁堵。

    在實際應(yīng)用中,一個redis cluster集群不超過200個節(jié)點,超過200個節(jié)點就會有大量的gossip 協(xié)議的報文, 很容易出現(xiàn)網(wǎng)絡(luò)擁塞。

關(guān)于這個問題,Redis作者的回答在這里:why redis-cluster use 16384 slots? · Issue #2576 · redis/redis

為什么Redis是使用哈希槽而不是一致性哈希呢?

接下來,我們再總結(jié)一下,為什么Redis是使用哈希槽而不是一致性哈希呢?

首先, Redis哈希槽和一致性哈希,總體的流程都是差不多的,都是兩個階段:

  • 第一階段是:hash 取模

  • 第二階段是:node 映射

第一階段都是 hash 之后取模分片。分為兩步:

  • 第一步:hash。hash算法的功效,核心就是保證數(shù)據(jù)不傾斜,或者說保證分布均勻。redis cluster 的hash算法,采用的是 crc16 哈希算法。

  • 第二步:取模。就是槽位的數(shù)量, redis 集群的把數(shù)據(jù)分為16484 (16K)個slot槽位。一致性哈希是 2的32次方個槽位。

為啥redis cluster 不設(shè)置 2的32次方個槽位呢?主要是考慮節(jié)點數(shù)在1000的規(guī)模一下,而是使用gossip 去中心一致性協(xié)議,數(shù)據(jù)包不能太大,16K 個二進(jìn)制位 2K字節(jié)已經(jīng)很大了。

第二階段是:node 映射。

  • 一致性hash是哈希環(huán)順時針映射,

  • redis 哈希槽是靜態(tài)映射。

通過前面的對比,得到一個結(jié)論:

  • 一致性hash 哈希環(huán)順時針映射 優(yōu)先考慮的是:如何實現(xiàn) 最少的節(jié)點數(shù)據(jù)發(fā)生數(shù)據(jù)遷移。

    一致性hash 哈希環(huán)上面,只有被干掉的節(jié)點順時針方向最近的那一個節(jié)點涉及到數(shù)據(jù)遷移;其他間隔較遠(yuǎn)的節(jié)點,不涉及到數(shù)據(jù)遷移。

  • redis cluster ?哈希槽靜態(tài)映射 優(yōu)先考慮的是:?如何 實現(xiàn)數(shù)據(jù)的均勻。

    redis cluster 各個節(jié)點都會參與數(shù)據(jù)遷移,優(yōu)先保證各個redis節(jié)點承擔(dān)同樣的訪問壓力。

  • 同時,redis cluster ?哈希槽靜態(tài)映射還有一個優(yōu)點,手動遷移。

    redis cluster ?可以自動分配,也可以根據(jù)節(jié)點的性能(比如Memory大?。?手動的調(diào)整slot的分配。

附錄1:Raft 協(xié)議

Raft協(xié)議對標(biāo)Paxos,容錯性和性能都是一致的,但是Raft比Paxos更易理解和實施。系統(tǒng)分為幾種角色:Leader(發(fā)出提案)、Follower(參與決策)、Candidate(Leader選舉中的臨時角色)。

剛開始所有節(jié)點都是Follower狀態(tài),然后進(jìn)行Leader選舉。成功后Leader接受所有客戶端的請求,然后把日志entry發(fā)送給所有Follower,當(dāng)收到過半的節(jié)點的回復(fù)(而不是全部節(jié)點)時就給客戶端返回成功并把commitIndex設(shè)置為該entry的index,所以是滿足最終一致性的。

Leader同時還會周期性地發(fā)送心跳給所有的Follower(會通過心跳同步提交的序號commitIndex),F(xiàn)ollower收到后就保持Follower狀態(tài)(并應(yīng)用commitIndex及其之前對應(yīng)的日志entry),如果Follower等待心跳超時了,則開始新的Leader選舉:首先把當(dāng)前term計數(shù)加1,自己成為Candidate,然后給自己投票并向其它結(jié)點發(fā)投票請求。直到以下三種情況:

  • 它贏得選舉;

  • 另一個節(jié)點成為Leader;

  • 一段時間沒有節(jié)點成為Leader。

在選舉期間,Candidate可能收到來自其它自稱為Leader的寫請求,如果該Leader的term不小于Candidate的當(dāng)前term,那么Candidate承認(rèn)它是一個合法的Leader并回到Follower狀態(tài),否則拒絕請求。

如果出現(xiàn)兩個Candidate得票一樣多,則它們都無法獲取超過半數(shù)投票,這種情況會持續(xù)到超時,然后進(jìn)行新一輪的選舉,這時同時的概率就很低了,那么首先發(fā)出投票請求的的Candidate就會得到大多數(shù)同意,成為Leader。

redis為什么使用哈希槽而不用一致性哈希,JAVA 面試題分享,Redis 面試題分享,java,redis,哈希算法

在Raft協(xié)議出來之前,Paxos是分布式領(lǐng)域的事實標(biāo)準(zhǔn),但是Raft的出現(xiàn)打破了這一個現(xiàn)狀(raft作者也是這么想的,請看論文),Raft協(xié)議把Leader選舉、日志復(fù)制、安全性等功能分離并模塊化,使其更易理解和工程實現(xiàn),將來發(fā)展怎樣我們拭目以待(挺看好)。

Raft協(xié)議目前被用于 cockrouchDB,TiKV等項目中,據(jù)我聽的一些報告來看,一些大廠自己造的分布式數(shù)據(jù)庫也在使用Raft協(xié)議。

附錄2:Gossip 協(xié)議

Gossip協(xié)議與raft協(xié)議最大的區(qū)別就是它是徹底的去中心化的,

Gossip 協(xié)議也叫 Epidemic Protocol(流行病協(xié)議),主要用于消息傳播,是一種一致性算法。

協(xié)議也非常好理解,正如協(xié)議的名稱,如流行病一樣靠“感染”節(jié)點進(jìn)行持續(xù)傳播。

使用 Gossip 協(xié)議的有:Redis Cluster、Consul、Apache Cassandra等。

Gossip協(xié)議基本思想就是:一個節(jié)點想要分享一些信息給網(wǎng)絡(luò)中的其他的節(jié)點,于是隨機(jī)選擇一些節(jié)點進(jìn)行信息傳遞。這些收到信息的節(jié)點接下來把這些信息傳遞給其他一些隨機(jī)選擇的節(jié)點。

Gossip 整體過程描述如下。

  1. Gossip 是周期性的散播消息

  2. 被感染節(jié)點隨機(jī)選擇 k 個鄰接節(jié)點(fan-out)散播消息,假設(shè)把 fan-out 設(shè)置為2,每次最多往2個節(jié)點散播

  3. 每次散播消息都選擇尚未發(fā)送過的節(jié)點進(jìn)行散播

  4. 收到消息的節(jié)點不再往發(fā)送節(jié)點散播,比如 A -> B,那么 B 進(jìn)行散播的時候,不再發(fā)給 A

redis為什么使用哈希槽而不用一致性哈希,JAVA 面試題分享,Redis 面試題分享,java,redis,哈希算法

前面的raft協(xié)議雖然去中心化,但是還是要選出一個類似于Leader的角色來統(tǒng)籌安排事務(wù)的響應(yīng)、提交與中斷,

但是Gossip協(xié)議中就沒有Leader,也不選舉leader每個節(jié)點都是平等的。

?

Gossip 協(xié)議 每個節(jié)點存放了一個key,value,version構(gòu)成的列表,每隔一定的時間,節(jié)點都會主動挑選一個在線節(jié)點進(jìn)行上圖的過程(不在線的也會挑一個嘗試),兩個節(jié)點各自修改自己較為落后的數(shù)據(jù),最終數(shù)據(jù)達(dá)成一致并且都較新。節(jié)點加入或退出都很容易。

Gossip 協(xié)議優(yōu)點

  • 擴(kuò)展性

Gossip 協(xié)議的可擴(kuò)展性極好,一般只需要 O(LogN) 輪就可以將信息傳播到所有的節(jié)點,其中 N 代表節(jié)點的個數(shù)。即使集群節(jié)點的數(shù)量增加,每個節(jié)點的負(fù)載也不會增加很多,幾乎是恒定的。這就允許集群管理的節(jié)點規(guī)模能橫向擴(kuò)展到幾千幾萬個,集群內(nèi)的消息通信成本卻不會增加很多。

  • 容錯

網(wǎng)絡(luò)中任何節(jié)點的宕機(jī)和重啟都不會影響 Gossip 消息的傳播,Gossip 協(xié)議具有天然的分布式系統(tǒng)容錯特性。

  • 健壯性

Gossip 協(xié)議是去中心化的協(xié)議,所以集群中的所有節(jié)點都是對等的,任何節(jié)點出現(xiàn)問題都不會阻止其他節(jié)點繼續(xù)發(fā)送消息。任何節(jié)點都可以隨時加入或離開,而不會影響系統(tǒng)的整體服務(wù)質(zhì)量。

  • 最終一致性

消息傳播是指數(shù)級的快速傳播,因此當(dāng)有新信息傳播時,消息可以快速地發(fā)送到全局節(jié)點。

系統(tǒng)狀態(tài)的不一致可以在很快的時間內(nèi)收斂到一致。

Gossip 協(xié)議缺點

  • 消息延遲

節(jié)點隨機(jī)向少數(shù)幾個節(jié)點發(fā)送消息,消息最終是通過多個輪次的傳播而到達(dá)全網(wǎng),不可避免的造成消息延遲。不適合于對實時性要求較高的場景。

  • 消息冗余

節(jié)點會定期隨機(jī)選擇周圍節(jié)點發(fā)送消息,而收到消息的節(jié)點也會重復(fù)該步驟,因此就不可避免的存在消息重復(fù)發(fā)送給同一節(jié)點的情況,造成了消息的冗余,同時也增加了收到消息的節(jié)點的處理壓力。文章來源地址http://www.zghlxwxcb.cn/news/detail-853668.html

到了這里,關(guān)于JAVA面試題分享五百六十五:為啥Redis用哈希槽,不用一致性哈希?的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 第二百六十九回

    第二百六十九回

    我們在上一章回中介紹了Card Widget相關(guān)的內(nèi)容,本章回中將介紹國際化設(shè)置.閑話休提,讓我們一起Talk Flutter吧。 我們在這里說的國際化設(shè)置是指在App設(shè)置相關(guān)操作,這樣可以讓不同國家的用戶使用App時呈現(xiàn)不同的語言。總之,就是通過相關(guān)的操作,讓App支持多個國家的語言。

    2024年01月18日
    瀏覽(22)
  • 第二百六十四回

    我們在上一章回中介紹了SliverPadding組件相關(guān)的內(nèi)容,本章回中將介紹Sliver綜合示例.閑話休提,讓我們一起Talk Flutter吧。 我們在前面的章回中介紹了各種Sliver相關(guān)的組件:SliverList,SliverGrid,SliverAppBar和SliverPadding,本章回將綜合使用它們。下面是示例程序的 運行效果圖。不過

    2024年01月18日
    瀏覽(20)
  • 冥想第九百六十二天

    1.周二,太忙了,來補(bǔ)日記,被客戶批了,因為一個case沒有測到,不過度譴責(zé)自己,提高就好。 2.下班跑了6公里很舒服。毫無壓力。心率平穩(wěn)并且低。 3.感謝父母,感謝朋友,感謝家人,感謝不斷進(jìn)步的自己。

    2024年02月06日
    瀏覽(18)
  • 每天一個數(shù)據(jù)分析題(一百六十)

    以下關(guān)于代碼片段(使用sklearn)的使用和PCA(主成分分析)的描述中,哪項是正確的? A. preprocessing.scale(data)用于對數(shù)據(jù)進(jìn)行歸一化處理,確保PCA分析前各特征處于同一量級。 B. PCA(n_components=9)將數(shù)據(jù)降維了9個主成分。 C. pca.explained_variance_輸出的是降維后各主成分的方差。

    2024年02月20日
    瀏覽(23)
  • 第一百六十四回 如何實現(xiàn)NumberPicker

    第一百六十四回 如何實現(xiàn)NumberPicker

    我們在上一章回中介紹了\\\"如何在任意位置顯示PopupMenu\\\"相關(guān)的內(nèi)容,本章回中將介紹 如何實現(xiàn)NumberPicker .閑話休提,讓我們一起Talk Flutter吧。 我們在本章回中介紹的 NumberPicker 主要用來實現(xiàn)數(shù)字選擇功能,比如選擇年月日,當(dāng)然也可以使用 YearPicker 實現(xiàn),不過YearPicer是把年月

    2024年02月07日
    瀏覽(27)
  • 每天一個數(shù)據(jù)分析題(一百六十四)

    關(guān)于OLAP系統(tǒng),下列選項不正確的是() A. 是基于數(shù)據(jù)倉庫的信息進(jìn)行分析處理過程 B. 用戶數(shù)量相對較少,其用戶主要是業(yè)務(wù)決策人員與管理人員 C. 對響應(yīng)時間要求非常高。 D. 基礎(chǔ)數(shù)據(jù)來源于生產(chǎn)系統(tǒng)的操作數(shù)據(jù),也就是說,OLAP系統(tǒng)的數(shù)據(jù)來源與OLTP系統(tǒng)。 題目來源于CDA模

    2024年02月22日
    瀏覽(24)
  • JAVA面試題分享二百五十五:mysql 和 es 的5個一致性方案,你知道嗎?

    JAVA面試題分享二百五十五:mysql 和 es 的5個一致性方案,你知道嗎?

    目錄 問題場景分析 方案一:同步雙寫 方案二:異步雙寫 方案2.1 使用內(nèi)存隊列(如阻塞隊列)異步 方案2.2 使用消息隊列(如阻塞隊列)異步 方案三:定期同步 方案四:數(shù)據(jù)訂閱 方案五:etl 工具 咱們的生產(chǎn)需求上,為了便于商品的聚合搜索,高速搜索,采用兩大優(yōu)化方案

    2024年02月04日
    瀏覽(17)
  • PCL點云處理之多種體素濾波方法大匯總(一百六十四)

    對PCL中的基于八叉樹體素濾波方法,以及在此基礎(chǔ)上,自己進(jìn)一步實現(xiàn)的新濾波方法,進(jìn)行一個匯總,列出各自的效果和,具體的實現(xiàn)代碼 PCL中自帶的濾波方法,也是最常用的濾波方法,應(yīng)該是體素中的點云重心取代原始點,但使用時要注意體素不可過小,

    2024年02月05日
    瀏覽(86)
  • 一百六十九、Hadoop——Hadoop退出NameNode安全模式與查看磁盤空間詳情(踩坑,附截圖)

    一百六十九、Hadoop——Hadoop退出NameNode安全模式與查看磁盤空間詳情(踩坑,附截圖)

    在海豚跑定時跑kettle的從Kafka到HDFS的任務(wù)時,由于Linux服務(wù)器的某個文件磁盤空間滿了,導(dǎo)致Hadoop的NodeName進(jìn)入安全模式,此時光執(zhí)行 hdfs dfsadmin -safemode leave命令語句沒有效果( 雖然顯示Safe mode is OFF,但沒效果,一旦執(zhí)行還是報錯 ) Caused by: org.apache.hadoop.ipc.RemoteException(org

    2024年02月10日
    瀏覽(21)
  • 一百六十、Kettle——Linux上安裝的Kettle9.2.0連接Hive3.1.2

    一百六十、Kettle——Linux上安裝的Kettle9.2.0連接Hive3.1.2

    Kettle9.2.0在Linux上安裝好后,需要與Hive3.1.2數(shù)據(jù)庫建立連接 之前已經(jīng)在本地上用kettle9.2.0連上Hive3.1.2 kettle9.2.0安裝包網(wǎng)盤鏈接 鏈接:https://pan.baidu.com/s/15Zq9wNDwyMnc3qFVxYOMXw?pwd=zwae? 提取碼:zwae 1、Hive312的lib里面MySQL驅(qū)動包的版本是mysql-connector-java-5.1.37.jar 2、Kettle9.2里MySQL驅(qū)動包的

    2024年02月12日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包