SSDB是一个快速的用来存储十亿级别列表数据的开源 NoSQL 数据库。
特性
- 替代 Redis 数据库, Redis 的 100 倍容量
- LevelDB 网络支持, 使用 C/C++ 开发
- Redis API 兼容, 支持 Redis 客户端
- 适合存储集合数据, 如 list, hash, zset...
- 客户端 API 支持的语言包括: C++、PHP、Python、Cpy、Java、NodeJS、Ruby、Go。
- 持久化的队列服务
- 主从复制, 负载均衡
性能
1000请求:
writeseq : 0.546 ms/op 178.7 MB/s
writerand : 0.519 ms/op 188.1 MB/s
readseq : 0.304 ms/op 321.6 MB/s
readrand : 0.310 ms/op 315.0 MB/s
并发:
========== set ==========
qps: 44251, time: 0.226 s
========== get ==========
qps: 55541, time: 0.180 s
========== del ==========
qps: 46080, time: 0.217 s
========== hset ==========
qps: 42338, time: 0.236 s
========== hget ==========
qps: 55601, time: 0.180 s
========== hdel ==========
qps: 46529, time: 0.215 s
========== zset ==========
qps: 37381, time: 0.268 s
========== zget ==========
qps: 41455, time: 0.241 s
========== zdel ==========
qps: 38792, time: 0.258 s
在MacBook Pro 13 (Retina屏幕)上运行。
与redis的比较:
性能数据使用 ssdb-bench(SSDB) 和 redis-benchmark(Redis) 来获取。
架构
安装
下载压缩包,解压缩
wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zip
unzip master
cd ssdb-master
编译
make
安装(可选)
sudo make install
运行
./ssdb-server ssdb.conf
或者以后台的方式运行
./ssdb-server -d ssdb.conf
ssdb命令行
./tools/ssdb-cli -p 8888
停止ssdb-server
kill `cat ./var/ssdb.pid`
使用
PHP
<?php
include_once('SSDB.php');
try{
$ssdb = new SimpleSSDB('127.0.0.1', 8888);
}catch(Exception $e){
die(__LINE__ . ' ' . $e->getMessage());
}
$ret = $ssdb->set('key', 'value');
if($ret === false){
// error!
}
echo $ssdb->get('key');
Python
使用pyssdb
>>> import pyssdb
>>> c = pyssdb.Client()
>>> c.set('key', 'value')
1
>>> c.get('key')
'value'
>>> c.hset('hash', 'item', 'value')
1
>>> c.hget('hash', 'item')
'value'
>>> c.hget('hash', 'not exist') is None
True
>>> c.incr('counter')
1
>>> c.incr('counter')
2
>>> c.incr('counter')
3
>>> c.keys('a', 'z', 1)
['counter']
>>> c.keys('a', 'z', 10)
['counter', 'key']
Ruby
使用ssdb-rb
require "ssdb"
ssdb = SSDB.new url: "ssdb://1.2.3.4:8889"
ssdb.set("mykey", "hello world")
# => true
ssdb.get("mykey")
# => "hello world"
ssdb.batch do
ssdb.set "foo", "5"
ssdb.get "foo"
ssdb.incr "foo"
end
# => [true, "5", 6]
Go
package main
import (
"fmt"
"os"
"./ssdb"
)
func main(){
ip := "127.0.0.1";
port := 8888;
db, err := ssdb.Connect(ip, port);
if(err != nil){
os.Exit(1);
}
var val interface{};
db.Set("a", "xxx");
val, err = db.Get("a");
fmt.Printf("%s\n", val);
db.Del("a");
val, err = db.Get("a");
fmt.Printf("%s\n", val);
db.Do("zset", "z", "a", 3);
db.Do("multi_zset", "z", "b", -2, "c", 5, "d", 3);
resp, err := db.Do("zrange", "z", 0, 10);
if err != nil{
os.Exit(1);
}
if len(resp) % 2 != 1{
fmt.Printf("bad response");
os.Exit(1);
}
fmt.Printf("Status: %s\n", resp[0]);
for i:=1; i<len(resp); i+=2{
fmt.Printf(" %s : %3s\n", resp[i], resp[i+1]);
}
return;
ngx_lua
使用lua-resty-ssdb
lua_package_path "/path/to/lua-resty-ssdb/lib/?.lua;;";
server {
location /test {
content_by_lua '
local ssdb = require "resty.ssdb"
local db = ssdb:new()
db:set_timeout(1000) -- 1 sec
local ok, err = db:connect("127.0.0.1", 8888)
if not ok then
ngx.say("failed to connect: ", err)
return
end
ok, err = db:set("dog", "an animal")
if not ok then
ngx.say("failed to set dog: ", err)
return
end
ngx.say("set result: ", ok)
local res, err = db:get("dog")
if not res then
ngx.say("failed to get dog: ", err)
return
end
if res == ngx.null then
ngx.say("dog not found.")
return
end
ngx.say("dog: ", res)
db:init_pipeline()
db:set("cat", "Marry")
db:set("horse", "Bob")
db:get("cat")
db:get("horse")
local results, err = db:commit_pipeline()
if not results then
ngx.say("failed to commit the pipelined requests: ", err)
return
end
for i, res in ipairs(results) do
if type(res) == "table" then
if not res[1] then
ngx.say("failed to run command ", i, ": ", res[2])
else
-- process the table value
end
else
-- process the scalar value
end
end
-- put it into the connection pool of size 100,
-- with 0 idle timeout
local ok, err = db:set_keepalive(0, 100)
if not ok then
ngx.say("failed to set keepalive: ", err)
return
end
-- or just close the connection right away:
-- local ok, err = db:close()
-- if not ok then
-- ngx.say("failed to close: ", err)
-- return
-- end
';
}
}
C++
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include "SSDB.h"
int main(int argc, char **argv){
const char *ip = (argc >= 2)? argv[1] : "127.0.0.1";
int port = (argc >= 3)? atoi(argv[2]) : 8888;
ssdb::Client *client = ssdb::Client::connect(ip, port);
if(client == NULL){
printf("fail to connect to server!\n");
return 0;
}
ssdb::Status s;
s = client->set("k", "hello ssdb!");
if(s.ok()){
printf("k = hello ssdb!\n");
}else{
printf("error!\n");
}
delete client;
return 0;