Как никто не написал ответ в конце награды. Я пишу свой опыт решения проблемы для людей, которые получат эту ошибку позже.
Обратите внимание, что это не канонический ответ. Но это скорее обходной путь.
Я начинаю рассказывать о том, что происходит.
Мы пытались выполнить миграцию с сервера Redis, на котором размещено около 600 000 ключей. Стандартный процесс миграции занимал много времени для переноса такого количества ключей из Redis в keyDB. Итак, я нашел другое решение.
Наша KeyDB работает на 2 серверах Active-Active реплик. Я предоставлю ссылку тем, кто интересуется, как работает эта система.
https://medium.com/faun/failover-redis-like-cluster-from-two-masters-with-keydb-9ab8e806b66c
Решение было воссоздавать наши данные Redis с использованием некоторой агрегации базы данных MongoDB и выполнение некоторых пакетных операций на 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);
}
Запуск этого кода в 16 процессах с использованием pm2
устанавливает все ключи в keyDB примерно за 45 минут. (по сравнению с 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
Сначала я начал с настройки кода, создав транзакцию, вместо того, чтобы настраивать каждый ключ отдельно. и установил интервал в 1 секунду между каждыми 1000 операциями. код изменился следующим образом.
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. Поэтому я попросил администратора нашего сервера проверить и, если возможно, удалить версию docker и установить ее из репозитория rpm.
https://download.keydb.dev/packages/rpm/centos7/x86_64/
Сделал это, и это сработало. Все ошибки исчезли, и их удалось успешно перенести за 20 минут.
Я не считаю это реальным ответом. Но это должно быть полезно для некоторых экспертов, чтобы выяснить, что случилось.