发布时间:2025-12-10 19:14:31 浏览次数:5
ssdb介绍_ssd结构ssdb介绍ssdb是一款类似于redis的nosql数据库,不过redis是基于内存的,服务器比较昂贵,ssdb则是基于硬盘存储的,很容易扩展,对于一些对速度要求不是太高的应用,还是不错的选择。SSDB是一套基于LevelDB存储引擎的非关系型数据库(NOSQL),可用于取代Redis,更适合海量数据的存储。另外,rocksdb是FB在LevelDB的二次开发版本,因此也存在使用Ro…_ssdb
ssdb是一款类似于redis的nosql数据库,不过redis是基于内存的,服务器比较昂贵,ssdb则是基于硬盘存储的,很容易扩展,对于一些对速度要求不是太高的应用,还是不错的选择。
SSDB是一套基于LevelDB存储引擎的非关系型数据库(NOSQL),可用于取代Redis,更适合海量数据的存储。
另外,rocksdb是FB在LevelDB的二次开发版本,因此也存在使用RocksDB作为存储引擎的SSDB版本,可以参考这里。
先记录一个比较坑的东西,具体的用法以后补充。
ssdb删除数据的时候有很多中方法:
flushdb 删除整个数据库中的所有数据
qclear 删除列表类型的数据
hclear 删除hash类型的数据
zclear 删除有序集合类型的梳理
del 删除字符串类型的数据
不过,ssdb在删除数据的时候并不会立刻释放磁盘的空间,用作者的话说就是ssdb会在合适的时候去释放,这就会造成不知不觉中ssdb占用的磁盘空间越来越大,还不知道什么时候才会被释放,如果不及时处理的话,服务器卡死是很正常的事情,经过不断的寻找,终于被我发现了一个命令 compact , 这个命令会自动去释放应该被释放的磁盘空间,不过在使用的时候会造成ssdb卡慢,并且 compact 命令的执行速度也不快,但总算是可以立刻释放了,不用再担心服务器被撑爆。
需要注意的是如果服务器已经快被撑爆了,那么你在执行 compact 的时候ssdb是有可能崩溃的,而且执行一次 compact 并不会释放所有应该释放的空间,可能需要多次执行才行。
还有一个比较坑的东西就是在删除数据的时候,会造成服务阻塞,其他任何写命令都执行不了,可读不可写。。。而且删除的超级慢。。。
编译和安装
wget --no-check-certificate https://github.com/ideawu/ssdb/archive/master.zipunzip mastercd ssdb-mastermake# 将安装在 /usr/local/ssdb 目录下sudo make install希望我今天分享的这篇文章可以帮到您。
启动服务
# 启动主库./ssdb-server ssdb.conf# 或者启动为后台进程./ssdb-server -d ssdb.conf# 启动 ssdb 命令行客户端./tools/ssdb-cli -p 8888# 停止 ssdb-server./ssdb-server ssdb.conf -s stop# 对于旧版本kill `cat ./var/ssdb.pid`配置文件
ssdb.conf:
work_dir = ./varpidfile = ./var/ssdb.pidserver: ip: 127.0.0.1 port: 8888 # bind to public ip #ip: 0.0.0.0 # format: allow|deny: all|ip_prefix # multiple allows or denys is supported #deny: all #allow: 127.0.0.1 #allow: 192.168 # auth password must be at least 32 characters #auth: very-strong-passwordreplication: binlog: yes # Limit sync speed to *MB/s, -1: no limit sync_speed: -1 slaveof: # to identify a master even if it moved(ip, port changed) # if set to empty or not defined, ip:port will be used. #id: svc_2 # sync|mirror, default is sync #type: sync #ip: 127.0.0.1 #port: 8889logger: level: debug # 支持的日志级别有:debug, warn, error, fatal. output: log.txt rotate: size: 1000000000leveldb: # in MB cache_size: 500 # in KB block_size: 32 # in MB write_buffer_size: 64 # in MB compaction_speed: 1000 # yes|no compression: yes 一个 ssdb-server 实例占用的内存瞬时(有可能, 而且即使达到, 也只是持续短时间)最高达到(MB):
cache_size + write_buffer_size * 66 + 32这是对于压缩选项没有开启的情况, 如果 compression: yes, 计算公式是:
cache_size + 10 * write_buffer_size * 66 + 32你可以调整配置参数, 限制 ssdb-server 的内存占用.
与Redis类似,SSDB也支持多种数据结构(KV list, hash, soreted set),下面列出了常用命令:
dbsize #返回数据库占用空间,以字节为单位
flushdb #清空数据库
info # 返回服务器信息
auth password # 验证访问密码
set key value
setx key value ttl # 设置key的同时设置ttl
setnx key value # 若key已存在,则不设置
multi_set key1 value1 key2 value2 …
exists key
get key
getset key value # 更新key,并返回旧value
multi_get key1 key2 …
keys key_start key_end limit #返回指定范围内的key,左开右闭区间(SSDB的key有序存储)
rkeys key_start key_end limit
scan key_start key_end limit
rscan key_start key_end limit
expire key ttl
ttl key
del key
multi_del key1 key2 …
substr key start size # 返回子串
strlen key
incr key [num]
getbit key offset
setbit key offset val
bitcount key [start] [end]
countbit key start size
hset name key value
multi_hset name key1 value1 key2 value2 …
hget name key
multi_hget name key1 key2 …
hgetall name
hkeys name key_start key_end
hscan key_start key_end limit
hrscan key_start key_end limit
hdel name key # 删除一个字段
hclear name # 删除所有字符
multi_hdel name key1 key2 …
hexists name key
hsize name
hincr name key [num]
hlist name_start name_end limit # 列出指定范围的所有hash表
hrlist name_start name_end limit
qpush_front name item1 item2 … # 往队头插入新元素
qpush_back name item1 item2 … # 往队尾插入新元素
qpop_front name size # 从队头弹出若干个元素
qpop_back name size # 从队尾弹出若干个元素
qtrim_front name size # 从队头移除多个元素
qtrim_back name size # 从队尾移除多个元素
qfront name # 返回队头
qback name # 返回队尾
qsize name # 返回队长
qget name index # 返回指定位置元素
qset name index val
qrange name offset limit # 返回一个切片
qslice name begine end # 返回一个切片
qclear name
qlist name_start name_end limit
qrlist name_start name_end limit
zset name key socre
zget name key
zdel name key
zexists name key
zsize name
zincr name key num
SSDB才有LSM模型,也就是说它的key是有序存储的,因此,我们可以导出所有key的数据,也可以导出指定范围内key的数据。
1、使用ssdb-cli 命令行客户端
导出整个数据库:
# backup current database into file backup.ssdbssdb 127.0.0.1:8888> export backup.ssdb按照 Key 区间导出数据库(交互模式)
ssdb 127.0.0.1:8888> export -i backup.ssdbinput KV range[start, end]: start(inclusive, default none): a end(inclusive, default none): zinput HASH range: start(inclusive, default none): end(inclusive, default none):input ZSET range: start(inclusive, default none): end(inclusive, default none):input QUEUE range: start(inclusive, default none): end(inclusive, default none):命令 export -i backup.ssdb 将导出区间 [a, z] 内的 KV, 所有的 HASH, ZSET, QUEUE.
导入命令:
# import backup.ssdb into current databasessdb 127.0.0.1:8888> import backup.ssdbimport 命令会把数据库中的相同 key 给替换。
2、SSDB 另一个专门用于导出工具是 ssdb-dump,用法如下:
./tools/ssdb-dump ip port output_folder目录 output_folder 必须不存在, 因为 ssdb-dump 会创建这个目录. 导出之后, 这个目录里将有两个子目录, data 目录里包含着数据, 还有一个空的 meta 目录.
如果想从导出的目录恢复数据,可以将 output_folder 目录拷贝到你的服务器上面,然后修改你的 ssdb.conf 配置文件, 将 work_dir 指向 output_folder 目录, 然后重启 ssdb-server。
最大 Key 长度 200 字节
最大 Value 长度 31MB
最大请求或响应长度 31MB
单个 HASH 中的元素数量 9,223,372,036,854,775,807
单个 ZSET 中的元素数量 9,223,372,036,854,775,807
单个 QUEUE 中的元素数量 9,223,372,036,854,775,807
命令最多参数个数 所有参数加起来体积不超过 31MB 大小
Redis的主从复制在主库挂了的时候就无法再写入数据了,而SSDB不但支持主-从结构,还支持多主结构。
#server1:
replication: slaveof:#server2:
replication: slaveof: id: svc_1 # sync|mirror, default is sync type: sync ip: 127.0.0.1 port: 8888#server1:
replication: slaveof: id: svc_2 # sync|mirror, default is sync type: mirror ip: 127.0.0.1 port: 8889#server2:
replication: slaveof: id: svc_1 # sync|mirror, default is sync type: mirror ip: 127.0.0.1 port: 8888在一组一共包含 n 个实例的 SSDB 实例群中, 每一个实例必须 slaveof 其余的 n-1 个实例.
replication: slaveof: id: svc_1 # sync|mirror, default is sync type: mirror ip: 127.0.0.1 port: 8888 slaveof: id: svc_2 # sync|mirror, default is sync type: mirror ip: 127.0.0.1 port: 8889 # ... more slaveofinfo命令可以返回SSDB服务状态:
ssdb 127.0.0.1:8899> infobinlogs capacity : 10000000 min_seq : 1 max_seq : 74replication client 127.0.0.1:55479 type : sync status : SYNC last_seq : 73replication slaveof 127.0.0.1:8888 id : svc_2 type : sync status : SYNC last_seq : 73 copy_count : 0 sync_count : 44binlogs,当前实例的写操作状态:
capacity: binlog 队列的最大长度min_seq: 当前队列中的最小 binlog 序号max_seq: 当前队列中的最大 binlog 序号replication,可以有多条 replication 记录. 每一条表示一个连接进来的 slave(client), 或者一个当前服务器所连接的 master(slaveof).
slaveof|client ip:port, 远端 master/slave 的 ip:porttype: 类型, sync|mirrorstatus: 当前同步状态, DISCONNECTED|INIT|OUT_OF_SYNC|COPY|SYNC,见下面的解释last_seq: 上一条发送或者收到的 binlog 的序号slaveof.id: master 的 id(这是从 slave’s 角度来看的, 你永远不需要在 master 上配置它自己的 id)slaveof.copy_count: 在全量同步时, 已经复制的 key 的数量slaveof.sync_count: 发送或者收到的 binlog 的数量.关于 status:
DISCONNECTED: 与 master 断开了连接, 一般是网络中断INIT: 初始化状态OUT_OF_SYNC: 由于短时间内在 master 有大量写操作, 导致 binlog 队列淘汰, slave 丢失同步点, 只好重新复制全部的数据COPY: 正在复制基准数据的过程中, 新的写操作可能无法及时地同步SYNC: 同步状态是健康的判断同步状态
binlogs.max_seq 是指当前实例上的最新一次的写(写/更新/删除)操作的序号;
replication.client.last_seq 是指已发送给 slave 的最新一条 binlog 的序号;
所以, 如果你想判断主从同步是否已经同步到位(实时更新), 那么就判断 binlogs.max_seq 和 replication.client.last_seq 是否相等。
SSDB协议与Redis的文本协议也类似:
SSDB数据包的结构:
Packet := Block+ '\n'Block := Size '\n' Data '\n'Size := literal_integerData := size_bytes_of_data请求:
Request := Cmd Blocks*Cmd := Block请求命令包括: get, set, del, …
响应:
Response := Status Block*Status := Block响应状态码包括: ok, not_found, error, fail, client_error
示例:
用 telnet 或者 nc 命令连接到 SSDB 服务器, 然后输入下面的代码(用最后一行空行结束):
3get3key你将看到类似这样的响应:
2ok3valSSDB 协议解析器的C实现:
#include <stdlib.h>#include <string.h>int len = buffer->size();char *ptr = buffer->data();while(len > 0){ char *data = (char *)memchr(ptr, '\n', len); if(data == NULL){ break; } data += 1; int num = data - ptr; if(num == 1 || (num == 2 && ptr[0] == '\r')){ // Packet received. return OK; } // Size received int size = (int)strtol(ptr, NULL, 10); len -= num + size; ptr += num + size; if(len >= 1 && ptr[0] = '\n'){ len -= 1; ptr += 1; }else if(len >= 2 && ptr[0] == '\r' && ptr[1] == '\n'){ len -= 2; ptr += 2; }else{ break; } // Data received}