驚現(xiàn)支撐1億pv/天的超級數(shù)據(jù)庫解決方案
更新時(shí)間:2008年07月23日 19:27:37 作者:
我說的系統(tǒng)主要是構(gòu)建在hibernate之上的高效數(shù)據(jù)庫緩存系統(tǒng),其中包含了分布式解決方案,該系統(tǒng)已經(jīng)應(yīng)用在舍得網(wǎng)上了,沒有發(fā)現(xiàn)大問題,
舍得網(wǎng)支撐1億pv/天構(gòu)架,開源了
說是支持1億pv/天,也許有點(diǎn)夸張,也是為了吸引您能點(diǎn)進(jìn)來,如果您能認(rèn)真看完相信也不會讓您失望,當(dāng)然,肯定有很多“高手”會對此會嗤之以鼻,沒關(guān)系,有很多眼高手低的人總喜歡評論別人卻從不會看清自己。
如果大家真想支持我、支持中國人開源項(xiàng)目,請把該文貼到自己的博客中或者收藏本文,記得包含文檔的下載地址?。。。。。?!謝謝。
我說的系統(tǒng)主要是構(gòu)建在hibernate之上的高效數(shù)據(jù)庫緩存系統(tǒng),其中包含了分布式解決方案,該系統(tǒng)已經(jīng)應(yīng)用在舍得網(wǎng)上了,沒有發(fā)現(xiàn)大問題,本人也相信該系統(tǒng)已經(jīng)足夠強(qiáng)大,應(yīng)付數(shù)百萬IP/天的應(yīng)用都不是問題,我這么說肯定有人會對此表示懷疑,其實(shí)系統(tǒng)到底能撐多少IP/天不在于系統(tǒng)本身而是在于使用該系統(tǒng)的人。
代碼看上去很簡單,其實(shí)卻是兩年經(jīng)驗(yàn)的總結(jié),整過過程也遇到了很多難點(diǎn),最后一一解決了,所以也請各位珍惜他人的勞動成果。本系統(tǒng)非常簡潔易用,主程序BaseManager.java不到1000行代碼,用“精悍”來形容絕對不為過,1000行代碼卻包含了數(shù)據(jù)庫對象的緩存、列表和長度的緩存、按字段散列緩存、update延時(shí)更新、自動清除列表緩存等功能,用它來實(shí)現(xiàn)像論壇、博客、校友錄、交友社區(qū)等絕大部分應(yīng)用網(wǎng)站都足夠了。
我在理想狀態(tài)下做了壓力測試,在沒有數(shù)據(jù)庫操作的jsp頁面(舍得網(wǎng)新首頁)里可以完成2000多requests每秒(正常情況可能有1/1000的request有數(shù)據(jù)庫查詢,其余999/1000都是直接從緩存里讀?。?,物品詳情頁每秒可完成3000多 requests,純靜態(tài)html頁面也只能完成7000多requests/秒,我對首頁進(jìn)行了三個(gè)小時(shí)的壓力測試,完成了24850800個(gè) requests,java一點(diǎn)事都沒有,內(nèi)存沒有上漲。按照2000個(gè)requests/秒算,一天按15小時(shí)計(jì)算,那么每天能完成 3600*15*2000=1億零8百萬requests,當(dāng)然這是理想狀態(tài),實(shí)際狀態(tài)就算打一折,還能完成1000萬pv/天,要知道,這只是一個(gè)普通 1萬3千塊錢買的服務(wù)器,內(nèi)存4G,CPU2個(gè),LinuxAS4系統(tǒng),apache2.0.63/resin2.1.17/jdk6.0的環(huán)境。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。?!,F(xiàn)在進(jìn)入正題。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
為什么要用緩存?如果問這個(gè)問題說明你還是新手,數(shù)據(jù)庫吞吐量畢竟有限,每秒讀寫5000次了不起了,如果不用緩存,假設(shè)一個(gè)頁面有100個(gè)數(shù)據(jù)庫操作,50個(gè)用戶并發(fā)數(shù)據(jù)庫就歇菜,這樣最多能支撐的pv也就50*3600*15=270萬,而且數(shù)據(jù)庫服務(wù)器累得半死,搞不好什么時(shí)候就累死了。我的這套緩存系統(tǒng)比單獨(dú)用memcached做緩存還要強(qiáng)大,相當(dāng)于在memcached上再做了兩級緩存,大家都知道m(xù)emcached很強(qiáng)了,但是吞吐量還是有限,每秒20000次get和put當(dāng)遇到超大規(guī)模的應(yīng)用時(shí)還是會歇菜,本地HashMap每秒可執(zhí)行上百萬次put和get,在這上面損耗的性能幾乎可以忽略不記了。溫馨提示:能不用分布式的時(shí)候就不要用分布式,非用分布式的時(shí)候再考慮用memcached,我的緩存系統(tǒng)在這方面都已經(jīng)實(shí)現(xiàn)了,改個(gè)配置就可以了,有興趣的可以仔細(xì)測試測試!
一般數(shù)據(jù)庫緩存在我看來包含四種。第一種:單個(gè)對象的緩存(一個(gè)對象就是數(shù)據(jù)庫一行記錄),對于單個(gè)對象的緩存,用HashMap就可以了,稍微復(fù)雜一點(diǎn)用LRU算法包裝一個(gè)HashMap,再復(fù)雜一點(diǎn)的分布式用memcached即可,沒什么太難的;第二種:列表緩存,就像論壇里帖子的列表;第三種:長度的緩存,比如一個(gè)論壇板塊里有多少個(gè)帖子,這樣才方便實(shí)現(xiàn)分頁。第四種:復(fù)雜一點(diǎn)的 group,sum,count查詢,比如一個(gè)論壇里按點(diǎn)擊數(shù)排名的最HOT的帖子列表。第一種比較好實(shí)現(xiàn),后面三種比較困難,似乎沒有通用的解決辦法,我暫時(shí)以列表緩存(第二種)為例分析。
mysql和hibernate的底層在做通用的列表緩存時(shí)都是根據(jù)查詢條件把列表結(jié)果緩存起來,但是只要該表的記錄有任何變化(增加/刪除/修改),列表緩存要全部清除,這樣只要一個(gè)表的記錄經(jīng)常變化(通常情況都會這樣),列表緩存幾乎失效,命中率太低了。
本人想了一個(gè)辦法改善了列表緩存,當(dāng)表的記錄有改變時(shí),遍歷所有列表緩存,只有那些被影響到的列表緩存才會被刪除,而不是直接清除所有列表緩存,比如在一個(gè)論壇版(id=1)里增加了一個(gè)帖子,那么只要清除id=1這個(gè)版對應(yīng)的列表緩存就可以了,版id=2就不用清除了。這樣處理有個(gè)好處,可以緩存各種查詢條件(如等于、大于、不等于、小于)的列表緩存,但也有個(gè)潛在的性能問題,由于需要遍歷,CPU符合比較大,如果列表緩存最大長度設(shè)置成10000,兩個(gè) 4核的CPU每秒也只能遍歷完300多次,這樣如果每秒有超過300個(gè)insert/update/delete,系統(tǒng)就吃不消了。
在前面兩種解決辦法都不完美的情況下,本人和同事經(jīng)過幾個(gè)星期的思索,總算得出了根據(jù)表的某幾個(gè)字段做散列的緩存辦法,這種辦法無需大規(guī)模遍歷,所以CPU 符合非常小,由于這種列表緩存按照字段做了散列,所以命中率極高。思路如下:每個(gè)表有3個(gè)緩存Map(key=value鍵值對),第一個(gè)Map是對象緩存A,在A中,key是數(shù)據(jù)庫的id,Value是數(shù)據(jù)庫對象(也就是一行數(shù)據(jù));第二個(gè)Map是通用列表緩存B,B的最大長度一般1000左右,在B 中,key是查詢條件拼出來的String(如start=0,length=15#active=0#state=0),Value是該條件查詢下的所有id組成的List;第三個(gè)Map是散列緩存C,在C中,key是散列的字段(如根據(jù)userId散列的話,其中某個(gè)key就是userId=109這樣的String)組成的String,value是一個(gè)和B類似的HashMap。其中只有B這個(gè)Map是需要遍歷的,不知道說明白了沒有,看完小面這個(gè)例子應(yīng)該就明白了,就用論壇的回復(fù)表作說明,假設(shè)回復(fù)表T中假設(shè)有字段id,topicId,postUserId等字段(topicId就是帖子的 id,postUserId是發(fā)布者id)。
第一種情況,也是最常用的情況,就是獲取一個(gè)帖子對應(yīng)的回復(fù),sql語句應(yīng)該是象
select id from T where topicId=2008 order by createTime desc limit 0,5
select id from T where topicId=2008 order by createTime desc limit 5,5
select id from T where topicId=2008 order by createTime desc limit 10,5
的樣子,那么這種列表很顯然用topicId做散列是最好的,把上面三個(gè)列表緩存(可以是N個(gè))都散列到key是topicId=2008這一個(gè)Map中,當(dāng)id是2008的帖子有新的回復(fù)時(shí),系統(tǒng)自動把key是topicId=2008的散列Map清除即可。由于這種散列不需要遍歷,因此可以設(shè)置成很大,例如100000,這樣10萬個(gè)帖子對應(yīng)的所有回復(fù)列表都可以緩存起來,當(dāng)有一個(gè)帖子有新的回復(fù)時(shí),其余99999個(gè)帖子對應(yīng)的回復(fù)列表都不會動,緩存的命中率極高。
第二種情況,就是后臺需要顯示最新的回復(fù),sql語句應(yīng)該是象
select id from T order by createTime desc limit 0,50
的樣子,這種情況不需要散列,因?yàn)楹笈_不可能有太多人訪問,常用列表也不會太多,所以直接放到通用列表緩存B中即可。
第三種情況,獲取一個(gè)用戶的回復(fù),sql語句象
select id from T where userId=2046 order by createTime desc limit 0,15
select id from T where userId=2046 order by createTime desc limit 15,15
select id from T where userId=2046 order by createTime desc limit 30,15
的樣子,那么這種列表和第一種情況類似,用userId做散列即可。
第四種情況,獲取一個(gè)用戶對某個(gè)帖子的回復(fù),sql語句象
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 0,15
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 15,15
的樣子,這種情況比較少見,一般以topicId=2008為準(zhǔn),也放到key是topicId=2008這個(gè)散列Map里即可。
那么最后的緩存結(jié)構(gòu)應(yīng)該是下面這個(gè)樣子:
緩存A是:
Key鍵(long型) Value值(類型T)
11 Id=11的T對象
22 Id=22的T對象
133 Id=133的T對象
……
列表緩存B是:
Key鍵(String型) Value值(ArrayList型)
from T order by createTime desc limit 0,50 ArrayList,對應(yīng)取出來的所有id
from T order by createTime desc limit 50,50 ArrayList,對應(yīng)取出來的所有id
from T order by createTime desc limit 100,50 ArrayList,對應(yīng)取出來的所有id
……
散列緩存C是:
Key鍵(String型) Value值(HashMap)
userId=2046 Key鍵(String型) Value值(ArrayList)
userId=2046#0,5 id組成的List
userId=2046#5,5 id組成的List
userId=2046#15,5 id組成的List
……
userId=2047 Key鍵(String型) Value值(ArrayList)
userId=2047#0,5 id組成的List
userId=2047#5,5 id組成的List
userId=2047#15,5 id組成的List
……
userId=2048 Key鍵(String型) Value值(ArrayList)
userId=2048#topicId=2008#0,5 id組成的List
userId=2048#5,5 id組成的List
userId=2048#15,5 id組成的List
……
……
總結(jié):這種緩存思路可以存儲大規(guī)模的列表,緩存命中率極高,因此可以承受超大規(guī)模的應(yīng)用,但是需要技術(shù)人員根據(jù)自身業(yè)務(wù)邏輯來配置需要做散列的字段,一般用一個(gè)表的索引鍵做散列(注意順序,最散的字段放前面),假設(shè)以userId為例,可以存儲N個(gè)用戶的M種列表,如果某個(gè)用戶的相關(guān)數(shù)據(jù)發(fā)生變化,其余N- 1個(gè)用戶的列表緩存紋絲不動。以上說明的都是如何緩存列表,緩存長度和緩存列表思路完全一樣,如緩存象select count(*) from T where topicId=2008這樣的長度,也是放到topicId=2008這個(gè)散列Map中。如果再配合好使用mysql的內(nèi)存表和memcached,加上F5設(shè)備做分布式負(fù)載均衡,該系統(tǒng)對付像1000萬IP/天這種規(guī)模級的應(yīng)用都足夠了,除搜索引擎外一般的應(yīng)用網(wǎng)站到不了這種規(guī)模。
再次申明:系統(tǒng)到底是不是強(qiáng)大不在系統(tǒng)本身而在于使用該系統(tǒng)的人?。。?
這個(gè)緩存系統(tǒng)是我和同事幾年經(jīng)驗(yàn)的總結(jié),看似簡單,其實(shí)也沒那么簡單,把它作為開源有下面幾個(gè)目的:第一,真的希望有很多人能用它;第二:希望更多的人能夠完善和改進(jìn)它;第三:希望大家能聚到一起為通用高效數(shù)據(jù)庫緩存構(gòu)架作出貢獻(xiàn),畢竟,數(shù)據(jù)庫操作是各種應(yīng)用最常用的操作,也是最容易產(chǎn)生性能瓶頸的地方。
Zip包中包含了配置方法和測試用的jsp,只要把它配置成一個(gè)web應(yīng)用就可以快速調(diào)試并看到緩存的力量了,文檔和下載地址是http://shedewang.com/akaladocs/api/com/akala/dbcache/core/BaseManager.html。
配置說明文件在docs/開始配置.txt里有說明。
最后啰嗦一句,如果大家真想支持我、支持中國人開源項(xiàng)目,請把該文貼到自己的博客中或者收藏本文,記得包含文檔的下載地址!?。。。。。≈x謝。thank you and Good luck。
QQ群:24561583
復(fù)制過來格式有點(diǎn)亂了,還是自己下載一個(gè)下來看看吧,里面有個(gè)word文檔,寫得比較清晰。
說是支持1億pv/天,也許有點(diǎn)夸張,也是為了吸引您能點(diǎn)進(jìn)來,如果您能認(rèn)真看完相信也不會讓您失望,當(dāng)然,肯定有很多“高手”會對此會嗤之以鼻,沒關(guān)系,有很多眼高手低的人總喜歡評論別人卻從不會看清自己。
如果大家真想支持我、支持中國人開源項(xiàng)目,請把該文貼到自己的博客中或者收藏本文,記得包含文檔的下載地址?。。。。。?!謝謝。
我說的系統(tǒng)主要是構(gòu)建在hibernate之上的高效數(shù)據(jù)庫緩存系統(tǒng),其中包含了分布式解決方案,該系統(tǒng)已經(jīng)應(yīng)用在舍得網(wǎng)上了,沒有發(fā)現(xiàn)大問題,本人也相信該系統(tǒng)已經(jīng)足夠強(qiáng)大,應(yīng)付數(shù)百萬IP/天的應(yīng)用都不是問題,我這么說肯定有人會對此表示懷疑,其實(shí)系統(tǒng)到底能撐多少IP/天不在于系統(tǒng)本身而是在于使用該系統(tǒng)的人。
代碼看上去很簡單,其實(shí)卻是兩年經(jīng)驗(yàn)的總結(jié),整過過程也遇到了很多難點(diǎn),最后一一解決了,所以也請各位珍惜他人的勞動成果。本系統(tǒng)非常簡潔易用,主程序BaseManager.java不到1000行代碼,用“精悍”來形容絕對不為過,1000行代碼卻包含了數(shù)據(jù)庫對象的緩存、列表和長度的緩存、按字段散列緩存、update延時(shí)更新、自動清除列表緩存等功能,用它來實(shí)現(xiàn)像論壇、博客、校友錄、交友社區(qū)等絕大部分應(yīng)用網(wǎng)站都足夠了。
我在理想狀態(tài)下做了壓力測試,在沒有數(shù)據(jù)庫操作的jsp頁面(舍得網(wǎng)新首頁)里可以完成2000多requests每秒(正常情況可能有1/1000的request有數(shù)據(jù)庫查詢,其余999/1000都是直接從緩存里讀?。?,物品詳情頁每秒可完成3000多 requests,純靜態(tài)html頁面也只能完成7000多requests/秒,我對首頁進(jìn)行了三個(gè)小時(shí)的壓力測試,完成了24850800個(gè) requests,java一點(diǎn)事都沒有,內(nèi)存沒有上漲。按照2000個(gè)requests/秒算,一天按15小時(shí)計(jì)算,那么每天能完成 3600*15*2000=1億零8百萬requests,當(dāng)然這是理想狀態(tài),實(shí)際狀態(tài)就算打一折,還能完成1000萬pv/天,要知道,這只是一個(gè)普通 1萬3千塊錢買的服務(wù)器,內(nèi)存4G,CPU2個(gè),LinuxAS4系統(tǒng),apache2.0.63/resin2.1.17/jdk6.0的環(huán)境。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。?!,F(xiàn)在進(jìn)入正題。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
為什么要用緩存?如果問這個(gè)問題說明你還是新手,數(shù)據(jù)庫吞吐量畢竟有限,每秒讀寫5000次了不起了,如果不用緩存,假設(shè)一個(gè)頁面有100個(gè)數(shù)據(jù)庫操作,50個(gè)用戶并發(fā)數(shù)據(jù)庫就歇菜,這樣最多能支撐的pv也就50*3600*15=270萬,而且數(shù)據(jù)庫服務(wù)器累得半死,搞不好什么時(shí)候就累死了。我的這套緩存系統(tǒng)比單獨(dú)用memcached做緩存還要強(qiáng)大,相當(dāng)于在memcached上再做了兩級緩存,大家都知道m(xù)emcached很強(qiáng)了,但是吞吐量還是有限,每秒20000次get和put當(dāng)遇到超大規(guī)模的應(yīng)用時(shí)還是會歇菜,本地HashMap每秒可執(zhí)行上百萬次put和get,在這上面損耗的性能幾乎可以忽略不記了。溫馨提示:能不用分布式的時(shí)候就不要用分布式,非用分布式的時(shí)候再考慮用memcached,我的緩存系統(tǒng)在這方面都已經(jīng)實(shí)現(xiàn)了,改個(gè)配置就可以了,有興趣的可以仔細(xì)測試測試!
一般數(shù)據(jù)庫緩存在我看來包含四種。第一種:單個(gè)對象的緩存(一個(gè)對象就是數(shù)據(jù)庫一行記錄),對于單個(gè)對象的緩存,用HashMap就可以了,稍微復(fù)雜一點(diǎn)用LRU算法包裝一個(gè)HashMap,再復(fù)雜一點(diǎn)的分布式用memcached即可,沒什么太難的;第二種:列表緩存,就像論壇里帖子的列表;第三種:長度的緩存,比如一個(gè)論壇板塊里有多少個(gè)帖子,這樣才方便實(shí)現(xiàn)分頁。第四種:復(fù)雜一點(diǎn)的 group,sum,count查詢,比如一個(gè)論壇里按點(diǎn)擊數(shù)排名的最HOT的帖子列表。第一種比較好實(shí)現(xiàn),后面三種比較困難,似乎沒有通用的解決辦法,我暫時(shí)以列表緩存(第二種)為例分析。
mysql和hibernate的底層在做通用的列表緩存時(shí)都是根據(jù)查詢條件把列表結(jié)果緩存起來,但是只要該表的記錄有任何變化(增加/刪除/修改),列表緩存要全部清除,這樣只要一個(gè)表的記錄經(jīng)常變化(通常情況都會這樣),列表緩存幾乎失效,命中率太低了。
本人想了一個(gè)辦法改善了列表緩存,當(dāng)表的記錄有改變時(shí),遍歷所有列表緩存,只有那些被影響到的列表緩存才會被刪除,而不是直接清除所有列表緩存,比如在一個(gè)論壇版(id=1)里增加了一個(gè)帖子,那么只要清除id=1這個(gè)版對應(yīng)的列表緩存就可以了,版id=2就不用清除了。這樣處理有個(gè)好處,可以緩存各種查詢條件(如等于、大于、不等于、小于)的列表緩存,但也有個(gè)潛在的性能問題,由于需要遍歷,CPU符合比較大,如果列表緩存最大長度設(shè)置成10000,兩個(gè) 4核的CPU每秒也只能遍歷完300多次,這樣如果每秒有超過300個(gè)insert/update/delete,系統(tǒng)就吃不消了。
在前面兩種解決辦法都不完美的情況下,本人和同事經(jīng)過幾個(gè)星期的思索,總算得出了根據(jù)表的某幾個(gè)字段做散列的緩存辦法,這種辦法無需大規(guī)模遍歷,所以CPU 符合非常小,由于這種列表緩存按照字段做了散列,所以命中率極高。思路如下:每個(gè)表有3個(gè)緩存Map(key=value鍵值對),第一個(gè)Map是對象緩存A,在A中,key是數(shù)據(jù)庫的id,Value是數(shù)據(jù)庫對象(也就是一行數(shù)據(jù));第二個(gè)Map是通用列表緩存B,B的最大長度一般1000左右,在B 中,key是查詢條件拼出來的String(如start=0,length=15#active=0#state=0),Value是該條件查詢下的所有id組成的List;第三個(gè)Map是散列緩存C,在C中,key是散列的字段(如根據(jù)userId散列的話,其中某個(gè)key就是userId=109這樣的String)組成的String,value是一個(gè)和B類似的HashMap。其中只有B這個(gè)Map是需要遍歷的,不知道說明白了沒有,看完小面這個(gè)例子應(yīng)該就明白了,就用論壇的回復(fù)表作說明,假設(shè)回復(fù)表T中假設(shè)有字段id,topicId,postUserId等字段(topicId就是帖子的 id,postUserId是發(fā)布者id)。
第一種情況,也是最常用的情況,就是獲取一個(gè)帖子對應(yīng)的回復(fù),sql語句應(yīng)該是象
select id from T where topicId=2008 order by createTime desc limit 0,5
select id from T where topicId=2008 order by createTime desc limit 5,5
select id from T where topicId=2008 order by createTime desc limit 10,5
的樣子,那么這種列表很顯然用topicId做散列是最好的,把上面三個(gè)列表緩存(可以是N個(gè))都散列到key是topicId=2008這一個(gè)Map中,當(dāng)id是2008的帖子有新的回復(fù)時(shí),系統(tǒng)自動把key是topicId=2008的散列Map清除即可。由于這種散列不需要遍歷,因此可以設(shè)置成很大,例如100000,這樣10萬個(gè)帖子對應(yīng)的所有回復(fù)列表都可以緩存起來,當(dāng)有一個(gè)帖子有新的回復(fù)時(shí),其余99999個(gè)帖子對應(yīng)的回復(fù)列表都不會動,緩存的命中率極高。
第二種情況,就是后臺需要顯示最新的回復(fù),sql語句應(yīng)該是象
select id from T order by createTime desc limit 0,50
的樣子,這種情況不需要散列,因?yàn)楹笈_不可能有太多人訪問,常用列表也不會太多,所以直接放到通用列表緩存B中即可。
第三種情況,獲取一個(gè)用戶的回復(fù),sql語句象
select id from T where userId=2046 order by createTime desc limit 0,15
select id from T where userId=2046 order by createTime desc limit 15,15
select id from T where userId=2046 order by createTime desc limit 30,15
的樣子,那么這種列表和第一種情況類似,用userId做散列即可。
第四種情況,獲取一個(gè)用戶對某個(gè)帖子的回復(fù),sql語句象
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 0,15
select id from T where topicId=2008 and userId=2046 order by createTime desc limit 15,15
的樣子,這種情況比較少見,一般以topicId=2008為準(zhǔn),也放到key是topicId=2008這個(gè)散列Map里即可。
那么最后的緩存結(jié)構(gòu)應(yīng)該是下面這個(gè)樣子:
緩存A是:
Key鍵(long型) Value值(類型T)
11 Id=11的T對象
22 Id=22的T對象
133 Id=133的T對象
……
列表緩存B是:
Key鍵(String型) Value值(ArrayList型)
from T order by createTime desc limit 0,50 ArrayList,對應(yīng)取出來的所有id
from T order by createTime desc limit 50,50 ArrayList,對應(yīng)取出來的所有id
from T order by createTime desc limit 100,50 ArrayList,對應(yīng)取出來的所有id
……
散列緩存C是:
Key鍵(String型) Value值(HashMap)
userId=2046 Key鍵(String型) Value值(ArrayList)
userId=2046#0,5 id組成的List
userId=2046#5,5 id組成的List
userId=2046#15,5 id組成的List
……
userId=2047 Key鍵(String型) Value值(ArrayList)
userId=2047#0,5 id組成的List
userId=2047#5,5 id組成的List
userId=2047#15,5 id組成的List
……
userId=2048 Key鍵(String型) Value值(ArrayList)
userId=2048#topicId=2008#0,5 id組成的List
userId=2048#5,5 id組成的List
userId=2048#15,5 id組成的List
……
……
總結(jié):這種緩存思路可以存儲大規(guī)模的列表,緩存命中率極高,因此可以承受超大規(guī)模的應(yīng)用,但是需要技術(shù)人員根據(jù)自身業(yè)務(wù)邏輯來配置需要做散列的字段,一般用一個(gè)表的索引鍵做散列(注意順序,最散的字段放前面),假設(shè)以userId為例,可以存儲N個(gè)用戶的M種列表,如果某個(gè)用戶的相關(guān)數(shù)據(jù)發(fā)生變化,其余N- 1個(gè)用戶的列表緩存紋絲不動。以上說明的都是如何緩存列表,緩存長度和緩存列表思路完全一樣,如緩存象select count(*) from T where topicId=2008這樣的長度,也是放到topicId=2008這個(gè)散列Map中。如果再配合好使用mysql的內(nèi)存表和memcached,加上F5設(shè)備做分布式負(fù)載均衡,該系統(tǒng)對付像1000萬IP/天這種規(guī)模級的應(yīng)用都足夠了,除搜索引擎外一般的應(yīng)用網(wǎng)站到不了這種規(guī)模。
再次申明:系統(tǒng)到底是不是強(qiáng)大不在系統(tǒng)本身而在于使用該系統(tǒng)的人?。。?
這個(gè)緩存系統(tǒng)是我和同事幾年經(jīng)驗(yàn)的總結(jié),看似簡單,其實(shí)也沒那么簡單,把它作為開源有下面幾個(gè)目的:第一,真的希望有很多人能用它;第二:希望更多的人能夠完善和改進(jìn)它;第三:希望大家能聚到一起為通用高效數(shù)據(jù)庫緩存構(gòu)架作出貢獻(xiàn),畢竟,數(shù)據(jù)庫操作是各種應(yīng)用最常用的操作,也是最容易產(chǎn)生性能瓶頸的地方。
Zip包中包含了配置方法和測試用的jsp,只要把它配置成一個(gè)web應(yīng)用就可以快速調(diào)試并看到緩存的力量了,文檔和下載地址是http://shedewang.com/akaladocs/api/com/akala/dbcache/core/BaseManager.html。
配置說明文件在docs/開始配置.txt里有說明。
最后啰嗦一句,如果大家真想支持我、支持中國人開源項(xiàng)目,請把該文貼到自己的博客中或者收藏本文,記得包含文檔的下載地址!?。。。。。≈x謝。thank you and Good luck。
QQ群:24561583
復(fù)制過來格式有點(diǎn)亂了,還是自己下載一個(gè)下來看看吧,里面有個(gè)word文檔,寫得比較清晰。
相關(guān)文章
jsp自定義標(biāo)簽之ifelse與遍歷自定義標(biāo)簽示例
這篇文章主要介紹了jsp自定義標(biāo)簽之ifelse與遍歷自定義標(biāo)簽,需要的朋友可以參考下2014-03-03JSP開發(fā)之Struts2實(shí)現(xiàn)下載功能的實(shí)例
這篇文章主要介紹了JSP開發(fā)之Struts2實(shí)現(xiàn)下載功能的實(shí)例的相關(guān)資料,這里提供實(shí)現(xiàn)代碼幫助大家實(shí)現(xiàn)這樣的功能,希望能幫助到大家,需要的朋友可以參考下2017-08-08java易懂易用的MD5加密(可直接運(yùn)行) (1)
出于安全考慮,網(wǎng)絡(luò)的傳輸中經(jīng)常對傳輸數(shù)據(jù)做加密和編碼處理,其中涉及以下幾種2008-11-11jsp 開發(fā)之struts2中s:select標(biāo)簽的使用
這篇文章主要介紹了jsp 開發(fā)之struts2中s:select標(biāo)簽的使用的相關(guān)資料,需要的朋友可以參考下2017-08-08JSP 中Spring的Resource類讀寫中文Properties實(shí)例代碼
這篇文章主要介紹了JSP 中Spring的Resource類讀寫中文Properties實(shí)例代碼的相關(guān)資料,需要的朋友可以參考下2017-03-03