MegaHash - 一个高性能nodejs缓存技术

本文笔者想要来分享和介绍一个高性能的内存键值缓存系统和技术-MegaHash。笔者已经将其应用在一个对性能非常敏感的信息查询系统当中,并取得了比较好的效果。

关于MegaHash

MegaHash(MH)没有正式的官网,使用github进行相关技术和产品的发布和服务。

github.com/jhuckaby/me...

根据其产品描述,MegaHash是一个超快速的键-值哈希表,使用C++编写,并被封装为Nodejs模块和API,方便nodejs应用程序的集成和使用。它的主要特性包括:

  • 高性能读、写、删除和键迭代操作
  • 性能稳定并且可预测
  • 低内存消耗
  • 所有的数据存储都在V8堆之外
  • 支持Buffer、字符串、数字、布尔和对象等多种类型
  • 测试过高达100万的键值
  • 兼容基本的ES6 Map API

可以看到,MH的一个核心特点是其性能,因为它针对的是普通nodejs应用的一个比较忽视的方面,就是对于大型数据集的内存管理。普通的nodejs程序工作时的内存基本上都局限在V8内存堆中,也使用V8和相关的内存机制,但当数据规模超过限制时,会出现灵活性不足的问题。MH自行实现了相关的内存和数据管理机制,不会占用应用程序的堆内存,从而提高了额外的性能、灵活性和健壮性。

其他一些技术细节和限制包括:

  • 安装过程需要GCC编译器
  • MH使用"Separate Chaining(独立链接)"技术管理键和存储
  • MH使用32位DJB2算法对键进行摘要,并使用特别得方式建立索引,从而能够在速度和内存开销之间取得平衡
  • MH的值,实际上都会被序列化,并在写入和读取时自动处理
  • 键的长度限制为65K字节,不能为空(实际上使用buffer),数量没有明确限制
  • MH值得限制为2GB

性能

关于性能,这里有一个简单的测试案例,可以帮助读者初步理解Megahash系统能够提供的应用性能。这个测试(图)的设置和结果要点包括:

  • 平台: AWS EC2 c5a.16xlarge VM
  • 配置: 64核/128GB内存/20Gbps网络
  • 数据: 10亿个key,简单数据
  • 性能(平均): 写535261/秒,读961851/秒
  • 内存: 总占用约34GB,其中Megahash的开销约为27GB

这样的配置,放到现在,就是一台普通的工业服务器的配置水平,但能够支持数百K/S级别的数据读写操作,完全可以满足一般规模的企业级业务系统的使用了。另外,从测试的图中可以看到,在一定的范围内,其读写性能基本上不受数据规模的影响,这对于应用的稳定性是非常重要的。

应用

MH的开发和集成也是非常简单,和一般的npm应用差异不大。一般的步骤和操作如下。

安装npm

当然作为一个外部软件,需要先进行安装,可以使用npm:

npm install megahash

引用和实例化

然后,在使用之前,需要先引用和实例化:

const MegaHash = require('megahash');

let hashTable = new MegaHash();

实例化之后,实际上就在系统中建立起了一个内存键值存储表,可以进行相关的数据操作了。

一般操作

作为一个键值数据库,一般的操作包括增加(设置)、读取、存在检查、删除和清除,其参考操作代码如下:

js 复制代码
// 增加和设置
hash.set( "hello", "there" );

// 读取和查询,如果没有,结果为 undefined
let hvalue =   hash.get("hello");

// 存在检查
let isexist =  hash.has("hello");

// 删除键
hash.delete("hello");

// 清除数据
hash.clear();

数据类型

MH的key使用的就是普通的字符串,它的值支持更大的数据类型,包括普通的字符串、js对象、buffer、number、boolean和null等等。

遍历

除了可以直接使用键进行访问之外,还可以使用遍历的方式来访问MH实例:

js 复制代码
let key = hash.nextKey();
while (key) {
   // do something with key
   key = hash.nextKey(key);
}

状态

MH提供了存储状态检查的功能,可以检查如键的数量、数据大小、索引大小等统计和状态信息,使用方法如下:

js 复制代码
// hash表的大小
let length = hash.length();

// 统计信息
let stats = hash.stats();
console.log(stats);

Example stats:
{
	"numKeys": 10000,
	"dataSize": 217780,
	"indexSize": 87992,
	"metaSize": 300000,
	"numIndexes": 647
}

错误处理

MH并没有提供太复杂的错误处理机制,因为最常见能够遇到的问题就是资源限制无法操作了,如下列代码:

js 复制代码
    let result = hash.set( "hello", "there" );
    if (!result) {
            throw new Error("Failed to write to MegaHash: Out of memory");
    }

注意事项

首先,MH是一些特殊的目标和场景设计的,它是一个内存数据系统,它没有持久化的功能,如果考虑到意外宕机的恢复,可能需要自己实现相关的持久化的机制。

另外,和Redis不同,它也没有相关的网络访问方式和额外的数据类型,不能提供更为复杂的业务支撑功能,或者需要开发者进行额外的开发。MH提供的接口和功能比较简单,只能够和应该作为应用系统内部的一个程序模块来使用,而不是一个独立的子系统,当然如果业务的抽象层级足够的化,我们也可以将其封装成通用的模块来使用。

还有,就是其安装过程现在还不是特别方便,因为涉及C++原生程序,需要进行现场的编译,对Windows的支持也可能存在问题。

所以,MH这个技术是一种比较特别的技术,适用于一些特别的应用场景。比如对性能和并发要求比较高的,相对静态的数据和信息查询系统。

小结

本文探讨和分享了一个内存哈希表存储技术-Megahash,了解了其技术实现和特点,以及应用的方式和场合。

相关推荐
哎呦没23 分钟前
SpringBoot框架下的资产管理自动化
java·spring boot·后端
2401_8576009526 分钟前
SpringBoot框架的企业资产管理自动化
spring boot·后端·自动化
程序员爱技术1 小时前
Vue 2 + JavaScript + vue-count-to 集成案例
前端·javascript·vue.js
悦涵仙子2 小时前
CSS中的变量应用——:root,Sass变量,JavaScript中使用Sass变量
javascript·css·sass
兔老大的胡萝卜2 小时前
ppk谈JavaScript,悟透JavaScript,精通CSS高级Web,JavaScript DOM编程艺术,高性能JavaScript pdf
前端·javascript
NiNg_1_2344 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk6 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*6 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue6 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man6 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang