乙份針對於新手的多執行緒實踐 高階篇

2022-01-10 18:56:38 字數 2869 閱讀 2375

在上文《乙份針對於新手的多執行緒實踐》留下了乙個問題:

這只是多執行緒其中的乙個用法,相信看到這裡的朋友應該多它的理解更進一步了。

在 redis 或者其他儲存介質中存放有上千萬的手機號碼資料,每個號碼都是唯一的,需要在最快的時間內把這些號碼全部都遍歷一遍。

感謝每一位參與的朋友。

其實看了大家的方案大多都想到了資料肯定要分段,因為大量的資料肯定沒法一次性load到記憶體。

但怎麼載入就要考慮清楚了,有些人說放在資料庫中通過分頁的方式進行載入,然後將每頁的資料丟到乙個執行緒裡去做遍歷。

其實想法挺不錯的,但有個問題就是:

這樣肯定會導致有乙個主線程去遍歷所有的號碼,即便是分頁查詢的那也得全部查詢一遍,效率還是很低。

即便是分頁載入號碼用多執行緒,那就會涉及到鎖的問題,怎麼保證每個執行緒讀取的資料是互不衝突的。

但如果儲存換成redisstring結構這樣就更行不通了。

有沒有一種利用多執行緒載入效率高,並且執行緒之間互相不需要競爭鎖的方案呢?

下面來看看這個方案:

首先在儲存這千萬號碼的時候我們把它的號段單獨提出來並冗餘儲存一次。

比如有個號碼是18523981123那麼就還需要儲存乙個號段:1852398

這樣當我們有以下這些號碼時:

18523981123 18523981124 18523981125 13123874321 13123874322 13123874323

我們就還會維護乙個號段資料為:

1852398 1312387

在需要遍歷時:

這樣做的根本原因其實是避免了執行緒之間加鎖,通過號段可以讓每個執行緒只取自己那一部分資料。

可能會有人說,如果號碼持續增多導致號段的資料也達到了上萬甚至幾十萬這怎麼辦呢?

那其實也是同樣的思路,可以再把號段進行拆分。

比如之前是1852398的號段,那我繼續拆分為1852

這樣只需要在之前的基礎上再啟動乙個執行緒去查詢子號段即可,有點fork/join的味道。

這樣的思路其實也和 jdk1.7 中的 concurrenthashmap 類似,定位乙個真正的資料需要兩次定位。

上面的方案也是由侷限性的,畢竟說到底還是乙個單機應用。沒法擴充套件;處理的資料始終是有上限。

因此隨著資料量的提公升我們肯定得需要通過水平擴充套件的方式才能達到最好的效能,這就是分布式的方案。

假設我現在有上億的資料需要遍歷,但我當前的伺服器配置只能支撐乙個應用啟動 n 個執行緒 5 分鐘跑5000w的資料。

於是我水平擴充套件,在三颱伺服器上啟動了三個獨立的程序。假設乙個應用能跑 5000w ,那麼理論上來說三個應用就可以跑1.5億的資料了。

但這個的前提還是和上文一樣:每個應用只能處理自己的資料,不能出現加鎖的情況(這樣會大大的降低效能)。

所以我們得對剛才的號段進行分組。

先通過一張圖來直觀的表示這個邏輯:

假設現在我有 9 個號段,那麼我就得按照圖中的方式把資料隔離開來。

第乙個資料給應用0,第二個資料給應用1,第三個資料給應用2。後面的資料以此類推(就是乙個簡單的取模運算)。

這樣就可以將號段均勻的分配給不同的應用來進行處理,然後每個應用再按照上文提到的將分配給自己的號段丟到執行緒池中由具體的執行緒去查詢、遍歷即可。

這樣看似沒啥問題,但一旦引入了分布式之後就不可避免的會出現cap的取捨,這裡不做過多討論,感興趣的朋友可以自行搜尋。

首先要解決的乙個問題就是:

這三個應用怎麼知道它自己應該取哪些號段的資料呢?比如 0 號應用就取0 3 6(這個相當於號段的下標),難道在配置檔案裡配置嘛?

那如果資料量又增大了,對應的機器數也增加到了 5 臺,那自然 0 號應用就不是取0 3 6了(取模之後資料會變)。

所以我們得需要乙個統一的排程來分配各個應用他們應當取哪些號段,這也就是資料分片

假設我這裡有乙個統一的分配中心,他知道現在有多少個應用來處理資料。還是假設上文的三個應用吧。

在真正開始遍歷資料的時候,這個分配中心就會去告訴這三個應用:

你們要開始工作了啊,0 號應用你的工作內容是0 3 6,1 號應用你的工作內容是1 4 7,2 號應用你的工作內容是2 5 8

這樣各個應用就知道他們所應當處理的資料了。

當我們新增了乙個應用來處理資料時也很簡單,同樣這個分配中心知道現在有多少臺應用會工作。

他會再拿著現有的號段對 4(3+1臺應用) 進行取模然後對資料進行重新分配,這樣就可以再次保證資料分配均勻了。

只是分配中心如何知道有多少應用呢,其實也簡單,只要中心和應用之間通訊就可以了。比如啟動的時候呼叫分配中心的介面即可。

上面提到的這個分配中心其實就是乙個常見的定時任務的分布式排程中心,由它來統一發起排程,當然分片只是它其中的乙個功能而已(關於排程中心之後有興趣再細說)。

本次**了多執行緒的更多應用方式,如要是如何高效的執行。最主要的一點其實就是盡量的避免加鎖。

你的點讚與**是最大的支援。

多乙份感動,多乙份行動

有乙個女生,因為跟家裡處得不好,所以很少回家,後來有一次回家,發現年老的母親走路一跛一跛的,不經意的看了母親的腳一眼,這才發現母親的腳指甲太長而長到肉裡面造成流血,流膿,這時,她認真的看者已經很久沒有正眼看過的母親,她才發現在她眼前的母親已經年老,老到已經沒有辦法彎下身來自己剪指甲,所以 才會讓雙腳...

針對於iMatrix平台的流程引擎見解

最近在網上看到開源的imatrix開發平台,看到有瀏覽器版本的流程設計器功能,自己研究了一下它和流程引擎的結合使用原理 首先看一下imatrix平台的xml和jbpm原生的xml有什麼區別?流程屬性 環節屬性和流向屬性生成xml的原理基本一致,生成的extend元素為平台自己新增的元素,通過這些擴充...

致敬我們自己的「李煥英」,多乙份陪伴少乙份遺憾!

親情,是一罈陳年老酒,甜美醇香 是一幅傳世名畫,精美雋永 是一首經典老歌,輕柔溫婉 是一方名貴絲綢,細膩光滑。親情是與生俱來的一種感情,不會隨著時間的流失而變淡,反而由於種種原因造成的遺憾,會讓我們的心靈久久不能平靜,每每想起到底是意難平。截至2月18日,喜劇演員賈玲導演的 你好,李煥英 票房突破3...