-
Notifications
You must be signed in to change notification settings - Fork 71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Discussion: migrate from "unmaintained" redisio to node-redis #555
Comments
I propose something like this as a starting point for others that run into wanting to scale properly with sharded replicas: // src/redis/redis.module.ts
import { DynamicModule, Global, Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import {
createCluster,
RedisClusterType,
RedisFunctions,
RedisModules,
RedisScripts,
} from 'redis';
export const REDIS_CLIENT = 'REDIS_CLIENT';
@Global()
@Module({})
export class RedisModule {
static forRoot(): DynamicModule {
return {
module: RedisModule,
imports: [ConfigModule],
providers: [
{
provide: REDIS_CLIENT,
useFactory: async (
configService: ConfigService,
): Promise<
RedisClusterType<RedisModules, RedisFunctions, RedisScripts>
> => {
const nodes =
configService
.get<string>('REDIS_NODES')
?.split(',')
.map((node) => {
const [host, port] = node.split(':');
return {
url: `redis://${host}:${port}`,
};
}) || [];
const cluster = createCluster({
rootNodes: nodes,
defaults: {
password: configService.get('REDIS_PASSWORD'),
socket: {
connectTimeout: 14444,
reconnectStrategy: (retries) => {
if (retries > 22) {
return new Error('Redis cluster connection failed');
}
return Math.min(retries * 77, 2222);
},
},
},
});
cluster.on('error', (err) => {
console.error('Redis Cluster Error:', err);
});
cluster.on('connect', () => {
console.log('Redis Cluster Connected');
});
await cluster.connect();
return cluster;
},
inject: [ConfigService],
},
],
exports: [REDIS_CLIENT],
};
}
} Then include it in your app.module.ts: ...
import { RedisModule } from './redis/redis.module';
@Module({
imports: [
ConfigModule.forRoot(),
RedisModule.forRoot(),
],
})
export class AppModule {} And then use it in services: import {
Inject,
Injectable,
Logger,
} from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { REDIS_CLIENT } from 'src/redis/redis.module';
import {
RedisClusterType,
RedisFunctions,
RedisModules,
RedisScripts,
} from 'redis';
@Injectable()
export default class MyService{
private readonly logger = new Logger(MyService.name);
constructor(
@Inject(REDIS_CLIENT)
private readonly redis: RedisClusterType<
RedisModules,
RedisFunctions,
RedisScripts
>,
) {}
async deleteKeysByPattern(pattern: string) {
this.logger.log(
`Initiating deletion for keys matching pattern: ${pattern}`,
);
// In cluster mode, we need to scan each master node
const keysToDelete = new Set<string>();
// Get all keys from each master node
await Promise.all(
this.redis.masters.map(async (master) => {
const client = await this.redis.nodeClient(master);
for await (const key of client.scanIterator({
MATCH: pattern,
COUNT: 100,
})) {
keysToDelete.add(key);
}
}),
);
// Delete all found keys
if (keysToDelete.size > 0) {
const keys = Array.from(keysToDelete);
this.logger.log(`Deleting keys: ${keys.join(', ')}`);
await Promise.all(keys.map((key) => this.redis.del(key)));
}
this.logger.log(`Deletion for keys matching pattern: ${pattern} completed`);
}
} And example values you might want to have in your .env:
And finally, here's a nice guide to help you setup redis with shards in cluster in case you are using docker: |
No doubt, this is a work in progress. |
are you guys aware of issue with redisio and cluster that has been present for several years and the issue is still open?
Please review this carefully:
Thanks for raising this up! Yeah we currently don't route messages to the right node and also don't subscribe to the right node. Should think about a solution for that.
I propose we need to swith to node-redis which is maintained and works correctly
The text was updated successfully, but these errors were encountered: