我们使用Redis已经有很长时间了,直到我们得出结论,迁移到KeyDB可能是它的特性的一个不错的选择。
环境
OS: Centos 7
NodeJs: v12.18.0
Redis: v6.0.5
Targeted KeyDB: v0.0.0 (git:1069d0b4) // keydb-cli -v showed this. Installed Using Docker.
ioredis: v4.17.3
pm2: v4.2.1 // used for clustering my application. 背景
参考KeyDB文档,KeyDB与Redis的最新版本兼容。
KeyDB仍然与Redis模块、API和协议完全兼容。因此,从Redis迁移到KeyDB非常简单,并且类似于在Redis到Redis场景中所期望的迁移。https://docs.keydb.dev/docs/migration/
在同一页中,它们提供了与KeyDB兼容的redis客户端列表。清单上有我正在使用的ioredis
KeyDB与所有Redis客户端兼容,如列出的这里,因此这不应引起关注。只需像使用Redis那样使用您的客户即可。https://docs.keydb.dev/docs/migration/
问题
就像文件里说的。我应该能够在几个小时内轻松地迁移到KeyDB。但事实并非如此!至少对我来说不是!我在网上搜索了最后3天的解决方案。我得出的结论是,我应该写信给stackoverflow :)
这个问题有点有趣。客户端实际上正在使用KeyDb,并且进程实际上正在设置和检索键(不确定,但可能在错误期间丢失一些数据)。但在10%的时间里,它给了我以下错误,并在一段时间后继续工作。由于我使用Redis在我的生产环境中存储会话和其他东西,我不能冒险忽略这样的坚持错误。
error: message=write EPIPE, stack=Error: write EPIPE
./app-error-1.log:37: at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:92:16), errno=EPIPE, code=EPIPE, syscall=write我在几乎所有的互联网上搜索了这个错误,但是没有人给出解决方案,也没有人给出错误的解释。
幸运的是,进程“有时”显示错误的堆栈。它指向ioredis代码中的lib/redis/index.ts:711。我不知道它能做什么。
(stream || this.stream).write(command.toWritable());https://github.com/luin/ioredis/blob/master/lib/redis/index.ts#L711
我在ioredis github存储库中发现了一些问题,提到了一些EPIPE错误。但是他们中的大多数都是关于错误处理的东西,并且都被标记为已解决。
我还在谷歌上发现了一些常见的EPIPE错误(大部分是关于socket.io的,这不是我用的)。
包扎
这东西怎么了?
发布于 2020-06-26 13:25:04
因为没有人在赏金结束时写了答案。我正在写我的经验,解决问题的人谁将得到这一错误以后。
请注意,这不是一个典型的答案。但这是一个解决方案--
我从分享所发生的事情开始。
我们试图从一个拥有近60万个密钥的Redis服务器上迁移。标准的迁移过程花费了大量的时间将大量密钥从Redis传输到keyDB。所以我遇到了一个不同的解决方案。
我们的KeyDB工作在两个主动-主动复制服务器上.我会提供链接到那些想知道这个系统如何工作。
https://medium.com/faun/failover-redis-like-cluster-from-two-masters-with-keydb-9ab8e806b66c
解决方案是使用一些MongoDB数据库聚合重新构建我们的Redis数据,并在KeyDB上执行一些批处理操作。
这里是一个模拟(不是精确的来源)。另外,我没有测试语法错误)
const startPoint =
(Number.parseInt(process.env.NODE_APP_INSTANCE) || 0) * 40000;
let skip = 0 + startPoint;
let limit = 1000;
let results = await SomeMongooseSchema.find({someQueries}).limit(1000).skip(skip);
let counter = 0;
while (results.length){
if(counter > 39) break;
for(const res of results){
const item = {
key: '',
value: ''
};
// do some build ups on item
...
// end n
app.ioRedisClient.set(item.key, item.value);
}
counter++;
skip = i * limit + startPoint;
results = await SomeMongooseSchema.find({someQueries}).limit(limit).skip(skip);
}使用pm2在16个进程上运行此代码可以在45分钟内设置keyDB的所有键。(与4至5小时相比)
pm2 start app.js -i 16 当我们在Redis服务器上运行代码时。它可以工作,但在KeyDB上给出了以下错误。
error: message=write EPIPE, stack=Error: write EPIPE
./app-error-1.log:37: at WriteWrap.onWriteComplete [as oncomplete] (internal/stream_base_commons.js:92:16), errno=EPIPE, code=EPIPE, syscall=write首先,我首先通过创建事务来优化代码,而不是单独设置每个键。并在每1000次操作之间设置了1秒的间隙。代码更改如下。
const startPoint =
(Number.parseInt(process.env.NODE_APP_INSTANCE) || 0) * 40000;
let skip = 0 + startPoint;
let limit = 1000;
let results = await SomeMongooseSchema.find({someQueries}).limit(1000).skip(skip);
const batch = app.ioredisClient.multi();
let counter = 0;
while (results.length){
if(counter > 39) break;
for(const res of results){
const item = {
key: '',
value: ''
};
// do some build ups on item
...
// end n
batch.set(item.key, item.value);
}
counter++;
await batch.exec();
await sleep();
skip = i * limit + startPoint;
results = await SomeMongooseSchema.find({someQueries}).limit(limit).skip(skip);
}这样,只要操作时间减少到20分钟,错误率就会降低。但这一错误仍然持续存在。
我怀疑此错误可能是由于码头版本的某些权限错误造成的。因此,我要求服务器管理员检查,如果可能的话,删除docker版本并从rpm存储库中安装。
https://download.keydb.dev/packages/rpm/centos7/x86_64/做了然后就成功了。所有的错误都消失了,并在20分钟内成功地迁移了。
我不认为这是一个真正的答案。但是,对于一些专家来说,找出问题所在应该是有用的。。
https://stackoverflow.com/questions/62406075
复制相似问题