@Interval(1000 * 60)
async handleScheduledTasks() {
// await this.redisConnection();
for (const channelType of Object.values(ChannelType)) {
let cursor = '0';
const tasks = [];
do {
const [nextCursor, keys] = await this.redisDataClient.scan(
cursor,
'MATCH',
`${channelType}:*`,
'COUNT',
100,
);
cursor = nextCursor;
if (keys.length === 0) continue;
for (const key of keys) {
tasks.push(this.processKey(key));
if (tasks.length >= 500) {
await Promise.all(tasks.splice(0, 500));
}
}
} while (cursor !== '0');
await Promise.all(tasks);
}
}
async processKey(key: string) {
const retainCount = 50;
const messages = await this.redisDataClient.lrange(
key,
0,
-retainCount - 1,
);
if (messages.length > 0) {
const [channelType, roomId] = key.split(':chat:');
await this.saveMessagesToDatabase(messages, channelType, +roomId);
await this.redisDataClient.ltrim(key, -retainCount, -1);
}
}
기존 로직인 채팅을 레디스에 저장하는 로직은 유지하되, mongodb에 저장하여 저장이 되는것을 기다리지 않고 서버에 부하가 최소화되게끔 로직을 구현함
async saveMessagesToDatabase(
messages: string[],
channelType: string,
roomId: number,
) {
const chats = [];
for (const message of messages) {
const parsedMessage = JSON.parse(message);
const user = await this.usersInfoRepository.findOne({
where: { id: parsedMessage.userId },
select: ['nickName'],
});
chats.push(
new this.chatModel({
message: parsedMessage.message,
userId: parsedMessage.userId,
RoomId: roomId,
timestamp: parsedMessage.timestamp,
userName: user ? user.nickName : 'Unknown User',
channelType: channelType,
}),
);
}
try {
await this.chatModel.insertMany(chats);
} catch (error) {
console.log('몽고 디비 저장 중 오류가 발생했습니다.:', error);
}
}
대규모 비정형 데이터를 성능 면에서 최적화된 mongodb로 저장함으로써 좀 더 빠르게 저장 가능함
rdbms와는 달리 채팅 데이터를 가져오는데 있어서 복잡한 조인이 필요하지 않음
차후 채팅 데이터의 변경에 있어서 그 전의 데이터와의 일관성을 유지하기 힘듬 rdbms에 비해 비교적 높은 메모리 사용량