日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Java實(shí)現(xiàn)權(quán)重隨機(jī)算法詳解

瀏覽:61日期:2022-08-09 08:34:02
目錄應(yīng)用場(chǎng)景本文目標(biāo)算法詳解權(quán)重比例Java 實(shí)現(xiàn)參考應(yīng)用場(chǎng)景

客戶(hù)端負(fù)載均衡,例如 Nacos 提供的客戶(hù)端負(fù)載均衡就是使用了該算法游戲抽獎(jiǎng)(普通道具的權(quán)重很高,稀有道具的權(quán)重很低)

本文目標(biāo)

Java 實(shí)現(xiàn)權(quán)重隨機(jī)算法

算法詳解

比如我們現(xiàn)在有三臺(tái) Server,權(quán)重分別為1,3,2。現(xiàn)在想對(duì)三臺(tái) Server 做負(fù)載均衡

Server1 Server2 Server3 weight weight weight 1 3 2權(quán)重比例

我們算出每臺(tái) Server 的權(quán)重比例,權(quán)重比例 = 自己的權(quán)重 / 總權(quán)重

server1 server2 server3 weight weight weight 1 3 2 radio radio radio 1/6 3/6 2/6

根據(jù)權(quán)重比例計(jì)算覆蓋區(qū)域

server1 server2 server3 ^ ^^ |---------||---------|---------|---------||---------|---------|| 0 1/6 4/6 6/6 ^ ^ ^ 0.16666667 0.66666667 1.0

根據(jù)權(quán)重負(fù)載均衡

如步驟2所示,每個(gè) server 都有自己的范圍,把每一個(gè)格子作為單位來(lái)看的話(huà)

server1 (0,1] server2 (1,4] server3 (4,6]

使用隨機(jī)數(shù)函數(shù),取 (0,6] 之間的隨機(jī)數(shù),根據(jù)隨機(jī)數(shù)落在哪個(gè)范圍決定如何選擇。例如隨機(jī)數(shù)為 2,處于 (1,4] 范圍,那么就選擇 server2。

思路大概就是這樣,落實(shí)到代碼上,用一個(gè)數(shù)組 [0.16666667, 0.66666667, 1] 來(lái)表示這三個(gè) server 的覆蓋范圍,使用 ThreadLocalRandom 或者 Random 獲取 [0,1) 內(nèi)的隨機(jī)數(shù)。然后使用二分查找法快速定位隨機(jī)數(shù)處于哪個(gè)區(qū)間

Java 實(shí)現(xiàn)

代碼基本上與 com.alibaba.nacos.client.naming.utils.Chooser 一致,在可讀性方面做了下優(yōu)化。

