欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 八卦 > 用户刷题记录日历——签到表功能实现

用户刷题记录日历——签到表功能实现

2025/6/6 22:02:58 来源:https://blog.csdn.net/cui_hao_nan/article/details/148122988  浏览:    关键词:用户刷题记录日历——签到表功能实现

MySQL实现

在数据库中设计一张签到表,记录用户每次签到的日期及其他相关信息。然后通过时间范围查询得到用户的签到记录。

CREATE TABLE user_sign_in (id BIGINT AUTO_INCREMENT PRIMARY KEY,  -- 主键,自动递增userId BIGINT NOT NULL,               -- 用户ID,关联用户表signDate DATE NOT NULL,            -- 签到日期createdTime TIMESTAMP DEFAULT CURRENT_TIMESTAMP,  -- 记录创建时间UNIQUE KEY uq_user_date (userId, signDate)  -- 用户ID和签到日期的唯一性约束
);

通过唯一索引,可以确保同一用户在同一天内只能签到一次。v7MVXjmkYSVF6bWEkbEtbK7rqOSiRVZrvgDMFuqdQNE=

通过下面的 SQL 即可查询用户的签到记录:

SELECT signDate FROM user_sign_in 
WHERE userId = ? AND signDate BETWEENAND ?;

分析:

优点:原理简单,容易实现,适用于用户量较小的系统。

缺点:

1、存储空间占用大

字段名数据类型估算空间说明
idBIGINT8 字节主键,自增
userIdBIGINT8 字节用户ID
signDateDATE3 字节日期:YYYY-MM-DD
createdTimeTIMESTAMP4 字节时间戳(支持秒级精度)

如果存储 100 万个用户,365天的签到记录,需要 100 万× 365 × 40字节 = 14GB

随着用户量和数据量增大,对数据库的压力增大,直接查询数据库性能较差。除了单接口的响应会增加,可能整个系统都会被其拖垮。

基于缓存 Redis Set

可以利用内存缓存加速读写,常用的本地缓存是 Caffeine,分布式缓存是 Redis。

由于每个用户会有多个签到记录,很适合使用 Redis 的 Set 类型存储,每个用户对应一个键,Set 内的每个元素为签到的具体日期

Redis Key 的设计为:user:signins:{userId}

其中:

  1. user 是业务领域前缀
  2. signins 是具体操作或功能
  3. {userId} 表示每个用户,是动态值

如果 Redis 被多个项目公用,还可以在开头增加项目前缀区分,比如 interviewPal:user:signins:{userId}。

具体示例如下,可以使用 Redis 命令行工具添加值到集合中:

SADD user:signins:123 "2024-09-01"
SADD user:signins:123 "2024-09-02"

使用命令查找集合中的值:

SMEMBERS user:signins:123

优点:Set 数据结构天然支持去重,适合存储和检索打卡记录。

存储 100 万个用户 的 365 天 签到记录,使用 Redis 集合类型来存储每个用户的签到信息,每个用户需要大约 1880 字节(365 × 4字节)的空间,总共需要大约 1.88GB 的内存空间,相比数据库节约了 10 倍左右。

Bitmap 位图

Bitmap 位图,是一种使用位(bit)来表示数据的 紧凑 数据结构。每个位可以存储两个值:0 或 1,常用于表示某种状态或标志。因为每个位仅占用 1 位内存,Bitmap 在大规模存储二值数据(如布尔值)时,非常高效且节约空间。

核心思想:与其存储用户签到的具体日期,不如存储用户在今年的第 N 天是否签到

2024-01-01 => 1(第一天)
2024-01-03 => 3(第三天)

使用位图类型存储,每个用户对应一个键,Bitmap 的 每一位 来表示用户在 某一天 是否打卡。

把 int 优化成用 bit 存储,那么占用的空间可以优化 32 倍!假设原先占用的大小需要 32 G,那么改造后仅需 1 G

对于刷题签到记录场景,一个用户存储一年的数据仅需占用 46 字节,因为 46 * 8 = 368,能覆盖 365 天的记录。那一百万用户也才占用 43.8 MB,相比于 Redis Set 结构节约了 40 多倍存储空间!

Redis Key 的设计为:user:signins:{年份}:{userId}

设置某一个 bit 值的命令如下:

-- 表示用户在第 240 天打卡
SETBIT user:signins:2024:123 240 1
-- 表示用户在第 241 天打卡
SETBIT user:signins:2024:123 241 1

查询某一个 bit 值的命令:

GETBIT user:signins:2024:123 240

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词