一個參考ssdb,使用go相似的實現redis高性能nosql:ledisdb

原由

ledisdb是一個參考ssdb。採用go實現,底層基於leveldb,類似redis的高性能nosql數據庫,提供了kv,list,hash以及zset數據結構的支持。c++

咱們現在的應用極大的依賴redis。但隨着咱們用戶量愈來愈大,redis的內存愈來愈不夠用。並且replication可能還會致使超時問題。git

儘管興許咱們可以經過加入多臺機器來解決。但是在現有機器配置如下。咱們仍但願單臺機器承載不少其它的用戶。另外,因爲業務的特性,咱們事實上並不需要將所有的數據放到內存。僅僅需要存放當前活躍用戶。github

通過咱們的調研,發現ssdb已經很是好的幫咱們攻克了這個問題,它提供了跟redis一致的接口(固然有些地方仍是略微不一樣)。但是底層採用leveldb進行存儲。redis

依據其官網的描寫敘述。性能已經接近甚至超越了redis。sql

 

本着造輪子的精神。我決定用go實現一個類似的db。取名爲ledisdb。也就是level-redis-db,爲啥不用現成的ssdb,我以爲有例如如下幾個緣由:數據庫

  • go語言開發的高速。這點毋庸置疑,儘管性能上面鐵定離c++的代碼有差距。但是我可以高速的進行原型搭建並實驗。實際上,我在很是短的時間裏面就開發出了ledisdb。讓我興許繼續開發有了信心。
  • leveldb的研究。我一直很是想將leveldb應用到咱們的項目中,做爲本機熱點數據的首選數據存儲方式。經過ledisdb,讓我對leveldb的使用有了很是多經驗。
  • redis的熟悉,儘管我用了很是久的redis,但是很是多redis的命令仍然需要去查手冊。經過實現ledisdb,我更加熟悉了redis的命令,同一時候,因爲要了解這個命令redis怎樣實現。對redis內部又又一次來了一次剖析。

在準備開發ledisdb的時候。我就在思索一個問題,我需不需要開發還有一個redis?事實上這是一個很是明白的問題,我不需要還有一個redis。json

ledisdb儘管參考了redis,但爲了實現簡單,有時候我作了很是多減法或者變動,譬如對於zset這樣的數據結構,我就僅僅支持int64類型的score。而redis的score是double類型的,詳細緣由興許解說zset的時候詳細說明。數據結構

因此,咱們可以以爲,ledisdb是一個基於redis通訊協議,提供了多種高級數據結構的nosql數據庫。它並不是還有一個redis。nosql

編譯安裝

因爲ledisdb是用go寫的,因此首先需要安裝go以及配置GOROOT,GOPATH。性能

mkdir $WORKSPACE
cd $WORKSPACE
git clone git@github.com:siddontang/ledisdb.git src/github.com/siddontang/ledisdb

cd src/github.com/siddontang/ledisdb

#構建leveldb。假設已經安裝了,可忽略
./build_leveldb.sh  

#安裝ledisdb go依賴
. ./bootstap.sh     

#配置GOPATH等環境變量
. ./dev.sh          

go install ./...

詳細的安裝說明,可以查看代碼文件夾如下的readme。

Example

使用ledisdb很是easy。僅僅需要執行:

./ledis-server -config=/etc/ledis.json

ledisdb的配置文件採用json格式。爲啥選用json。我在使用json做爲基本的配置格式裏面有過說明。

咱們可以使用不論什麼redisclient鏈接ledisdb,譬如redis-cli,例如如下:

127.0.0.1:6380> set a 1
OK
127.0.0.1:6380> get a
"1"
127.0.0.1:6380> incr a
(integer) 2
127.0.0.1:6380> mset b 2 c 3
OK
127.0.0.1:6380> mget a b c
1) "2"
2) "2"
3) "3"

leveldb

因爲leveldb是c++寫的,因此在go裏面需要使用,cgo是一種很是好的方式。

這裏,我直接使用了levigo這個庫。並在上面進行了封裝。詳見這裏。儘管有一個go-leveldb,無奈仍不能用。