import java.util.*;import java.util.concurrent.ThreadLocalRandom;import java.util.concurrent.atomic.AtomicInteger;public class WeightRandom<T> { private final List<T> items = new ArrayList<>(); private double[] weights; public WeightRandom(List<ItemWithWeight<T>> itemsWithWeight) {this.calWeights(itemsWithWeight); } /** * 計(jì)算權(quán)重,初始化或者重新定義權(quán)重時(shí)使用 * */ public void calWeights(List<ItemWithWeight<T>> itemsWithWeight) {items.clear();// 計(jì)算權(quán)重總和double originWeightSum = 0;for (ItemWithWeight<T> itemWithWeight : itemsWithWeight) { double weight = itemWithWeight.getWeight(); if (weight <= 0) {continue; } items.add(itemWithWeight.getItem()); if (Double.isInfinite(weight)) {weight = 10000.0D; } if (Double.isNaN(weight)) {weight = 1.0D; } originWeightSum += weight;}// 計(jì)算每個(gè)item的實(shí)際權(quán)重比例double[] actualWeightRatios = new double[items.size()];int index = 0;for (ItemWithWeight<T> itemWithWeight : itemsWithWeight) { double weight = itemWithWeight.getWeight(); if (weight <= 0) {continue; } actualWeightRatios[index++] = weight / originWeightSum;}// 計(jì)算每個(gè)item的權(quán)重范圍// 權(quán)重范圍起始位置weights = new double[items.size()];double weightRangeStartPos = 0;for (int i = 0; i < index; i++) { weights[i] = weightRangeStartPos + actualWeightRatios[i]; weightRangeStartPos += actualWeightRatios[i];} } /** * 基于權(quán)重隨機(jī)算法選擇 * */ public T choose() {double random = ThreadLocalRandom.current().nextDouble();int index = Arrays.binarySearch(weights, random);if (index < 0) { index = -index - 1;} else { return items.get(index);}if (index < weights.length && random < weights[index]) { return items.get(index);}// 通常不會(huì)走到這里,為了保證能得到正確的返回,這里隨便返回一個(gè)return items.get(0); } public static class ItemWithWeight<T> {T item;double weight;public ItemWithWeight() {}public ItemWithWeight(T item, double weight) { this.item = item; this.weight = weight;}public T getItem() { return item;}public void setItem(T item) { this.item = item;}public double getWeight() { return weight;}public void setWeight(double weight) { this.weight = weight;} } public static void main(String[] args) {// for testint sampleCount = 1_000_000;ItemWithWeight<String> server1 = new ItemWithWeight<>('server1', 1.0);ItemWithWeight<String> server2 = new ItemWithWeight<>('server2', 3.0);ItemWithWeight<String> server3 = new ItemWithWeight<>('server3', 2.0);WeightRandom<String> weightRandom = new WeightRandom<>(Arrays.asList(server1, server2, server3));// 統(tǒng)計(jì) (這里用 AtomicInteger 僅僅是因?yàn)閷?xiě)起來(lái)比較方便,這是一個(gè)單線(xiàn)程測(cè)試)Map<String, AtomicInteger> statistics = new HashMap<>();for (int i = 0; i < sampleCount; i++) { statistics .computeIfAbsent(weightRandom.choose(), (k) -> new AtomicInteger()) .incrementAndGet();}statistics.forEach((k, v) -> { double hit = (double) v.get() / sampleCount; System.out.println(k + ', hit:' + hit);}); }}

這里重點(diǎn)說(shuō)一下 Arrays.binarySearch(weights, random),這個(gè) API 我之前沒(méi)有用過(guò)導(dǎo)致我在讀 Nacos 源碼時(shí),對(duì)這塊的操作十分費(fèi)解

來(lái)看一下 java API 文檔對(duì)該方法返回值的解釋

Returns:index of the search key, if it is contained in the array; otherwise, (-(insertion point) - 1). The insertion point is defined as the point at which the key would be inserted into the array: the index of the first element greater than the key, or a.length if all elements in the array are less than the specified key. Note that this guarantees that the return value will be >= 0 if and only if the key is found.

解釋下,首先該方法的作用是通過(guò)指定的 key 搜索數(shù)組。(前提條件是要保證數(shù)組的順序是從小到大排序過(guò)的)

如果數(shù)組中包含該 key,則返回對(duì)應(yīng)的索引 如果不包含該 key,則返回該 key 的 (-(insertion point)-1)

insertion point(插入點(diǎn)):該 key 應(yīng)該在數(shù)組的哪個(gè)位置。舉個(gè)例子,數(shù)組 [1,3,5],我的搜索 key 為 2,按照順序排的話(huà) 2 應(yīng)該在數(shù)組的 index = 1 的位置,所以此時(shí) insertion point = 1。

(這里 jdk 將能查到 key 和 查不到 key 兩種情況做了區(qū)分。為了將未找到的情況全部返回負(fù)數(shù),所以做了 (-(insertion point)-1) 這樣的操作)

看到這,我們就懂了,insertion point 就是我們需要的,現(xiàn)在我們用小學(xué)數(shù)學(xué)來(lái)推導(dǎo)一下如何計(jì)算 insertion point

// 小學(xué)數(shù)學(xué)推導(dǎo)一下 insertion point 如何計(jì)算returnValue = (- (insertionPoint) - 1)insertionPoint = (- (returnValue + 1) )// 所以就有了上邊代碼中的if (index < 0) { index = -index - 1;}參考

https://github.com/alibaba/nacos/blob/develop/client/src/main/java/com/alibaba/nacos/client/naming/utils/Chooser.java

到此這篇關(guān)于Java實(shí)現(xiàn)權(quán)重隨機(jī)算法詳解的文章就介紹到這了,更多相關(guān)Java 權(quán)重隨機(jī)內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产日韩一区二区三区在线 | 99久久精品网| 日韩精品电影| 成人va天堂| 91九色精品国产一区二区| 欧美日韩国产综合网| 日韩在线播放一区二区| 亚洲精品少妇| 青青伊人久久| 欧美国产极品| 免费视频一区二区三区在线观看 | 国产精品亚洲四区在线观看 | 国产欧美日韩精品一区二区免费| 国产欧美三级| 福利精品一区| 欧美一级精品| 免费人成黄页网站在线一区二区| 日韩激情一区二区| 久久精品一区二区国产| 福利精品一区| 国产麻豆久久| 久久福利精品| 欧美三级第一页| 水蜜桃久久夜色精品一区| 91九色精品国产一区二区| 久久午夜精品| 久久99蜜桃| 久久精品不卡| 日本亚洲不卡| 国产成人精品一区二区三区在线| 久久一区二区中文字幕| 亚洲综合福利| 久久精品国产亚洲一区二区三区| 日韩精品影视| 亚洲九九精品| 麻豆精品少妇| 亚洲高清成人| 日本免费在线视频不卡一不卡二| 精品久久影院| 一区三区视频| 久久超级碰碰| 不卡中文字幕| 国产精品mv在线观看| 国产在线成人| 国产精品日本一区二区不卡视频| 日韩不卡在线| 日本不卡高清视频| 欧美一区久久久| 亚洲免费专区| 91看片一区| 日韩精品国产欧美| 在线天堂资源www在线污| 男女男精品视频网| 成年男女免费视频网站不卡| 日韩精品一二三区| 91中文字幕精品永久在线| 一区二区不卡| 色网在线免费观看| 婷婷综合福利| 99精品美女| 欧美激情麻豆| 免费不卡在线观看| 日韩精品永久网址| 欧美欧美黄在线二区| 国产精品97| 免费在线观看一区| 丝袜美腿亚洲色图| 久久夜夜操妹子| 国产精品中文字幕亚洲欧美| 91九色精品| 成人精品国产亚洲| 欧美视频一区| 免费在线观看视频一区| 私拍精品福利视频在线一区| 国产福利一区二区精品秒拍| 男人的天堂亚洲一区| 日韩精品诱惑一区?区三区| 欧美一级久久| 伊人国产精品| 欧美午夜不卡| 国产v综合v| 国产情侣久久| 中文字幕av一区二区三区人| 激情欧美丁香| 日韩成人亚洲| 精品精品99| 日本午夜精品久久久| 午夜在线一区| 在线一区电影| 播放一区二区| 色网在线免费观看| 精品视频黄色| 国产日韩欧美三区| 日韩视频一二区| 三级在线观看一区二区| 999久久久国产精品| 久久精品国产在热久久| 国产亚洲观看| 亚洲男人在线| 伊人久久大香伊蕉在人线观看热v| 欧美中文一区二区| 91精品婷婷色在线观看| 中文字幕在线高清| 国产一区不卡| 精品视频一区二区三区在线观看| 国产精品久久久一区二区| 色8久久久久| 亚洲精品第一| 亚洲精品动态| 视频一区中文字幕精品| 亚洲精品看片| 免费人成网站在线观看欧美高清| 99国产一区| 性色一区二区| 日韩精品一区第一页| 人人爽香蕉精品| 亚洲精品免费观看| 日本中文字幕一区二区视频| 婷婷精品久久久久久久久久不卡| 美国av一区二区| 日韩专区一卡二卡| 丝袜美腿亚洲一区| 男女男精品网站| 一区二区国产在线观看| 一区二区国产在线观看| 亚洲精品亚洲人成在线观看| 老色鬼久久亚洲一区二区| 亚洲免费婷婷| 伊人久久亚洲| 欧美三区不卡| 久久这里只有| caoporn视频在线| 日韩精品久久久久久久电影99爱| 久久狠狠婷婷| 久久国产成人| 日韩不卡一区二区三区| 久久99蜜桃| av日韩中文| 精品中文字幕一区二区三区av| 国产亚洲精品v| 日韩成人午夜精品| 国产精品一级在线观看| 91视频久久| 日韩一级欧洲| 欧美亚洲tv| 亚洲天堂av影院| 中文在线不卡| 欧美日韩1区2区3区| 久久99精品久久久野外观看| 理论片午夜视频在线观看| 亚洲手机视频| 日韩激情中文字幕| 国产一区精品福利| 一区免费视频| 国产欧美大片| 久久九九电影| 亚洲网址在线观看| 欧美aⅴ一区二区三区视频| 88xx成人免费观看视频库| 西西人体一区二区| 国产精品多人| 久久久精品网| 亚洲麻豆一区| 成人在线视频区| 久久国产精品99国产| 国产精品美女午夜爽爽| 日韩欧美一区二区三区免费看| 国产视频欧美| 蜜桃久久久久| 国产精品嫩草99av在线| 国产精品对白久久久久粗| 美女福利一区二区三区| 在线精品国产亚洲| 日本一二区不卡| 综合精品一区| 国产成人在线中文字幕| 久久午夜精品| 久久久久久色| 色爱综合av| 97久久亚洲| 激情婷婷久久| 国产精品一区免费在线| 午夜av一区| 老司机精品视频网| 蜜桃伊人久久| 97精品国产| 天堂va蜜桃一区二区三区| 国产成人精品亚洲线观看| 老牛影视一区二区三区| 成人日韩av| 午夜精品影视国产一区在线麻豆| 黄毛片在线观看| 青草久久视频| 欧美精品激情| 日本精品黄色| 欧美偷窥清纯综合图区| 日韩午夜av在线| 国产一区二区三区四区五区传媒| 一区二区三区国产在线| 电影天堂国产精品|