核心问题
一个项目中,遇到了搜索热词统计的需求,我使用了 redis 的五大数据类型之一 Sorted Set 实现。目前有两项数据需要统计:“当日搜索热词 top10”和“当周搜索热词 top10”。
关于这两项数据的统计方法,目前想到了两种实现方法:
- 两个 redis 的 Sorted Set 实现,一个 Sorted Set A 统计当天,0 点 top10 记录进 mysql,Sorted Set 清零。一个 Sorted Seted B 统计当周,每周日 top10 记录进 mysql,Sorted Set B 清零。
- 只使用用一个 Sorted Set 记录当天搜索热词,0 点 top10 记录进 mysql,Sorted Set 清零。到周日时,会有 7 * 10 行记录。把这 7 * 10 行遍历,每次便利都记录进 Sorted Set,全部遍历结束后,再从 Sorted Set 中取出 top10 记录进 mysql 的周热词统计表中。
Sorted Set 是 redis 的数据结构,方法 1 会占用两份内存,一份当天的,一份当周的。方法 2 会提高系统的复杂度,并且在统计周表时,可能会出现短时间内大量的计算(当然可以使用定时任务放到凌晨进行)。
请问我该选择哪种解决办法比较好呢?
硬件与用户量
我在写的是一个学生项目,ECS 是 1 核 2GB 内存的学生机(别歧视呀哈哈,穷学生 😅)。如果当天的搜索热词和当周的搜索热词都使用 redis 内存记录,我怕内存会爆炸。
目前生产环境的 ECS 内存用了 1GB,保守还剩 900MB,我怕 redis 消耗两份内存会炸。目前是一个小程序的后端,快要上线了,预计初期用户数量不多。关键词长度限制最大 8
天马行空想一下,1MB = 1048576 字节,按两个字节存一个字算,1MB 能存 1048576/2/8 = 65,536 个不重复的搜索关键词,看起来好像可以存很多。我没熟练使用过 redis,不知道这样天马行空地计算,是否真的可以呢 🤔
问题中涉及的相关知识(如已经了解问题,这部分可忽略)
一个项目中,遇到了搜索热词统计的需求。我使用了 redis 的五大数据类型之一 Sorted Set 实现。
Redis 有序集合(sorted set)
Redis 有序集合和集合一样也是 string 类型元素的集合,且不允许重复的成员。
不同的是每个元素都会关联一个 double 类型的分数。redis 正是通过分数来为集合中的成员进行从小到大的排序。
有序集合的成员是唯一的,但分数(score)却可以重复。
集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储 40 多亿个成员)。
如上图,redis 的 Sorted Set 自带排序功能。
操作方法也比较简单,在本项目中,核心是两个方法:
zincrby 命令,对于一个 Sorted Set,存在的就把分数加 x (x 可自行设定),不存在就创建一个分数为 1 的成员。
zrevrange,查询集合中指定顺序的值。返回有序的集合中,score 大的在前面。