中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

詳談分布式系統緩存的設計細節

發布時間:2020-07-01 22:46:05 來源:網絡 閱讀:354 作者:大快DKhadoop 欄目:開發技術


在分布式Web程序設計中,解決高并發以及內部解耦的關鍵技術離不開緩存和隊列,而緩存角色類似計算機硬件中CPU的各級緩存。如今的業務規模稍大的互聯網項目,即使在最初beta版的開發上,都會進行預留設計。但是在諸多應用場景里,也帶來了某些高成本的技術問題,需要細致權衡。

詳談分布式系統緩存的設計細節

服務端數據緩存

一種區分

緩存基于不同的條件有很多種劃分方式,本地緩存(Local cache)和分布式緩存(Distributed cache)是一種常見分類,兩者自身又包含很多細類。

本地并不是指程序所在本地服務器(從嚴格概念來說),而是更細粒度的指位于程序自身的內部存儲空間,而分布式更多強調的是存儲在進程之外的一個或者多個服務器上,彼此交互通信,在具體軟件項目的設計和應用中,多數時候是混合一體。當然,個人認為對緩存本質的理解才是最重要的,至于概念上的分類只是一個不同理解下的劃分而已。

一些技術成本

在具體項目架構設計時,單純使用前者(本地緩存)的開發成本毋庸置疑是極低的,主要考慮的是本機的內存負載或者極少量的磁盤I/O影響。而后者的設計初心是為了利于分布式程序之間緩存數據的高效共享和管理,除了考慮緩存所在服務器自身的內存負載,設計時更需要充分考慮網絡I/O、CPU的負載,以及某些場景下的磁盤I/O的代價,同時還在具體設計時盡可能規避和權衡整體穩定性和效率,這些不僅僅只是作為緩存服務器的硬件成本和技術維護。需要謹慎考慮的底層問題包括緩存間通信、網絡負載和延遲等各種需要權衡的細節。

其實如果理解了緩存本質就該知道,任何存儲介質在適當的場景下都可以充當一個高效的緩存角色并進行項目集成和緩存間集群。常見主流的Memcached和Redis等均是屬于后者范疇,甚至可以包括如基于NoSQL設計的MongoDB這類文檔數據庫(但這是從角色角度講,而狹義劃分上這是基于磁盤的存儲庫,需要注意,各有專攻)。

這些第三方緩存在進行項目集成和緩存間集群,也需要解決一些問題。甚至項目迭代到了后期階段,往往還需要具備較高專業知識的運維同時參與,并且在開發中的邏輯設計和代碼實現也會增加一定的工作量。所以有時候在具體項目的設計上,一方面要盡可能預留,一方面還得根據實際情況盡可能精簡。

額外說下其他體會:在個人有限的技術學習和實踐里,關于節點數據交互,尤其是服務間通信,是不存在完美的閉環的,理論上也都是在“當前階段”面向“高一致”的權衡罷了(大概跟生活是一樣的吧)。

詳談分布式系統緩存的設計細節

緩存數據庫結構設計細節

由于目前個人工作中大多數情況應用的是Redis 3.x,以下若有特性關聯,均是以此作為參照說明。

實例(Instance)

根據業務場景,公共數據和業務耦合數據,一定分別使用不同的實例。如果是單實例,才可以考慮以DB劃分。當你使用的是Redis,那么DB在Redis里是有數據隔離,但沒有嚴格權限限制,所以劃庫只是一種選擇。在Cluster集群里則是保持默認單個庫,不過實際中我會嘗試根據項目大小來調整,至于在哪個開發階段則是作為預留設計。

額外需要注意的是,作為重度依賴服務器內存的緩存產品,如果開啟了持久化(后面會提到),并且在為并發量極大的服務提供支持時,服務器硬件資源會出現大量搶占,請結合持久策略配置,考慮實例是否進行分盤存儲。

持久化本質是將內存數據同步寫入硬盤(刷盤),而磁盤I/O實在有限,被迫的寫入阻塞除了造成線程阻塞和服務超時,還會導致額外異常甚至波及其他底層依賴服務。當然,我的建議是,如果條件允許,最好是在項目初期設計時就進行規劃并確定。

緩存“表”(Table)

一般緩存中并沒有傳統RDBMS中直觀的表概念(往往以鍵值對“KV”形式存在),但從結構上來講,鍵值對本身就可以組裝為各種表結構。一般我會先生成數據庫表關系圖,然后分析什么時候存儲字符串,什么時候存儲對象,然后使用緩存鍵(KEY)進行表和字段(列)分割。