cgo的性能開銷仍是有的,這點在我作benchmark的時候就明顯感受出來。只是興許優化的空間很是大。譬如將多個leveldb的調用邏輯該用c重寫。這樣僅僅需要一次cgo就可以了。只是這個興許在考慮。

leveldb的一些參數在構建編譯的時候是需要調整的,這點我沒啥經驗,僅僅能google和參考ssdb。

譬如如下這幾個:

+ db/dbformat.h

// static const int kL0_SlowdownWritesTrigger = 8;
static const int kL0_SlowdownWritesTrigger = 16;

// static const int kL0_StopWritesTrigger = 12;
static const int kL0_StopWritesTrigger = 64;

+ db/version_set.cc

//static const int kTargetFileSize = 2 * 1048576;
static const int kTargetFileSize = 32 * 1048576;

//static const int64_t kMaxGrandParentOverlapBytes = 10 * kTargetFileSize;
static const int64_t kMaxGrandParentOverlapBytes = 20 * kTargetFileSize;

相關參數的調優,僅僅能等我興許深刻研究leveldb了在好好考慮。

性能測試

不論什麼一個服務端服務沒有性能測試報告那就是耍流氓。我現在僅僅是簡單的用了redis_benchmark進行測試,測試環境爲一臺快兩年的老爺mac air機器。

測試語句:

redis-benchmark -n 10000 -t set,incr,get,lpush,lpop,lrange,mset -q

redis-benchmark默認沒有hash以及zset的測試。興許我在本身加入。

leveldb配置:

compression       = false
block_size        = 32KB
write_buffer_size = 64MB
cache_size        = 500MB

redis

SET: 42735.04 requests per second
GET: 45871.56 requests per second
INCR: 45248.87 requests per second
LPUSH: 45045.04 requests per second
LPOP: 43103.45 requests per second
LPUSH (needed to benchmark LRANGE): 44843.05 requests per second
LRANGE_100 (first 100 elements): 14727.54 requests per second
LRANGE_300 (first 300 elements): 6915.63 requests per second
LRANGE_500 (first 450 elements): 5042.86 requests per second
LRANGE_600 (first 600 elements): 3960.40 requests per second
MSET (10 keys): 33003.30 requests per second

ssdb

SET: 35971.22 requests per second
GET: 47393.37 requests per second
INCR: 36630.04 requests per second
LPUSH: 37174.72 requests per second
LPOP: 38167.94 requests per second
LPUSH (needed to benchmark LRANGE): 37593.98 requests per second
LRANGE_100 (first 100 elements): 905.55 requests per second
LRANGE_300 (first 300 elements): 327.78 requests per second
LRANGE_500 (first 450 elements): 222.36 requests per second
LRANGE_600 (first 600 elements): 165.30 requests per second
MSET (10 keys): 33112.59 requests per second

ledisdb

SET: 38759.69 requests per second
GET: 40160.64 requests per second
INCR: 36101.08 requests per second
LPUSH: 33003.30 requests per second
LPOP: 27624.31 requests per second
LPUSH (needed to benchmark LRANGE): 32894.74 requests per second
LRANGE_100 (first 100 elements): 7352.94 requests per second
LRANGE_300 (first 300 elements): 2867.79 requests per second
LRANGE_500 (first 450 elements): 1778.41 requests per second
LRANGE_600 (first 600 elements): 1590.33 requests per second
MSET (10 keys): 21881.84 requests per second

可以看到,ledisdb的性能趕redis以及ssdb仍是有差距的,但也不至於不可用。有些區別並不大。至於爲啥lrange比ssdb高,我比較困惑。

興許的測試報告,我會不斷在benchmark文件中面更新。

Todo。。

ledisdb仍是一個很是新的項目,比起ssdb已經在生產環境中用了很是久,還有很是多路要走,還有一些重要的功能需要實現,譬如replication等。

歡迎有興趣的童鞋一塊兒參與進來,在漫漫程序開發路上有一些好基友但是很是幸運的。

相關文章
相關標籤/搜索