新闻文章的 Redis 缓存
Redis cache for news articles
我有一堆新闻文章(目前约 10 万篇)。每篇文章都可以与多个类别相关联。所以我有两个键 article URL
和 category
。我需要将这些文章存储在 Redis 中,并且需要按类别对它们进行分组。我需要快速获取任何类别的所有文章,其中一篇文章 URL。我还需要所有文章的过期时间。
我决定使用哈希集,但后来了解到哈希集项没有有效期。
简而言之,我不确定从这里去哪里最好。我在这方面还很陌生。我想知道是否有一些最佳实践。
您可以使用排序集来存储特定类别的文章列表。您使用 score
作为过期时间,并使用 id
作为值。我不建议您将整篇文章(全文)存储为值,因为您的内存使用量可能会急剧增加,因为多个类别将具有相同的文章,并且您需要将相同的文章存储在不同的多个排序集(类别 a,b ,c可能都有文章1,2,3).
设置文章时;
SET
文章(id 为关键字),带有 EX
选项。 (正文会在这里)
SET
文章 url 作为键,文本作为值,带有 EX
选项。 (这部分我跳过了,你这边已经很清楚了)
- 对于文章的每个类别,运行
ZREMRANGEBYSCORE
(从 -inf 到当前时间戳)删除已经过期的文章。
- 将文章id推入分类排序集合
ZADD
(过期时间为分数,值为文章id)
- 通过
ZRANGE
分页获取文章 ID。
- 或者,您可以在使用
ZRANGE
之前使用 ZREMRANGEBYSCORE。
- 它会给你文章id,然后你可以使用
GET
获取文章的文本。
为简单起见,我使用了较小的过期时间。
127.0.0.1:6379> SET article:1 very-long-article-text EX 120
OK
127.0.0.1:6379> ZREMRANGEBYSCORE category:1 -inf 20
(integer) 0
127.0.0.1:6379> ZADD category:1 3 article:1
(integer) 1
127.0.0.1:6379> SET article:2 article-details EX 120
OK
127.0.0.1:6379> ZREMRANGEBYSCORE category:1 -inf 20
(integer) 1
127.0.0.1:6379> ZADD category:1 3 article:2
(integer) 1
127.0.0.1:6379> ZRANGE category:1 0 9
1) "article:2"
127.0.0.1:6379> ZADD category:2 3 article:2
(integer) 1
如果您不想在排序集中使用文章 ID,您可以设置文本而不是 id
,并在获取所有 ID 后删除 GET
的使用。
@Ersoy 的回答对你的情况来说是一个很好的解决方案,我认为有一些改进:
我建议不要直接使用 URL 作为 redis 键,因为 URL 可能很长并且包含一些特殊字符(如 '/')。使用MD5或BASE64编码将是一个提升。
当执行多个Redis命令更新时,考虑并发情况,如果你一个一个执行这些命令。或者你可以使用事务或锁使其成为原子。
我有一堆新闻文章(目前约 10 万篇)。每篇文章都可以与多个类别相关联。所以我有两个键 article URL
和 category
。我需要将这些文章存储在 Redis 中,并且需要按类别对它们进行分组。我需要快速获取任何类别的所有文章,其中一篇文章 URL。我还需要所有文章的过期时间。
我决定使用哈希集,但后来了解到哈希集项没有有效期。
简而言之,我不确定从这里去哪里最好。我在这方面还很陌生。我想知道是否有一些最佳实践。
您可以使用排序集来存储特定类别的文章列表。您使用 score
作为过期时间,并使用 id
作为值。我不建议您将整篇文章(全文)存储为值,因为您的内存使用量可能会急剧增加,因为多个类别将具有相同的文章,并且您需要将相同的文章存储在不同的多个排序集(类别 a,b ,c可能都有文章1,2,3).
设置文章时;
SET
文章(id 为关键字),带有EX
选项。 (正文会在这里)SET
文章 url 作为键,文本作为值,带有EX
选项。 (这部分我跳过了,你这边已经很清楚了)- 对于文章的每个类别,运行
ZREMRANGEBYSCORE
(从 -inf 到当前时间戳)删除已经过期的文章。 - 将文章id推入分类排序集合
ZADD
(过期时间为分数,值为文章id) - 通过
ZRANGE
分页获取文章 ID。 - 或者,您可以在使用
ZRANGE
之前使用 ZREMRANGEBYSCORE。 - 它会给你文章id,然后你可以使用
GET
获取文章的文本。
为简单起见,我使用了较小的过期时间。
127.0.0.1:6379> SET article:1 very-long-article-text EX 120
OK
127.0.0.1:6379> ZREMRANGEBYSCORE category:1 -inf 20
(integer) 0
127.0.0.1:6379> ZADD category:1 3 article:1
(integer) 1
127.0.0.1:6379> SET article:2 article-details EX 120
OK
127.0.0.1:6379> ZREMRANGEBYSCORE category:1 -inf 20
(integer) 1
127.0.0.1:6379> ZADD category:1 3 article:2
(integer) 1
127.0.0.1:6379> ZRANGE category:1 0 9
1) "article:2"
127.0.0.1:6379> ZADD category:2 3 article:2
(integer) 1
如果您不想在排序集中使用文章 ID,您可以设置文本而不是 id
,并在获取所有 ID 后删除 GET
的使用。
@Ersoy 的回答对你的情况来说是一个很好的解决方案,我认为有一些改进:
我建议不要直接使用 URL 作为 redis 键,因为 URL 可能很长并且包含一些特殊字符(如 '/')。使用MD5或BASE64编码将是一个提升。
当执行多个Redis命令更新时,考虑并发情况,如果你一个一个执行这些命令。或者你可以使用事务或锁使其成为原子。