假定需要存儲一個登錄服務器表數據,包含字段(列):name、sign、addr,那么可以考慮將數據結構拆分為以下形式:

  { key : "server:name" , value : "xxxx" }

  { key : "server:sign" , value : "yyyy" }

  { key : "server:addr" , value : "zzzz" }

需要注意的是,往往在分布式緩存產品中,例如Redis,存在多種數據結構(如String、Hash等),還需要根據數據關聯性和列的數量,來選擇對應緩存的存儲數據結構,相關存儲空間和時間復雜度是完全不同的,而這個在初期階段是很難感受到的。

同時,就算緩存的內存設置的足夠大,剩余也很多,也同樣需要考慮類似RDBMS中的單表容量問題,控制條目數量不能無限增長(比如預知到存儲條目可以輕松達到百萬級),“分庫分表”的設計思路都是相通的。

緩存鍵(Key)

上面提到了基于緩存鍵來設計表,這里再單獨說明一下鍵相關的個人規范。在鍵長度足夠簡短的前提下,如果關聯相同業務模塊,則必須設計為以同一個標識(代號)開頭,目的是方便查找和統計管理。

如用戶登錄服務器列表:

  { key : "ul:server:a" , value : "xxxx" }

  { key : "ul:server:b" , value : "yyyy" }

另外,每個獨立業務系統可考慮配置一個唯一的通用前綴標識。當然,這里不是必需,若實際工作中,如果使用的是不同庫,則可以忽略。

緩存值(value)

緩存中的值(這里指單一條目)的大小沒有平均標準,但Size自然是越小越好(若使用的是Redis,一次操作的value較大會直接影響整個Redis的響應時間,不僅僅是指網絡I/O)。如果存儲占用空間直達10M+,建議考慮關聯的業務場景是否可以拆分為熱點和非熱點數據。

持久化(Permanence)

上面也簡單提了下,一般來說,持久和緩存本身是沒有直接關系的,可以粗略想象為一個面向硬盤一個面向內存。但如今的Web項目里,有些業務場景是高度依賴緩存的,持久化可以一方面幫助提高緩存服務重啟后的快速恢復,另一方面提供特定場景下的存儲特性。當然,由于持久化必然需要犧牲一些性能,包括CPU的搶占和硬盤I/O影響。不過大多數時候是利大于弊,建議在應用緩存的時候,沒有特別情況的話,盡量搭配持久化,無論是使用自身機制還是第三方來實現。

如果是使用的Redis,其自身就具備相關持久策略,包含AOF和RDB,我在大多數情況下是兩者同時配置的(當然,最新官方版本本身也提供了混合模式)。如果在一些非高并發的場景下,或者說在一些中小項目的管理模塊里,僅僅只是作為優化手段,確定了不需持久,也可以直接設置關閉,節約性能開銷損耗,但建議在程序中將該實例做好標注,確保該實例的公共使用范圍。

淘汰(Eliminate)

緩存如果無限制的增長,即使設置了較短的過期(Expiration ),在一些時間點上,高并發的一批大數據會在較短時間內就達到了可使用內存的峰頂,此時程序中與緩存服務器的交互會出現大量延遲和錯誤,甚至給服務器自身都帶來了嚴重的不穩定性。所以在生產環境里盡量給緩存配置最大內存限制,以及適當的淘汰策略。

如果使用的是Redis,自身淘汰策略選擇比較靈活。

個人的設計是,在數據呈現類似冪律分布情況下,總有大量數據訪問較低,我會選擇配置allkeys-lru、volatile-lru,將最少訪問的數據進行淘汰。再比如緩存是作為日志應用的,那么我一般是項目前期是配置no-enviction,后期會配置為volatile-ttl。

當然,我也見過一種特殊業務下的設計,緩存直接用來作為輕量的持久數據庫使用,而且是終端,開始覺得有些新奇,后來發現是非常符合業務設計的(比如幾乎沒有任何復雜邏輯和強事務)。所以合情合理,確實不應該禁錮在傳統設計里,畢竟架構總是基于業務去實時組合和改變的。

詳談分布式系統緩存的設計細節

 

 


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

张掖市| 大庆市| 衡阳市| 潜山县| 军事| 喀喇沁旗| 肥乡县| 囊谦县| 灵山县| 岱山县| 乌拉特后旗| 明水县| 灌阳县| 麟游县| 故城县| 星子县| 含山县| 集贤县| 宝应县| 青田县| 图们市| 乐昌市| 台州市| 新乐市| 永川市| 景德镇市| 额尔古纳市| 富裕县| 平乡县| 遵义县| 岳西县| 罗江县| 琼中| 浙江省| 虞城县| 航空| 兰考县| 巴中市| 太谷县| 嘉荫县| 黄浦区|