需要一个支持查询功能的内存key-value存储,Nodejs有没有什么好推荐的?
需要一个支持查询功能的内存key-value存储,Nodejs有没有什么好推荐的?
需求比较独特,就是要一个内存版的mongodb: 1、这个hash的key是有时序的,value是JSON格式的数据 2、JSON的读取支持类似mongodb的projection,只返回指定的数据 3、JSON的更新可以指定字段,类似mongodb的update 4、应该支持丰富的查询,包括按regexp查询一个或多个特定的key,或者查询特定字段是否存在,等等 5、API应该是异步的(对于大量数据来说,同步会卡住js进程) 6、占用内存只受配置或硬件限制,应该可以突破2G内存的局限。V8的BUG导致js对象占用空间无法突破2G,不论是不是64位系统。因此这个k-v必然是C++ Addon的实现。 7、不需要实现持久化功能,但是有持久化的event机制,用户可以自己接管事件,自己按需要做磁盘存储。 8、最好支持embedded模式运行。也就是以npm模块的方式在node内部运行,避免进程间通讯的序列化开销。因为频繁处理大批数据时,序列化的成本非常高。
我自己在断断续续做一个这样的东西,但是完成度还很低。大致上,就是用C++的map做保存,做了js的读写接口包装。查询上重点考虑了regexp的优化,测试之后选了速度最快的grep里的dfasearch模块,异步用的就是uv的工作队列。但是不知道怎么搞的,很多地方执行效率很低。。。如果不考虑这货能多线程的话,很多地方甚至不如纯js的速度。理想和现实相差太多。对v8的秉性不熟悉,对C++的优化毫无头绪。而且这货就算写成了也没法发出来了,直接把MIT GPL一堆柔和在一起,貌似法律上也违和了。如果有个现成的。。。真不想写下去了。
p.s. 请不要推荐类似 nedb 这样的纯 js 实现的库,这种库遇到大量数据的时候 node 进程就崩溃了,是 v8 陈年老 BUG 导致的。再说纯 js 实现的计算,量一大就会卡住js线程的,不可取。
针对您的需求,我推荐使用 LevelDB
或 RocksDB
结合 LevelUP
或 RocksUP
来实现一个支持查询功能的内存 key-value 存储。虽然这些存储引擎本身是基于文件系统的,但它们可以通过配置来主要利用内存,从而满足您的需求。以下是一个简单的示例,展示如何使用 LevelUP
和 LevelDOWN
(LevelDB 的 Node.js 封装)来实现您的需求。
首先,确保安装必要的依赖包:
npm install level levelup leveldown
接下来,创建一个简单的数据库操作示例:
const level = require('level');
const levelup = require('levelup');
// 创建一个新的LevelDB实例,使用内存模式
const db = levelup(level('./mydb', { valueEncoding: 'json' }));
// 示例数据插入
async function insertData() {
await db.put('key1', { timestamp: Date.now(), data: 'some data' });
await db.put('key2', { timestamp: Date.now(), data: 'other data' });
}
// 查询数据,支持projection
async function queryData() {
const iterator = db.iterator({ gte: 'key1', lte: 'key2' });
for await (const [key, value] of iterator) {
console.log(`Key: ${key}, Data: ${value.data}`); // projection 只返回 data 字段
}
}
// 更新数据,只更新指定字段
async function updateData() {
const key = 'key1';
const newValue = { $set: { data: 'updated data' } };
const currentData = await db.get(key);
const updatedData = { ...currentData, ...newValue.$set };
await db.put(key, updatedData);
}
// 使用正则表达式查询特定键
async function regexQuery() {
const iterator = db.iterator({ gte: 'key', lte: 'key\x7F' });
for await (const [key, value] of iterator) {
if (key.match(/key\d/)) {
console.log(`Matched Key: ${key}`);
}
}
}
// 运行示例
(async () => {
await insertData();
await queryData();
await updateData();
await regexQuery();
})();
此示例展示了如何插入、查询、更新数据以及通过正则表达式进行查询。请注意,LevelDB
和 RocksDB
都是持久化的存储解决方案,但在配置为内存模式下,它们可以提供高性能的内存存储。此外,您可以根据需要调整配置,以更好地适应内存使用情况。
如果需要更高级的查询功能,可以考虑结合其他技术如 Elasticsearch
或 Redis
,但这些通常需要更多的配置和资源管理。希望这个示例能满足您的基本需求!
没听说过这样的内存数据库…
坐等大神…
memcached 这个应该可以满足吧,我感觉
占用内存只受配置或硬件限制,应该可以突破2G内存的局限。V8的BUG导致js对象占用空间无法突破2G,不论是不是64位系统。因此这个k-v必然是C++ Addon的实现。
nodejs 的 Buffer 是 V8 以外的内存,不受 2G 限制。所以不是非得用 C++ addon
有特殊的需求,很难直接在现有的系统里找到。有没有考虑在现有的系统基础上开发,比如 redis 是开源的。
自己回自己吧。我最後用 shm 解決了。數據都保存在 /run/shm 的json文件中。這樣,對數據的訪問就變成了對內存文件的訪問。拆分大的數據,放在多個json文件中,減少序列化成本。仿mongodb寫了個查詢和更新的接口。測試結果,多個node併發訪問的速度果然比redis快,解決了之前用redis會卡的問題。
mysql 内存表不行吗,用memory引擎
针对你的需求,可以考虑使用 nedb-pure
的增强版本 lowdb
或者 LevelDB
的封装 level
,但这些方案可能不完全满足所有需求,尤其是关于复杂查询的支持。
这里推荐一个能满足部分需求的库——nanomongo
。虽然它不是专门为内存设计的,但它提供了类似 MongoDB 的 API,并且可以很好地集成到 Node.js 应用中。以下是一个简单的示例代码:
const NanoMongo = require('nanomongo');
const nanoMongo = new NanoMongo();
(async () => {
// 初始化数据库
await nanoMongo.init(':memory:');
// 插入数据
await nanoMongo.db.insert({ name: 'John Doe', age: 30, city: 'New York' });
await nanoMongo.db.insert({ name: 'Jane Doe', age: 25, city: 'San Francisco' });
// 查询数据
const result = await nanoMongo.db.find({ age: { $gt: 25 } });
console.log(result);
// 更新数据
await nanoMongo.db.update({ name: 'John Doe' }, { $set: { city: 'Los Angeles' } });
// 删除数据
await nanoMongo.db.remove({ name: 'Jane Doe' });
// 关闭数据库连接
await nanoMongo.close();
})();
这段代码演示了如何初始化数据库、插入数据、查询数据、更新数据和删除数据。nanomongo
提供了一些基本的查询能力,如条件查询和更新操作,但复杂的查询(如正则表达式)可能需要自行实现。
如果你需要更强大的查询能力和更好的性能,可能需要自己开发一个基于 C++ 的插件,或者寻找其他成熟的解决方案。