一个参考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等。

欢迎有兴趣的童鞋一块儿參与进来,在漫漫程序开发路上有一些好基友但是很是幸运的。

相关文章
相关标签/搜索