我在mac上有一个本地设置,运行一个有6个节点的redis集群。每当集群离线时,我一直试图处理连接错误并限制重试次数(有目的地试图触发mongo的回退(,但无论我传入的集群/redis选项如何,它都会不断重试,除非我返回"0";空";集群RetryStrategy中。这是我的redis服务的快照。
import Redis from 'ioredis';
export class RedisService {
public readonly redisClient: Redis.Cluster;
public readonly keyPrefix = 'MyRedisKey';
public readonly clusterOptions: Redis.ClusterOptions = {
enableReadyCheck: true,
retryDelayOnClusterDown: 3000,
retryDelayOnFailover: 30000,
retryDelayOnTryAgain: 30000,
clusterRetryStrategy: (times: number) => {
// notes: this is the only way I have figured how to throw errors without retying for ever when connection to the cluster fails.
// tried to use maxRetriesPerRequest=1, different variations of retryStrategy
return null;
},
slotsRefreshInterval: 10000,
redisOptions: {
keyPrefix: this.keyPrefix,
autoResubscribe: true,
autoResendUnfulfilledCommands: false,
password: process.env?.REDIS_PASSWORD,
enableOfflineQueue: false,
maxRetriesPerRequest: 1
}
};
constructor() {
const nodes: any = ['127.0.0.1:30001','127.0.0.1:30002','127.0.0.1:30003','127.0.0.1:30004','127.0.0.1:30005','127.0.0.1:30006'];
this.redisClient = new Redis.Cluster(nodes, this.clusterOptions);
}
public hget = async (field: string): Promise<any> => {
const response = await this.redisClient.hget(this.keyPrefix, field);
return response;
}
}
如果我的redis集群被停止,我会调用这个服务,比如:
public readonly redisService: RedisService = new RedisService();
try {
const item = await this.redisService.hget('test');
} catch(e){
console.error(e);
}
我无休止地得到错误";[ioredis]未处理的错误事件:ClusterAllFailedError:刷新插槽缓存失败"而且它永远不会掉到接球块里。
顺便说一句,我尝试了这里列出的解决方案,但没有成功。Redis(ioredis(-无法捕获连接错误以正常处理它们。
以下是我正在使用的ioredis npm包的版本。
"ioredis": "4.19.4"
"@types/ioredis": "4.17.10"
谢谢你的帮助。
刷新插槽缓存由IoRedis自动完成。将它们设置为10000ms是不好的,因为这意味着添加到集群中的任何新碎片在10秒内都不会被NodeJs服务器看到(这可能会在运行时产生一些严重错误(
为了捕捉这些错误,您可以监听error
事件。
this.redisClient.on('error', async (error: any) => {
logger.error(`[EventHandler] error`, { errorMessage: error.message });
});
关于集群RetryStrategy,确实有点奇怪。根据我的发现,IoRedis将这个clusterRetryStrategy
函数称为如下
- 第二个参数中有几次没有错误
- 参数
getaddrinfo ENOTFOUND
中传递了大量具有实际错误的时间 - 当连接恢复正常时,永远不会出现错误
为了在连接恢复时停止无限循环,我使用以下函数:
import Redis from 'ioredis';
export class RedisService {
public readonly redisClient: Redis.Cluster;
public readonly keyPrefix = 'MyRedisKey';
private retryStrategyErrorDetected: boolean = false;
public readonly clusterOptions: Redis.ClusterOptions = {
clusterRetryStrategy: (times: number, reason?: Error) => {
tLogger.warn(`[EventHandler] clusterRetryStrategy`, { count: times, name: reason?.message});
if (this.retryStrategyErrorDetected && !reason) {
this.retryStrategyErrorDetected = false;
return null;
}
if (reason) {
this.retryStrategyErrorDetected = true;
}
return Math.min(100 + times * 2, 2000);
};
},
};
constructor() {
const nodes: any = ['127.0.0.1:30001','127.0.0.1:30002','127.0.0.1:30003','127.0.0.1:30004','127.0.0.1:30005','127.0.0.1:30006'];
this.redisClient = new Redis.Cluster(nodes, this.clusterOptions);
this.redisClient.on('error', async (error: any) => {
logger.error(`[EventHandler] error`, { errorMessage: error.message });
});
}
}
希望它能帮助到别人。