我们的企业网盘OnceDoc和管理软件采用内存数据库 Redis 。 Redis 是一个使用 C 语言编写的键值对存储数据库,体积小巧,性能优异,实施简单。很多大并发网站如 Twitter 、 GitHub Weibo 、 Snapchat 、 Flickr 、阿里等都将其用作 SESSION 存储及缓存的管理。出于性能的考虑 Redis 自带的命令一般不支持按值查找。但是企业软件又需要数据库有搜索、复杂条件查询以及聚合分析的能力。为了实现这些功能我们修改了 Redis 的源码。并创建了一个新的开源分支 OnceDB,用户可以到 Github 下载最新的Windows 版本进行测试。
注* 我们为部分客户部署了一些 Linux 实例,到目前为止运行稳定, Windows 版本并没有在生产环境测试过。
我们基于 Redis3.x 版本进行修改,尽管最新的 4.x 添加了外部模块的支持,但并不适合我们的应用场景,外部模块会增加 Reids 的使用风险,并且会增加修改的难度。 Redis 从 3.x 版本开始支持集群 Cluster ,足以满足我们的需要。
我们基于 [email protected] 版本做了一个新的 node.js 驱动 oncedb-client。
使用 npm 安装 oncedb-client 驱动模块
npm install oncedb-client
通过 require 安装 oncedb-client 模块,并创建 client ,此时会默认连接本地 6379 端口的 redis ,然后就可以用他在 nodejs 中进行查询了。
var client = require("oncedb-client").createClient();
string 是 redis 最基本的类型,而且 string 类型是二进制安全的。即 string 可以包含任何数据。比如 jpg 图片或者序列化的 JSON 对象。下例在 text* 类型的 key 中查找值为'Kris'的数据
var client = require("oncedb-client").createClient();
client.search('text*', '=', 'Kris', function(err, objs) {
console.log(objs)
})
输出结果为数组,第一条为健第二条记录为值
> [ 'text1', 'Kris' ]
搜索含有 Kris 的记录
client.search('text*', '~', 'Kris', function(err, objs) {
console.log(objs)
})
输出结果为两组健值
> [ 'text1', 'Kris', 'text5', 'This is ok, Kris' ]
Redis hash 是一个 string 类型的 field 和 value 的映射表。一个 hash 类型的 key 含多个 field ,一个 field 对应一个 value 。 Hash 非常适合存放 JSON 对象。 hsearch 支持对 field 进行查询。
比如查询一条 userInfo 记录,其中 {'>':'100'} ,也可使用类 mongodb 语法:{'$gt':'100'}:
client.hsearch('userInfo:*', {
'name' : 'Mar'
, 'gender' : 'male'
, 'nVisit' : {'>':'100'}
}, function(err, objs) {
console.log(objs)
})
查找结果
> [ { _key: 'userInfo:1006',
name: 'Mar',
gender: 'male',
nVisit: '10000' } ]
[文档不断完善中]
原文地址:OnceDoc Blog
client.hselect(
['name', 'email', 'isPublic', 'nVisit']
, ['userInfo:100', 'userInfo:103', 'userInfo:1005', 'userInfo:1006']
, function(err, objs) {
console.log(objs)
})
输出结果
> [ { _key: 'userInfo:100',
name: 'shanghai',
email: null,
isPublic: null,
nVisit: null },
{ _key: 'userInfo:103',
name: 'newghost',
email: null,
isPublic: null,
nVisit: null },
{ _key: 'userInfo:1005',
name: 'Mars2',
email: null,
isPublic: '0',
nVisit: '10000' },
{ _key: 'userInfo:1006',
name: 'Mar',
email: null,
isPublic: '1',
nVisit: '10000' } ]
client.hmgetall(['userInfo:100', 'userInfo:1003', 'userInfo:100'], function(err, objs) {
console.log(objs)
})
输出结果
> [ { _key: 'userInfo:100',
id: '100',
name: 'shanghai',
gender: 'female',
poster: '龙' },
{ _key: 'userInfo:1003',
name: 'Telyer',
id: '1003',
gender: 'male',
active: '0',
joinTime: '1484445746020',
poster: '王五',
isPublic: '0',
nVisit: '300' },
{ _key: 'userInfo:100',
id: '100',
name: 'shanghai',
gender: 'female',
poster: '龙' } ]
[文档不断完善中]
1
alwayshere 2017-01-16 16:12:33 +08:00 2
貌似挺不错的样子,楼主是否考虑过用 ssdb 来替换 redis , http://ssdb.io ,协议和 redis 几乎一样
|
2
lan894734188 2017-01-16 16:13:26 +08:00 via Android
支持
|
3
newghost OP |
4
newghost OP |
5
enenaaa 2017-01-16 16:27:02 +08:00
问一下楼主, windows 版本,将程序窗口最小化后,大部分内存会被换入硬盘虚拟内存,导致检索卡顿。 你们是怎么解决的。 做成后台服务么。
|
7
misaka19000 2017-01-16 16:43:19 +08:00
感觉很不错,支持~
|
9
alwayshere 2017-01-16 20:19:32 +08:00
@newghost 希望能开发出 ssdb 版的,谢谢大神啦
|
10
newghost OP @alwayshere
不是大神,这个项目也是几个人和力搞的。不过也确实发现了 redis 有些设计不合理的地方,比如说 keys 的性能非常差,有机会学习一下 ssdb 的代码 @yanzixuan 我们生产环境用的都是 Linux ,不过本地测试都是在 Windows 下进行的,毕竟 Windows 占了 80%的市场份额。 |
11
laiwei 2017-01-16 23:18:45 +08:00 via Android
有没有相关的 benchmark 数据哈
|
13
wyntergreg 2017-01-17 08:55:00 +08:00
已 star
|
14
kofj 2017-01-17 10:27:53 +08:00
首先,赞一下,很不错的想法。但是,简单看了一下你们的代码后,发现用的是最基本的“顺序扫描法”执行搜索的,并没有看见有建立索引的部分,所以觉得说“支持全文搜索”欠妥。
https://github.com/OnceDoc/OnceDB/blob/master/src/t_string.c#L479-L555 |
15
newghost OP @kofj
嗯, redis 的 key 搜索目前只支持这样,它内部并没有实现一个 key 的有序列表。它里面是按 key 的 hash 值排序的,可能是因为 hash 值的分布比较均匀,在做集群时更容易做到负载均衡。 我们以后可能会在 redis 里面或驱动层增加一个关于 key 的有序列表,这样会极大提高它的搜索性能。 @wyntergreg 感谢 |
16
zonghua 2017-03-03 01:10:40 +08:00 via iPhone
python 有个 redisco 包实现了 redis 存储的 model ,内部实现好像是用 redis 的 zset
|
17
jingling0101 2017-03-15 10:10:12 +08:00
支持中文 吗
|