From 7cd9a90f2677681bc697148db41a8270baf6346d Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 8 Oct 2023 07:51:10 +0900 Subject: [PATCH] perf(backend): use HyperLogLog instead of Set to improve hashtag chart performance --- packages/backend/src/core/HashtagService.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/HashtagService.ts b/packages/backend/src/core/HashtagService.ts index 1a06767da..ddff28359 100644 --- a/packages/backend/src/core/HashtagService.ts +++ b/packages/backend/src/core/HashtagService.ts @@ -174,16 +174,15 @@ export class HashtagService { const redisPipeline = this.redisClient.pipeline(); - // TODO: これらの Set は Bloom Filter を使うようにしても良さそう - // チャート用 - redisPipeline.sadd(`hashtagUsers:${hashtag}:${window}`, userId); + redisPipeline.pfadd(`hashtagUsers:${hashtag}:${window}`, userId); redisPipeline.expire(`hashtagUsers:${hashtag}:${window}`, 60 * 60 * 24 * 3, // 3日間 'NX', // "NX -- Set expiry only when the key has no expiry" = 有効期限がないときだけ設定 ); // ユニークカウント用 + // TODO: Bloom Filter を使うようにしても良さそう redisPipeline.sadd(`hashtagUsers:${hashtag}`, userId); redisPipeline.expire(`hashtagUsers:${hashtag}`, 60 * 60, // 1時間 @@ -202,7 +201,7 @@ export class HashtagService { for (let i = 0; i < range; i++) { const window = `${now.getUTCFullYear()}${(now.getUTCMonth() + 1).toString().padStart(2, '0')}${now.getUTCDate().toString().padStart(2, '0')}${now.getUTCHours().toString().padStart(2, '0')}${now.getUTCMinutes().toString().padStart(2, '0')}`; - redisPipeline.scard(`hashtagUsers:${hashtag}:${window}`); + redisPipeline.pfcount(`hashtagUsers:${hashtag}:${window}`); now.setMinutes(now.getMinutes() - (i * 10), 0, 0); } @@ -223,7 +222,7 @@ export class HashtagService { for (let i = 0; i < range; i++) { const window = `${now.getUTCFullYear()}${(now.getUTCMonth() + 1).toString().padStart(2, '0')}${now.getUTCDate().toString().padStart(2, '0')}${now.getUTCHours().toString().padStart(2, '0')}${now.getUTCMinutes().toString().padStart(2, '0')}`; for (const hashtag of hashtags) { - redisPipeline.scard(`hashtagUsers:${hashtag}:${window}`); + redisPipeline.pfcount(`hashtagUsers:${hashtag}:${window}`); } now.setMinutes(now.getMinutes() - (i * 10), 0, 0); }