Design a high performance cache for multi-threaded environment

如何設計一個支持高并發的高性能緩存庫

不 考慮并發情況下的緩存的設計大家應該都比較清楚,基本上就是用map/hashmap存儲鍵值,然后用雙向鏈表記錄一個LRU來用于緩存的清理。這篇文章 應該是講得很清楚http://timday.bitbucket.org/lru.html。但是考慮到高并發的情況,如何才能讓緩存保持高性能呢?

高并發緩存需要解決2個問題:1. 高效率的內存分配;2. 高效率的讀取,插入和清理數據。關于第一個問題涉及到高效率的內存分配器,使用成熟的jemalloc/tcmalloc足夠滿足需求。這里探討下如何解決第二個問題。

由 于緩存系統的特點, 每次讀取緩存都需要更新一些訪問信息(最后讀取時間,訪問頻率),在清理時會根據這些信息使用不同的策略來進行數據清理,這樣看來似乎每次的讀操作都變成 了寫操作。看過幾篇文章都比較集中在如何優化這個讀操作修改LRU的行為。例如:?http://www.ebaytechblog.com/2011 /08/30/high-throughput-thread-safe-lru-caching/#.UzvEb3V53No 以及?http://openmymind.net/High-Concurrency-LRU-Caching/, 但是這種情況下不論怎么優化,使用鏈表的LRU始終是個瓶頸, 因為每次讀操作只能一個線程來修改這個LRU鏈表,并且修改都是集中在鏈表的兩端。有些文章甚至使用lock-free的doubled linked list來減少鎖競爭。 一些成熟的緩存系統如memcached,使用的是全局的LRU鏈表鎖,而redis是單線程的所以不需要考慮并發的問題。由于這些都是遠程的緩存服務 器,因此它們的瓶頸往往是網卡,所以并發上面并不需要什么高要求。

仔 細思考后,發現在并發的情況下使用LRU鏈表來記錄訪問信息其實并不合適,會導致嚴重的鎖競爭,這點無法避免。因此,需要徹底放棄使用LRU鏈表。鑒于緩 存系統的特性,可以做如下假設: 緩存如果達到閥值,可以使插入立即返回失敗。這樣,我們可以使用一個預分配的數組來記錄所有的cache item的訪問信息。整個結構如下:

concurrent cache system arch

可 以看到鎖粒度是hashmap里面的bucket級別,每次讀操作只需對相應的bucket加鎖,然后更新bucket對應的訪問信息數組元素即可,由于 每個bucket對應的訪問信息是獨立占據數組的一個元素的,因此bucket鎖就保證了訪問信息的線程安全。這樣就解決了讀取操作的并發競爭問題。

接 下來看看如何解決插入問題。從圖可以看到,每個bucket的需要分配一個獨立的access info位置索引,多線程插入的時候會發生競爭,為了減少競爭,可以預先生成一個目前空閑的位置鏈表,這樣插入的時候,每個線程可以根據當前的 bucket索引選擇從不同的free鏈表里面分配一個位置。這樣鎖競爭可以分散到多個free list上面,每次插入時把分配過的位置索引從free list 移除。

最 后,清理過程可以放在一個獨立線程里面,為了避免插入因為緩存滿了而返回失敗,每次在緩存快滿的時候(free list的size不夠用了),進行一次access info array掃描。根據不同的緩存清除策略和訪問信息(時間和頻率)來決定哪些位置索引是可以重新釋放到free list列表。由于掃描過程中無需加鎖,掃描對讀取和插入操作是沒有性能影響的。只有最后進行釋放時才會對需要釋放的bucket和free list進行加鎖,鎖競爭大大減少。

如上設計,大大減少了緩存的讀取,插入和清理過程中的鎖競爭問題,并且讀取和插入都是O(1)的,并不會因為緩存系統的增大影響性能(清理后臺線程可能會跑的久點,可以選擇性清理來優化)。這樣一個支持高并發的緩存系統就完成了。

