一致性Hash問題及解決方案

Hash算法的應用場景

  1. 請求的負載均衡
    Nginx的ip_hash策略可以在客戶端ip不發生變化的情況下,將其發出的請求始終路由到同一個目標服務器上,實現會話粘滯,避免處理session共享問題。
  • 如果沒有ip_hash策略,可以通過維護一張映射表的方式來實現會話粘滯:
    • 映射表存儲的是客戶端ip或者session與具體目標服務器的映射關系 <ip,server>

      • 缺點:
        1. 客戶端很多的情況下,映射表非常大,浪費內存空間
        2. 客戶端上下線、目標服務器上下線都會導致重新維護映射表,維護成本大
    • 如果使用Hash算法,可以對ip或者session計算hash值,hash值與服務器數量進行取模運算,得到的值就是當前請求應該被路由到的服務器編號。由此,同一個ip發送過來的請求就可以路由到同一個目標服務器,實現會話粘滯。

  1. 分布式存儲
    有 Redis1、Redis2、Redis3 三臺Redis服務器,可以針對key進行hash處理 Hash(key)%3 = index 使用余數鎖定存儲的具體服務器節點。

普通Hash算法存在的問題

以ip_hash為例,假定用戶ip固定不變,當后端服務器有一個宕機,數量由3變為2,那么之前所有用戶的求模都需要重新計算。
如果在生產環境中,后臺服務器有很多臺,客戶端也有很多個,出現這種問題的影響是很大的。服務器的擴縮容都會出現這樣的問題,大量的用戶請求被路由到其他的目標服務器處理,用戶在原來服務器的會話都將丟失。

普通Hash算法:

// 定義客戶端IP
String[] clients = {"192.168.31.121", "192.168.3.21", "192.168.1.11"};// 定義服務器數量
int server = 5;// hash(ip) % server數量 = index
for (String client : clients) {int hashCode = Math.abs(client.hashCode());int index = hashCode % server;System.out.println("客戶端:\t" + client + "\t 分配到了服務器 " + (index + 1) + " 上");
}

一致性Hash算法的思路

  1. 首先有一條直線,直線開頭和結尾分別定為1和232-1,這相當于一個地址
  2. 對于這樣一條直線,首尾相連構成一個閉環,這樣的圓環稱為Hash環
  3. 把服務器IP或者主機名求Hash值然后對應到Hash環上,針對客戶端IP求Hash值,對應到環上的某個位置,然后按照順時針的方向找最近的服務器節點

在這里插入圖片描述

  • 縮容
    假設將節點3下線,原來路由到3的客戶端請求重新路由到節點4,對于其他客戶端沒有影響,只是這一小部分受到影響
    請求的遷移量達到了最小,這樣的算法對于分布式集群來說非常合適,避免了大量請求轉移。

在這里插入圖片描述

  • 擴容
    新增節點5之后,原來路由到節點3的部分客戶端路由到了節點5上,對于其他客戶端沒有影響,只是這一小部分受到影響

在這里插入圖片描述

代碼如下:

// 定義服務器IP
String[] servers = {"192.168.31.121", "192.168.3.21", "192.168.1.11", "12.168.31.121", "192.138.3.21", "192.68.1.11"};
// 定義客戶端IP
String[] clients = {"12.16.31.121", "12.18.3.1", "19.16.1.11"};
// 計算服務器的Hash,并放到排序的Map中
SortedMap<Integer,String> hashServerMap = new TreeMap<>();
for (String server : servers) {int hashCode = Math.abs(server.hashCode());hashServerMap.put(hashCode,server);
}
// 求客戶端IP的Hash,取出對應的服務器
for (String client : clients) {int clientHash = Math.abs(client.hashCode());SortedMap<Integer, String> tailedMap = hashServerMap.tailMap(clientHash);// 取出Hash環上的第一臺服務器Integer firstKey;if (tailedMap.isEmpty()){firstKey = hashServerMap.firstKey();}else {firstKey = tailedMap.firstKey();}System.out.println("客戶端IP\t"+ client +"\t被路由到了服務器\t" + hashServerMap.get(firstKey));
}

存在的問題及解決方法

如上所述,每一臺服務器負責一段,一致性Hash算法對于節點的增加都只需要重定位環空間的一小部分數據,具有較好的容錯性和可擴展性。

  1. 一致性Hash算法在服務節點太少時,容易因節點分部不均勻造成數據傾斜問題。例如只有兩臺服務器,這兩臺服務器在環上的分部十分靠近,導致某個節點只負責非常小的一段,大量的請求落在了另外一個節點上,導致數據傾斜。
  2. 為了解決這種方法,一致性Hash算法引入了虛擬節點機制,即對每一個服務節點計算多個Hash,每個計算結果都放置一個此服務節點,稱為虛擬節點。具體做法可以在服務器IP或者主機名后增加編號來實現,例如 “節點1的ip#1” “節點1的ip#2” “節點1的ip#3”……形成多個虛擬節點,當客戶端被路由到虛擬節點的時候其實是被路由到該虛擬節點所對應的真實節點。

