CoolHash數據庫引擎壓測對比報告
Coolhash 當前性能指標:讀寫吞吐量超過百萬,千萬級別查詢1秒完成,連續48小時打滿CPU強壓力運行穩定。redis官方公布讀寫性能在10萬 tps,leveldb官方公布寫性能在40萬tps,讀在6萬tps,redis和leveldb都是傾向k/v高速讀寫,但不具備高效檢索功能,沒有 join關聯設計。coolhash可以拿去pk世界上任何的數據庫引擎產品。
下面以redis為例進行了詳細測試和技術分析,leveldb 的性能可詳見其官方資料,在寫性能上優于redis,但是讀性能和多數據結構支持上不如redis,leveldb讀代價高是因為需要在內存以及各級數據 文件逐項查找并要優先考慮數據最新狀態,另外redis還提供server和集群功能,leveldb不提供,redis是內存方式+內存快照持久化,而 leveldb是Memtable+硬盤持久化,leveldb持久化不受內存限制,也做到了接近緩存的性能,未來k/v數據庫的趨勢最好能直接當作緩存 使用,并能支持高效檢索功能。
按照redis的常用方式,我們在一臺服務器上進行redis“單server”和“多server”的測試:
從上面兩個圖,我們可以看到:
redis是一個單進程單線程的實現,單server的讀寫TPS大概在8—12萬(跟redis官網公布的數據一致),為了充分利用能夠資源,redis官方建議一臺機器部署多個redis server。
上面第二個圖的TPS超過了8-12萬的限制,這實際上是在一臺服務器上部署了多個redis server,并將該服務器總的吞吐量算到一個redis server上得到的。但是寫的時候是客戶端各自寫不同的redis server,多個redis server之間的數據是彼此獨立的,在不同的內存空間中,如果分開計算每個redis server的寫入總量除以時間,TPS還是在8-12萬左右。
我們再到24核/256g/SATA硬盤的pc server上測試一下redis的benchmark,200個客戶端共寫入2000萬數據,發現性能變化不大,還是在10萬左右的TPS,又測試了20個客戶端寫入2000萬數據,12萬TPS:
Redis很優秀,但是也有一些局限:
redis不是一個并行數據庫,由單進程單線程實現,已經做到了單進程極限,性能很難再突破。如果要重新改寫redis,代價很大,而且 只有redis作者有能力做,其他外圍的捐獻者動不了。redis官方采取一種曲線救國方式,不改變單進程模式,采取外圍做集群,部署多個server來 提高CPU利用率,redis3.0的集群方案使用一種hash slot算法(不是一致哈希),用多個redis server做數據分片存儲,按照crc16/16384取模方式,讓客戶端根據hash slot的配置尋址,擴容按照slot單位做數據遷移達到負載均衡。由于在同臺服務器也存在多server實例集群,會牽扯出很多server的 master-slave復制和數據遷移一致性等復雜性,也容易引起后端的IO爭用,特別是在AOF模式時。
redis是一種內存快照方式,也就意味著它的持久化大小受內存限制,不是真正的數據庫持久化存儲,內存是昂貴的,為了擴大內存存儲,往 往需要更多的服務器搭建緩存集群,redis作者曾想增加一種diskstore的全持久化+cache方式,采用SHA1算法來建立存儲結構,來改進內 存快照方式的種種不足,但是涉及到對redis底層持久化方式的重構,這個計劃從11年提出,截至到目前3.0版本,仍然還沒有提供。
redis的存儲方式不是按照數據庫存儲索引結構設計,無法做到高性能的按范圍、按key/value的模糊檢索,更多只能在內存中進行全局數據的遍歷過濾,沒有高效的查詢功能,redis更適合做緩存讀寫,不適合當作數據庫存儲使用。
國內的redis使用團隊更多也是在運維工具、監控管理、主備、故障恢復等等方面改進,不具備對上面redis的3點內核局限的重構能力。
我們接下來在同機環境(24核/256g/SATA硬盤)測試coolhash, 實際上coolhash也可以像上面redis那樣在一臺服務器上部署多個server實例,但是我們這里啟動一個coolhash就夠了。 coolhash是一個并行數據庫引擎和數據庫server,可以通過調整“coolhash數據工人數量、客戶端并發數量、每客戶端讀寫數量”三個指標 項達到一臺服務器的最佳吞吐量性能。
coolhash通過一組數據工人并行的完成任務,我們先測試一個coolhash啟動多少個數據工 人最合適,下面在一臺服務器上運行coolhash并分別啟動1-96個工人,再用另外一臺服務器模擬了200個客戶端并發,每個客戶端寫入10萬數據, 累計2000萬數據,數據格式key=n(0
測試1:x個數據工人,200個客戶端并發,每個客戶端寫入10萬數據
數據工人 | 1個工人 | 8個工人 | 24個工人 | 32個工人 | 96個工人 |
耗時 | 400秒 | 40秒 | 20秒 | 23秒 | 25秒 |
cpu最高峰 | 10% | 20% | 75% | 85% | 90% |
TPS | 5萬/秒 | 50萬/秒 | 100萬/秒 | 87萬/秒 | 80萬/秒 |
分析:可以清晰的看到并行數據庫的優勢明顯,如果只有一個數據工人,也就是單進程模式,它的TPS是很難超出 10萬的,如果是8個數據工人并行作業,性能一下子就能從400秒減少到40秒,提升10倍,但也不是數據工人越多性能越好,我們看到24-32個工人是 個頂峰,如果再增加工人數雖然能提升cpu使用率,但是調度開銷大,后端硬盤io等跟不上,導致性能反而有所下降。
根據上面的結論,我們配置coolhash啟動24個數據工人最合適,接下來再進一步調整“客戶端并發數”和“每個客戶端寫入數量”,來達到一臺服務器的最佳性能。
測試2:24個數據工人,x個客戶端并發,每個客戶端寫入10萬數據
客戶端數 | 1并發 | 10并發 | 20并發 | 50并發 | 100并發 | 200并發 |
寫入總量 | 10萬 | 100萬 | 200萬 | 500萬 | 1000萬 | 2000萬 |
耗時 | 1秒 | 3秒 | 5秒 | 10秒 | 18秒 | 20秒 |
TPS | 10萬/秒 | 33萬/秒 | 40萬/秒 | 50萬/秒 | 55萬/秒 | 100萬/秒 |
分析:如果每個客戶端寫相同數量的數據,隨著并發數的提高,總體的吞吐量會高于單客戶端呈線性增長趨勢,但是受 服務器cpu、內存、io等性能限制,不會一直增長,會傾向于一個平衡值。每臺服務器并不是能承受無限大的并發數量,如果超出了承受限制,客戶端會長時間 等待,容易產生socket連接超時。合理的控制并發數量能提升服務器的吞吐性能,下面我們增大每個客戶端的寫入數量,減少總的并發數,并觀察效果。
測試3:24個數據工人,20個客戶端并發,每個客戶端寫入x萬數據
每客戶端寫 | 10萬/每 | 50萬/每 | 100萬/每 | 200萬/每 | 300萬/每 |
寫入總量 | 200萬 | 1000萬 | 2000萬 | 4000萬 | 6000萬 |
耗時 | 4秒 | 6秒 | 10秒 | 15秒 | 22秒 |
寫TPS | 50萬/秒 | 167萬/秒 | 200萬/秒 | 267萬/秒 | 272萬/秒 |
分析:可以看到同樣寫入2000萬數據,采用20并發*100萬比200并發*10萬的性能提升了一倍,能達到 200萬以上TPS。這是因為客戶端建立連接后,一次提交100萬條數據的寫入請求,相比每條數據連接server,能很大節省網絡開銷和硬盤IO開銷。 由此我們也能得到,并不是并發連接越多越好,而是控制一定數量的連接池性能會更好。
接下來我們再以使用相同參數,測試一下讀的性能。
測試4:24個數據工人,20個客戶端并發,每個客戶端讀出x萬數據
每客戶端讀 | 10萬/每 | 50萬/每 | 100萬/每 | 200萬/每 | 300萬/每 |
讀出總量 | 200萬 | 1000萬 | 2000萬 | 4000萬 | 6000萬 |
耗時 | 4秒 | 6秒 | 11秒 | 20秒 | 30秒 |
讀TPS | 50萬/秒 | 167萬/秒 | 182萬/秒 | 200萬/秒 | 200萬/秒 |
分析:coolhash是一個讀寫平衡的數據庫引擎,可以看到讀和寫的性能相差不大,都能達到200萬的TPS。
coolhash 提供了高效的查詢檢索功能,可以支持key和value的同時模糊查詢,下面按照600萬—3億不同的數據總量進行模糊查詢,數據格式為key=n(0& lt;n<3億),value=n(0
測試5:24個數據工人,x個客戶端模糊查詢x萬數據
單個客戶端模糊查詢:
數據總量 | 600萬 | 2000萬 | 6000萬 | 1億 | 3億 |
耗時 | 0.9秒 | 1秒 | 1.7秒 | 2秒 | 6秒 |
多個客戶端高并發模糊查詢:
客戶端數 | 1并發 | 10并發 | 20并發 | 50并發 | 100并發 | 200并發 |
600萬 | 0.9秒 | 2秒 | 4秒 | 9秒 | 14秒 | 18秒 |
2000萬 | 1秒 | 4秒 | 9秒 | 21秒 | 37秒 | 45秒 |
分析:對于千萬級別的數據,客戶端一次任意模糊查詢的耗時都是在1秒完成,如果超過1億需要2秒,3億需要6秒 (在沒有額外構建索引情況下)。如果是100個客戶端并發模糊查詢,按照上面表格里100并發查詢2000萬數據,平均耗時37秒,每次查詢耗時 37/100=0.37秒,每秒查詢次數100/37=2.7次,每秒查詢數據范圍大小100*2000萬/37秒=5400萬。這里測試key是“*” 代表所有,如果key根據業務特點進行了分層設計,以“user.*.name”這樣形式模糊查詢,范圍會縮小,速度會更快。
測試6:壓力測試,200高并發下每客戶端讀取10萬數據連續48小時不間斷,服務端cpu、內存、帶寬資源高壓力運行穩定無異常。
下面歸納一下coolhash和redis的基本區別:
redis | coolhash | |
實現語言 | c | java |
大小 | 2.3萬行代碼 | 小于1萬行(含fourinone) |
運行環境 | Linux | Linux/windows |
數據庫類型 | k/v緩存數據庫 | k/v持久化數據庫 |
實現模式 | 單進程模式,所有操作單線程完成 | 多進程模式,并行數據庫,所有操作并行完成 |
持久化模式 | 內存快照,aof日志 | 硬盤持久化+cache |
存儲大小 | 受內存大小限制 | 無限制,取決硬盤大小 |
數據類型支持 | String,Hash,List,Set,Sorted set等,List是一個雙向鏈表實現,可用于實現消息隊列。 | 基本數據類型:“String、short、int、long、double、float、Date”,高級數據類型:大部分的java集合都能支持(List、Map、Set等),以及任意可序列化的自定義java類型,底層數據類型:二進制型 |
存儲結構 | redisDb內存結構,Key和key之間無聯系,無上下層結構 | 按照數據庫索引存儲結構設計,CoolHash算法實現,支持key的樹型層次結構 |
查詢檢索 | 沒有針對范圍檢索設計 | Key索引+并行計算高效查詢,查詢性能在秒級 |
關聯設計 | 沒有針對join設計 | Key指針設計,并可連續指,支持建立1對1、1對n、n對n的復雜關聯關系 |
讀寫性能 | 單server吞吐量10萬tps(內存) | 單server可達到百萬以上tps(硬盤) |
事務處理 | 支持,但沒有事務隔離級別 | 支持ACID,實現TRANSACTION_SERIALIZABLE隔離級別 |
Server支持 | 支持 | 支持 |
命令行支持 | 支持 | 不支持 |
主備支持 | 直接支持,通過redis.conf配置主備 | 不直接支持,提供fttp分布式備份api開發包支持 |
集群支持 | 3.0版直接支持,通過hash slot算法 | 不直接支持,提供分布式緩存集群和fttp等開發包支持 |
總結:
首先不能簡單的以實現語言來衡量性能,認為c實現的就一定比java高效,數據庫引擎的效率提升更多取決于底層算法改進和設計突破,c在底層和操作系統交互上有優勢,但是取決于開發者,一個蹩腳的c工程師寫出的代碼只會低效和漏洞百出。
redis的優勢在于快速的緩存讀寫、豐富的數據類型支持,以及完善的主備復制和集群實現,劣勢在于單進程模式、內存限制、查詢檢索等方面。
coolhash是一個并行數據庫引擎,在很多地方采用了大膽創新的設計,并獲得了很好的性能體驗,改進后的哈希算法能實現更快的讀寫吞 吐量,key層次結構和key指針等設計能實現更高效的查詢檢索和join關聯。由于只做數據庫引擎,暫不提供主備和集群功能,但是fourinone提 供了大部分分布式技術簡單實現的開發API,開發者可以利用這些自己去實現。
隨著數據庫實現技術的發展,kv緩存和kv持久化存儲的性能越來越接近,邊界會越來越模糊,也會越來越涵蓋關系數據庫的功能。存儲硬件技術也在發展,未來在內存+ssd混合存儲上還會有更好的性能突破。
以上測試程序和運行包都來源于fourinone4.0版本,可以到以下地址下載:
google code svn:http://fourinone.googlecode.com/svn/trunk/
國內oschina code:https://git.oschina.net/fourinone/fourinone/blob/master/fourinone-4.05.06.zip
CoolHash數據庫demo目錄內容:
RunServer.java:啟動服務端
RunClient.java:啟動客戶端
CoolHashTestRun.java:啟動多個并發客戶端
CoolHash作者聲明:歡迎各位朋友理性驗證和討論,不歡迎不理會各種噴子言論。
這 里有很多人是redis和leveldb的使用者和封裝者,其中一部分人會看coolhash不爽,甚至失去理性變成噴子,對coolhash大加攻擊和 詆毀,希望coolhash只是玩具,希望coolhash沒有場景...但是噴子們要清楚自己的位置,redis和leveldb不是你的作品,你只是 站在洋人前面狐假虎威而已,核心層面的東西你甚至不具備發言權。長期以來國內工程師都是以學習和使用國外開源軟件為生存技能,能理解這些人也只是混口飯 吃。
很多人軟件思想意識落后,“軟件傻瓜化”超出了他的理解范 圍,看到demo簡單,便誤認為框架源碼也膚淺,看到demo里沒有synchronized,便以為框架沒有同步,有人甚至懷疑源碼是假的。demo簡 單是為了保護用戶的自信心和駕馭感,用戶只需要看到一個美麗的軀殼,血肉模糊的東西留給框架戴著口罩拿著手術刀去做,這實際上對設計者提出了更大的難度, 所以源碼要實現那么多功能,還要做到體驗傻瓜化,一定是非常精密的邏輯組成,源碼不可能像demo那樣通俗易懂。
一些人一來就對 fourinone源碼指手畫腳,評頭論足,大部分批評只停留在“編程規范、格式、變量名、包名、調了哪些工具類”這些層面,這些人需要多花時間提升自己 的技術積累、設計能力、算法能力,才能真正理解源碼的各種行為,作者到過國內各種IT企業,非常清楚國內工程師的技術能力能到什么程度,國內的開源軟件大 部分是基于國外開源軟件封裝后的二次開源,真正意義上的原創很少,大部分中國IT企業處在產業鏈末端,沒有核心技術,依靠外包勞動力,工程師的技術壽命很 短,平均只有3-5年,然后周圍環境會暗示他轉向管理或者業務,只有這樣才能得到領導認可,技術積累太短暫,技術人員沒有悟性,也缺乏興趣,過于依賴國 外,是不可能在核心軟件層面有真正的原創。
一些人對coolhash很質疑,認為很少人很少代碼實現不了高性能,實際上早在幾年 前,fourinone就在一片質疑聲中被要求壓測,結果出乎意料在計算性能上優于hadoop,現在coolhash只是重演了創新能力而已。建議各種 質疑者跟風者先放下政治偏見、利益沖突、情感排斥,耐心的動手去試試。對于技術上缺乏分辨力的人,建議你認準三點,一看上手是否容易;二看功能是否強大; 三看性能是否高效,只要滿足這三點就沒有人可以忽悠得了你,然后你再結合源碼去反思是如何做到的。
曾國藩說過“竊喜洋人之智巧中國亦能為之,彼不能傲我以其所不知矣!”
文 人不相輕,技術歸技術,本文對redis和leveldb的作者充滿尊敬和虛心學習,Salvatore Sanfilippo(antirez) 說過代碼像一首詩,Jeffrey Dean更是google map/reduce的作者,他們都表現出很高的職業素養和天賦,是這些人推動著世界軟件技術的發展,也成為中國架構師內心難以跨越的豐碑。是存在差距, 但是可以站著學習,而不是跪著膜拜,一味跟從只會喪失判斷力和創新力,香港的年輕人曾經不相信大陸的taobao會比eBay強大,QQ會比MSN強大, 直到MSN垮了仍然不相信是真的,沒有信心,沒有努力,夢想只會變成做夢。
來自:http://my.oschina.net/fourinone/blog/289122