簡 單的實現后,實測在8核CPU上面8線程讀,8線程寫,可以跑到 讀寫TPS均在1M/S以上,參考官方單線程的redis的benchmark數據?Using a unix domain socket 排除網絡瓶頸,SET/GET的TPS大概在200k/s 左右,可以看到這樣一個高并發的cache基本上是scalable的。

轉載于:https://www.cnblogs.com/absolute8511/p/3641292.html

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

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

相關文章

《MySQL——join語句優化tips》

目錄要不要用joinJoin驅動表選擇Multi-Range Read優化Batched Key Access (BKA)對NLJ進行優化BNL算法性能問題BNL轉BKA要不要用join 1、如果使用的是Index Nested-Loop Join算法,即可以用上被驅動表的索引,可以用 2、如果使用的…

scala中抽象類_Scala中的抽象類

scala中抽象類抽象類 (Abstract Class) In the Scala programming language, abstraction is achieved using abstract class. 在Scala編程語言, 抽象是使用抽象類來實現的。 Abstraction is the process of showing only functionality and hiding the details fr…

不能catch Fatal的exception

Clemens Vasters - Are you catching falling knives?里給了一個判斷C#的exception是不是fatal的代碼,可以參考參考。 public static bool IsFatal(this Exception exception) {while (exception ! null){if (exception as OutOfMemoryException ! null &&…

HDU 2824 The Euler function

篩法計算歐拉函數 #include <iostream> #include <cstdio> using namespace std; const int maxn3000005; long long phi[maxn]; int main(){int i,j,a,b;for(i1;i<maxn;i) phi[i]i;for(i2;i<maxn;i2) phi[i]/2;for(i3;i<maxn;i2)if(phi[i]i){for(ji;j<…

LinkChecker 8.1 發布,網頁鏈接檢查

LinkChecker 8.1 可對檢查時間和最大的 URL 數量進行配置&#xff1b;當使用 HTTP 請求時發送 do-not-track 頭&#xff1b;生成 XML 的 sitemap 用于搜索引擎優化&#xff1b;檢測 URL 長度和重復的頁面內容&#xff1b;修復了很多檢查的 bug。 LinkChecker 是一個網頁鏈接檢查…

c語言語言教程0基礎_C語言基礎

c語言語言教程0基礎Hey, Folks here I am back with my second article on C language. Hope you are through with my previous article C language - History, Popularity reasons, Characteristics, Basic structure etc. In this one, I will cover some fundamental conce…

《MySQL——臨時表》

內存表與臨時表區別 臨時表&#xff0c;一般是人手動創建。 內存表&#xff0c;是mysql自動創建和銷毀的。 內存表&#xff0c;指的是使用Memory引擎的表&#xff0c;建表語法&#xff1a;create table ... engine memeory 表的數據存在內存里&#xff0c;系統重啟后會被清…

android中ActionBar的幾個屬性

actionBar.setHomeButtonEnabled //小于4.0版本的默認值為true的。但是在4.0及其以上是false&#xff0c;該方法的作用&#xff1a;決定左上角的圖標是否可以點擊。沒有向左的小圖標。 true 圖標可以點擊 false 不可以點擊。 actionBar.setDisplayHomeAsUpEnabled(true) //…

drei

模擬9 T3 &#xff08;COGS上也有&#xff0c;鏈接http://218.28.19.228/cogs/problem/problem.php?pid1428&#xff09; 題目描述 輸入a&#xff0c;p&#xff0c;求最小正整數x&#xff0c;使得a^x mod p 1。 分析 神奇的歐拉定理&#xff08;對于gcd&#xff08;a&#xf…

《MySQL——group by使用tips》

1、如果對group by語句結果沒有排序要求&#xff0c;在語句后面加order by null 2、盡量讓group by 過程用上索引&#xff0c;確認方法是explain結果里沒有Using temporary 和Using filesort 3、如果group by 需要統計的數據量不大&#xff0c;盡量只使用內存臨時表&#xff…