代碼如下:

// 定義服務器IP
String[] servers = {"192.168.31.121", "192.168.3.21", "192.168.1.11", "12.168.31.121", "192.138.3.21", "192.68.1.11"};
// 定義客戶端IP
String[] clients = {"12.16.31.121", "12.18.3.1", "19.16.1.11"};SortedMap<Integer, String> serverHash = new TreeMap<>();int virtualNodeCount = 3;
// 開始計算服務器的Hash
for (String server : servers) {int hash = Math.abs(server.hashCode());serverHash.put(hash, server);// 設置虛擬節點for (int i = 0; i < virtualNodeCount; i++) {int virtualNodeHash = Math.abs((server + "#" + i).hashCode());serverHash.put(virtualNodeHash, "虛擬節點" + i + "映射過來的請求:" + server);}
}System.out.println(serverHash.size());
// 計算客戶端請求的服務器Hash
for (String client : clients) {int clientHash = Math.abs(client.hashCode());SortedMap<Integer, String> tailedMap = serverHash.tailMap(clientHash);if (tailedMap.isEmpty()) {Integer firstKey = serverHash.firstKey();System.out.println("客戶端:" + client + "\t\t路由到了 \t" + serverHash.get(firstKey));} else {Integer firstKey = tailedMap.firstKey();System.out.println("客戶端:" + client + "\t\t路由到了 \t" + serverHash.get(firstKey));}
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/45117.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/45117.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/45117.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

常用包管理工具(apk、apt、yum)常用命令

apk 包管理工具apk是Alpine Linux中使用廣泛的一個工具&#xff0c;用于管理軟件包的安裝、更新、卸載等操作。以下是一些常用的apk命令及其解釋&#xff1a; 1.更新 apk update&#xff1a;從遠程鏡像源更新本地倉庫中的所有軟件包索引apk upgrade&#xff1a;升級本地已安裝…

ts實現將相同類型的數據通過排序放在一起

看下效果&#xff0c;可以將相同表名稱的字段放在一起 排序適用于中英文、數字 // 排序 function sortByType(items: any) {// 先按照類型進行排序items.sort((a: any, b: any) > {if (a.label < b.label) return -1;if (a.label > b.label) return 1;return 0;});r…

鴻蒙語言基礎類庫:【@ohos.application.testRunner (TestRunner)】 測試

TestRunner TestRunner模塊提供了框架測試的能力。包括準備單元測試環境、運行測試用例。 如果您想實現自己的單元測試框架&#xff0c;您必須繼承這個類并覆蓋它的所有方法。 說明&#xff1a; 開發前請熟悉鴻蒙開發指導文檔&#xff1a;gitee.com/li-shizhen-skin/harmony-…

編程語言與數據結構的關系:深度解析與探索

編程語言與數據結構的關系&#xff1a;深度解析與探索 在編程的世界中&#xff0c;編程語言和數據結構是兩個不可或缺的元素。它們之間既相互依存&#xff0c;又各自獨立&#xff0c;共同構成了編程的核心。本文將深入探索編程語言與數據結構之間的復雜關系&#xff0c;從四個…

[氮化鎵]Kevin J. Chen組新作—肖特基p-GaN HEMTs正柵ESD機理研究

這篇文章是發表在《IEEE Electron Device Letters》上的一篇關于Schottky型p-GaN柵極高電子遷移率晶體管&#xff08;HEMTs&#xff09;的正向柵極靜電放電&#xff08;ESD&#xff09;機理研究的論文。文章由Jiahui Sun等人撰寫&#xff0c;使用了基于碳化硅&#xff08;SiC&a…

8626 原子量計數

分析&#xff1a; 1. **讀取輸入**&#xff1a;首先&#xff0c;我們需要讀取輸入中的第一行&#xff0c;了解有多少個化學式需要處理。之后&#xff0c;對于每個化學式&#xff0c;我們逐行讀取并進行處理。 2. **解析化學式**&#xff1a;對于每個化學式&#xff0c;我們需要…

8627 數獨

為了判斷數獨解是否合法&#xff0c;我們需要遵循以下步驟&#xff1a; 1. **檢查每一行**&#xff1a;確保1到9每個數字在每一行中只出現一次。 2. **檢查每一列**&#xff1a;確保1到9每個數字在每一列中只出現一次。 3. **檢查每個3x3的宮**&#xff1a;確保1到9每個數字在…

細胞通訊之cellchat的流程

愿武藝晴小朋友一定得每天都開心 在細胞通訊的領域內有cellphoneDB、cellchat、iTALK等多種cell-cell communication的工具; 其中cellchat,我覺得它比較的親民和好看吧^_^ cellchat <- createCellChat(Matrix(health@assays$RNA$data,sparse = T), #用于seurat.v5對象 …

文件類:如何將excel文件轉為csv文件(且保留時間格式)?

最近有個場景&#xff0c;在ftp服務器上&#xff0c;讀取csv文件并入庫&#xff0c;但是客戶提供的一部分文件卻是xls文件&#xff0c;就得搞個將excel轉為csv文件的方法&#xff0c;話不多說直接開干。 方法 public static void convertExcelToCSV(String excelFilePath, Str…

掌握axios與Vue 3:構建高效HTTP請求的終極指南

引言 axios作為一個廣泛使用的JavaScript庫&#xff0c;因其簡潔的API、強大的功能和良好的瀏覽器兼容性&#xff0c;成為了許多前端開發者在Vue 3項目中的首選。 axios簡介 axios是什么&#xff1f; axios是一個基于Promise的HTTP客戶端&#xff0c;用于瀏覽器和node.js環境…

【視頻】R語言廣義加性模型GAMs非線性效應、比較分析草種耐寒性實驗數據可視化

全文鏈接&#xff1a;https://tecdat.cn/?p36979 原文出處&#xff1a;拓端數據部落公眾號 廣義加法模型&#xff08;Generalized Additive Models, GAMs&#xff09;作為一種高度靈活的統計工具&#xff0c;顯著擴展了廣義線性模型&#xff08;Generalized Linear Models, …

我被手機所傷,竟如此憔悴。

臨睡前&#xff0c;剛刷完小視頻&#xff0c;感覺好無聊。一陣陣空虛感襲來。看看時間&#xff0c;哦&#xff0c;原來我下班后一直從6點刷視頻到11點。 哎&#xff0c;太空虛了&#xff0c;又馬上要睡覺了&#xff0c;為什么會這么難受呢?明明我大學&#xff0c;高中&#x…

代碼隨想錄算法訓練營第9天

151.反轉字符串中的單詞 題目鏈接&#xff1a;151. 反轉字符串中的單詞 - 力扣&#xff08;LeetCode&#xff09; 視頻鏈接&#xff1a;代碼隨想錄 (programmercarl.com) 第一想法 使用split函數然后倒序相加 代碼隨想錄想法 先去除空格&#xff0c;再將整個字符串反轉&…

Android11 應用啟動流程

應用層調用startActivity&#xff0c;會跨進程調用導致ATMS的startActivityAsUser方法被調用 //frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java private int startActivityAsUser(IApplicationThread caller, String callingPack…

數字信號處理及MATLAB仿真(4)——量化的其他概念

上回書說到AD轉換的兩個步驟——量化與采樣兩個步驟。現在更加深入的去了解以下對應的概念。學無止境&#xff0c;要不斷地努力才有好的收獲。萬丈高樓平地起&#xff0c;唯有打好基礎&#xff0c;才能踏實前行。 不說了&#xff0c;今天咱們繼續說說這兩個步驟&#xff0c;首先…

每日刷題(二分圖,二分查找,dfs搜索)

目錄 1.P3853 [TJOI2007] 路標設置 2.P1129 [ZJOI2007] 矩陣游戲 3.P1330 封鎖陽光大學 4.Trees 5.P1141 01迷宮 1.P3853 [TJOI2007] 路標設置 P3853 [TJOI2007] 路標設置 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) 先求出每個路標之間的距離&#xff0c;再二分查找每…

新媒體運營都需要掌握哪些技術?沈陽新媒體運營免費培訓

新媒體運營需要掌握的技術包括內容創作、FAB產品介紹法、用戶運營、社群運營、活動策劃和數據分析。這個崗位在現代社會中的重要性日益突出&#xff0c;隨著互聯網的發展&#xff0c;新媒體已成為人們獲取信息的主要渠道之一&#xff0c;而新媒體運營則是通過各種新媒體平臺進行…

數據庫系統原理練習 | 作業2-第2章關系數據庫(附答案)

整理自博主本科《數據庫系統原理》專業課完成的課后作業&#xff0c;以便各位學習數據庫系統概論的小伙伴們參考、學習。 *文中若存在書寫不合理的地方&#xff0c;歡迎各位斧正。 專業課本&#xff1a; 目錄 一、選擇題 二、填空題 三、簡答題 四、關系代數 1.課本p70頁&…

hive中reverse函數

目錄 前言基本函數介紹實戰 前言 reverse函數&#xff0c;是一個常用的字符串處理函數&#xff0c;很多編程語言都有。最近開發中&#xff0c;遇到一個reverse解決的需求&#xff0c;發現自己尚未總結過&#xff0c;遂補上。 基本函數介紹 SELECT reverse(string_column) FR…

虛擬機安裝Linux CENTOS 07 部署NET8 踩坑大全

首先下載centos07鏡像&#xff0c;建議使用阿里云推薦的地址&#xff1a; https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spma2c6h.25603864.0.0.59b5f5ad5Nfr0X 其實這里就已經出現第一個坑了 centos 07 /usr/lib64/ 的 libstdc.so只支持到19&#xff1b; GLI…