css中變量_CSS中的變量

css中變量CSS | 變數 (CSS | Variables) CSS variables allow you to create reusable values that can be used throughout a CSS document. CSS變量允許您創建可在CSS文檔中使用的可重用值。 In CSS variable, function var() allows CSS variables to be accessed. 在CSS變…

位圖像素的顏色 攜程編程大賽hdu

位圖像素的顏色 Time Limit: 2000/1000 MS (Java/Others) MemoryLimit: 32768/32768 K (Java/Others) Total Submission(s): 0 Accepted Submission(s): 0 Problem Description 有一個在位圖上畫出矩形程序&#xff0c;一開始位圖都被初始化為白色&#xff08;RGB顏色表示…

《MySQL——InnoDB與Memory以及臨時表》

InooDB與Memory 數據組織方式不同&#xff1a; InnoDB引擎把數據放在主鍵索引上&#xff0c;其他索引上保存的是主鍵id。為索引組織表Memory引擎把數據單獨存放&#xff0c;索引上保存數據位置。為堆組織表 典型不同處&#xff1a; 1、InnoDB表的數據總是有序存放的&#x…

Oracle 用戶 profile 屬性 轉

--查看profile 內容 select * from dba_profiles where profilePF_EAGLE; --查看用戶的profiles select username,profile from dba_users; --查看是否啟用動態資源限制參數 SHOW PARAMETER RESOURCE_LIMIT; --啟用限制 ALTER SYSTEM SET RESOURCE_LIMITTRUE SCOPEBOTH; --創建…

CUL8R的完整形式是什么?

CUL8R&#xff1a;稍后再見 (CUL8R: See You Later) CUL8R is an abbreviation of "See You Later". CUL8R是“稍后見”的縮寫 。 It is an expression, which is commonly used in messaging or chatting on social media networking sites like Facebook, Yahoo M…

SuperSpider——打造功能強大的爬蟲利器

SuperSpider——打造功能強大的爬蟲利器 博文作者&#xff1a;加菲 發布日期&#xff1a;2013-12-11 閱讀次數&#xff1a;4506 博文內容&#xff1a; 1.爬蟲的介紹 圖1-1 爬蟲&#xff08;spider) 網絡爬蟲(web spider)是一個自動的通過網絡抓取互聯網上的網頁的程序&#xf…

《MySQL——關于grant賦權以及flush privileges》

先上總結圖&#xff1a; 對于賦予權限或者收回權限還是創建用戶&#xff0c;都會涉及兩個操作&#xff1a; 1、磁盤&#xff0c;mysql.user表&#xff0c;用戶行所有表示權限的字段的值的修改 2、內存&#xff0c;acl_users找到用戶對應的對象&#xff0c;將access值修改 g…

對Spring的理解

1、Spring實現了工廠模式的工廠類&#xff0c;這個類名為BeanFactory實際上是一個接口&#xff0c;在程序中通常BeanFactory的子類ApplicationContext。Spring相當于一個大的工廠類&#xff0c;在其配置文件中通過<bean>元素配置用于創建實例對象的類名和實例對象的屬性。…

Java中的null是什么?

As we know null is an important concept in every language not only in Java but here we will study various factors regarding null. 我們知道null在每種語言中都是重要的概念&#xff0c;不僅在Java中&#xff0c;在這里我們還將研究有關null的各種因素。 null is a ver…

《MySQL——分區表小記》

分區表的組織形式 以年份為分割方式&#xff0c;對表進行分割&#xff1a; CREATE TABLE t (ftime datetime NOT NULL,c int(11) DEFAULT NULL,KEY (ftime) ) ENGINEInnoDB DEFAULT CHARSETlatin1 PARTITION BY RANGE (YEAR(ftime)) (PARTITION p_2017 VALUES LESS THAN (201…