Redis Bitmaps 实战:签到系统内存优化与连续签到算法
做签到类需求大家第一反应大概率是建一张sign_log表user_id、sign_date、奖励批次再加个唯一索引。真这么干也不是跑不通就是性价比低得让人心疼。我在接手某个电商App的每日签到积分玩法时日活几十万一个月下来签到记录几千万行连续签到计算在关系库里绕来绕去最后直接换成 Redis Bitmaps整套逻辑退化成一堆位运算命令内存和响应时间都稳住了。这篇文章不给你贴完整业务代码而是把 Bitmaps 的底层原理、Key 设计、命令实操、连续签到算法、跨月边界、以及我踩过的坑一次说透。正在做签到、日活统计、灰度放量的同学可以直接拿去做参考。1. Bitmaps 到底是什么把二值状态压缩到极致的数据结构1.1 先忘掉数据库表从“一位就是一天”说起签到这个业务抽掉所有包装之后本质是一个用户在某一天只有两种状态签了1和没签0。一个用户一个月最多 31 个二值状态。这种“是/否”标记就是 Bitmaps 最典型的适用场景。Redis 的 Bitmaps 并不是一个独立的数据结构底层就是普通的字符串String。只不过 Redis 给字符串额外提供了一套按“位”读写的命令让你可以精确操作某个比特位。一位只能存 0 或 18 位组成一个字节。你可以把它理解成一张只有 0 和 1 的细长纸条每一位都有一个编号这个编号叫 offset偏移量。一个字节里有 8 个这样的“开关”所以同一个用户一个月的签到状态只需要 4 个字节就能存下因为 31 位刚好不到 4 字节Redis 字符串按字节分配用 4 字节存储。这个压缩比例任何关系型数据库都做不到。1.2 必须打熟的 6 个位命令在动手设计之前先把 Redis 的位操作命令过一遍后面所有代码都是这几个命令的组合SETBIT key offset value把 key 对应的字符串在 offset 位置写入 1 或 0返回该位置原来的值。GETBIT key offset读出 offset 位置的位值0 或 1。BITCOUNT key [start end [BIT]]统计整个字符串里值为 1 的位一共有多少个。start/end 默认是字节下标Redis 7.0 开始支持加BIT参数按位下标统计。BITOP operation destkey key [key ...]对多个 key 做位运算支持 AND、OR、XOR、NOT结果写入 destkey。BITPOS key bit [start end [BIT]]从前往后找第一个出现指定值0 或 1的位置。BITFIELD key GET/SET uX offset一次读写连续的若干位适合把一小段位当成整数一次性取出来。这里有一个非常关键、也最容易出错的细节Redis 的“位编号”和我们平时的字节习惯相反。bit 0是字符串第一个字节的最高位最左边那位bit 7才是第一个字节的最低位。举一个例子执行SETBIT k 0 1后GET k拿到的内容是二进制10000000也就是0x80再执行SETBIT k 7 1这个字节才变成10000001也就是0x81。很多坑都出在这个位序上后面第 4 节我会专门展开。1.3 先算一笔内存账为什么这个方案便宜得离谱我做需求前习惯先算账。假设全站 10 万用户每人当月平均签到 15 天关系库方案建一张sign_log表每行至少 user_id、sign_date、source 三个字段算上行头、索引、页填充单行实际占用 40~50 字节不是夸张。一个月就是 150 万行一年 1800 万行光原始数据就接近 1GB这还没算连续签到查询要做的自关联和窗口函数开销。Redis Bitmaps 方案每个用户每月一个 key数据部分只有 4 字节。10 万个 key 的 Redis 字典开销按每个 100 字节估整体也就在 10MB 上下浮动。查询一个用户当月签了多少天一条BITCOUNT命令就完事查连续签到31 次GETBIT撑死。再看另一种常见对比如果业务方要的是“某一天全站有多少人签到”用 Set 存sadd sign:20260107 userId1 万用户就是 1 万个成员每个成员一套哈希表开销而 Bitmaps 用用户 ID 充当偏移量直接在sign:20260107这个 key 上用SETBIT sign:20260107 userId 11 万用户只占 1250 字节。两者相差几十倍。方案数据量10万用户/月存储估算连续签到查询关系库 sign_log 表150万行约 1GB含索引窗口函数逐行算Redis Set10万成员/天每天几十MB级需额外聚合Redis Bitmaps10万 key x 4B约 10MBGETBIT 循环 31 次即可这个账算完基本没有理由不用 Bitmaps。但前提是你把 Key 结构和偏移量约定设计对否则省下来的内存会被各种错误操作加倍吐回去。2. 签到场景的数据结构设计Key 怎么定偏移量怎么算2.1 Key 命名把用户 ID 和月份放进一个 Key签到查询有两个固定维度哪个用户、哪个月。所以最自然的 Key 结构是sign:{userId}:{yyyyMM}例如用户10001在 2026 年 1 月的签到记录Key 就是sign:10001:202601。这个 Key 内部最多 31 个位对应 1 月 1 日到 1 月 31 日。这里有两个实践建议如果 Redis 部署的是集群模式建议把用户 ID 用花括号包起来写成sign:{10001}:202601。Redis Cluster 的哈希槽只对{}里面的内容做计算这样同一个用户的所有月度 Key 会落在同一个节点后续做 Lua 脚本、批量操作都能避免跨节点访问。另一个建议是把月份固定成六位数字不要用2026-01或者20260101这种带分隔符的格式。统一的固定位数能保证 Key 字符串长度稳定更容易排查和扫描。2.2 偏移量第 1 天就是 bit 0别搞混这是整个方案最容易翻车的地方。我把偏移量约定为offset 当月的第几天 - 1也就是说1 月 1 日对应 offset 01 月 2 日对应 offset 11 月 31 日对应 offset 30。这样设计的原因很简单GETBIT sign:10001:202601 0读出来如果是 1语义就是“1 月 1 日已签到”跟人类直觉完全一致。有人会习惯用“第几天直接当偏移量”也就是 1 号对应 offset 131 号对应 offset 31。这种写法不是不行但月底那几天容易出边界问题而且当你用BITCOUNT统计“本月已签天数”时需要额外判断 31 日是否存在。更严重的是如果两个开发同学一个用 day-1一个用 day整个月的记录都会错位一天这种问题在联调阶段非常难查。所以我强烈建议把偏移量计算封装成一个统一函数比如getOffset(day)内部自动减 1所有业务代码只传“第几天”不要到处直接写day - 1。2.3 为什么按月度拆 Key而不是按年度或按天有人会问能不能一个用户一年一个 Key365 个位一次性存完好处是连续签到不用处理跨月坏处也很明显按月拆 Key每个 Key 最多 4 字节Key 短、生命周期清楚到期直接过期清理。按年拆 Key一个 Key 46 字节看起来也不大但你想统计“1 月签了多少天”就必须做BITCOUNT key 0 30 BIT这种位段统计。在 Redis 7.0 之前位段统计非常别扭。月度 Key 天然适合做 TTL。比如业务只要求保留最近 6 个月的签到记录那生成 Key 时直接EXPIRE key 180 天完全不用写定时任务清理。按天拆 Key 也不是不行但那是“全站用户”维度比如sign:all:20260107统计当天有多少人签到。个人维度的签到还是月度 Key 最顺手。2.4 过期时间到底设多久月度 Key 的 TTL 设置是个业务决策。我只说一个容易踩的典型事故有次我把 TTL 设成了 31 天结果上个月前几天的签到数据在月底报表跑批前就过期了运营拿到的数据少了一大截。我的习惯是业务要求“最近一个季度可查”我就设 180 天 TTL覆盖三个月之外还有富余如果还要求年度累计那就不要让 Bitmaps 承担历史归档职责单独用一个哈希 Key 比如sign:stat:10001:2026每天累加一次成本几乎可以忽略。3. 实操落地签到、统计、连续签到一步一步写3.1 签到接口一条 SETBIT 就够还自带幂等用户点签到核心逻辑只有一行redis-cli SETBIT sign:10001:202601 0 1含义是用户10001在 2026 年 1 月 1 日签到偏移量 0 对应 1 号。真正要注意的是SETBIT的返回值——它返回该位原来的值。这个特性可以直接用来做“是否已签到”的幂等判断省一次GETBITimport redis client redis.Redis(host127.0.0.1, port6379, decode_responsesFalse) def sign_in(user_id: int, year: int, month: int, day: int): key fsign:{user_id}:{year}{month:02d} offset day - 1 prev client.setbit(key, offset, 1) if prev 1: return already_signed # 到这里才说明这次签到真正生效可以发积分、发奖励了 return ok这里还有一个细节签到接口一定要校验 offset 不能是未来日期。如果运营配置错了活动规则或者客户端传入了一个未来日期SETBIT会把未来的位也置成 1月度统计就会多出“未来签到”的脏数据。3.2 月度日历渲染和签到天数统计需要渲染整个月的签到日历最朴素的办法是循环 31 次GETBIT。别觉得循环性能差一个月最多 31 次位读取而且可以用 pipeline 在客户端合并成一次网络往返import calendar def month_status(user_id: int, year: int, month: int): key fsign:{user_id}:{year}{month:02d} days calendar.monthrange(year, month)[1] pipe client.pipeline(transactionFalse) for day in range(1, days 1): pipe.getbit(key, day - 1) bits pipe.execute() return {day: bits[day - 1] for day in range(1, days 1)}整月签到次数就更简单了一条BITCOUNTredis-cli BITCOUNT sign:10001:202601返回 1 的位数就是这个月的签到天数。如果想统计某一周、某一个连续段的签到数Redis 7.0 之后的写法是# 统计 1 月 1 日到 1 月 7 日offset 0~6的签到数 redis-cli BITCOUNT sign:10001:202601 0 6 BIT注意末尾的BIT参数它告诉 Redis start/end 这两个下标按“位”来算而不是按“字节”。这个问题在旧版本里非常坑我放到第 4 节详细说。3.3 连续签到计算循环倒查是最稳妥的写法连续签到尤其是“距离今天连续签了几天”是签到系统里最常被问到的需求。我推荐的做法是从今天往回倒查遇到第一个 0 就停def continuous_streak(user_id: int, year: int, month: int, day: int): key fsign:{user_id}:{year}{month:02d} offset day - 1 streak 0 for i in range(offset, -1, -1): if client.getbit(key, i) 1: streak 1 else: break return streak这段逻辑很好懂今天如果没签到第一轮GETBIT就是 0streak 直接返回 0今天签了再看昨天一直往前推。月度内最多循环 31 次加上 pipeline对一个 Redis 实例来说几乎是零压力。有人觉得循环不够“高级”其实完全没必要担心。真正在性能上有质的区别的是另一种需求判断“最近 7 天是否连续签到”。这种固定窗口判断可以用掩码加位运算一次算完先构造一个 mask key把窗口内的位全部置成 1# 假设今天是 1 月 10 日要判断 1 月 4 日到 10 日offset 3~9是否都签到 redis-cli SETBIT mask:10001:w2 3 1 redis-cli SETBIT mask:10001:w2 4 1 redis-cli SETBIT mask:10001:w2 5 1 redis-cli SETBIT mask:10001:w2 6 1 redis-cli SETBIT mask:10001:w2 7 1 redis-cli SETBIT mask:10001:w2 8 1 redis-cli SETBIT mask:10001:w2 9 1然后对用户 Key 和 mask 做一次 AND结果再数 1redis-cli BITOP AND week2:10001 sign:10001:202601 mask:10001:w2 redis-cli BITCOUNT week2:10001如果BITCOUNT结果是 7说明窗口内 7 天全部签到小于 7说明中间有断档。这个思路的核心是“只有对方位都为 1AND 之后才是 1”相当于用一个外部模板去筛选。还有一种更简洁的思路用BITFIELD把连续位段一次性读成整数再和“全 1”的数比较# 读取 offset 3 开始的 7 个位如果全是 1得到 127 redis-cli BITFIELD_RO sign:10001:202601 GET u7 3如果返回 127这 7 位全是 1返回 0说明这 7 位全是 0。这个方案适合判断“一个固定窗口是否全勤”但是不适合算“连续到今天是几天”因为你需要知道断点在哪个位置。3.4 跨月连续签到把上个月尾巴接上月度 Key 最大的边界问题就是跨月。比如用户 1 月 1 日、1 月 2 日都签了到那他的连续签到可能是 2 天但如果他 12 月 30 日、12 月 31 日也签了加上 1 月 1 日、1 月 2 日实际是 4 天。我把跨月逻辑写进同一个连续签到函数里原则是当月从今天往前数如果一直数到 1 号都是 1再继续去上个月从月末往月初数def continuous_streak_cross_month(user_id: int, check_date): year check_date.year month check_date.month day check_date.day key fsign:{user_id}:{year}{month:02d} offset day - 1 streak 0 reached_month_start True for i in range(offset, -1, -1): if client.getbit(key, i) 1: streak 1 else: reached_month_start False break if not reached_month_start: return streak # 当月从 1 号到今天全部签到继续查上个月 from datetime import date, timedelta last_month_end date(year, month, 1) - timedelta(days1) prev_key fsign:{user_id}:{last_month_end.year}{last_month_end.month:02d} for i in range(last_month_end.day - 1, -1, -1): if client.getbit(prev_key, i) 1: streak 1 else: break return streak这个函数有一个好处它不要求“今天必须是 1 号”。哪怕是 1 月 15 日用户从 1 月 1 日到 15 日连续签满也会自动去查 12 月的情况把跨月连续天数接上。业务逻辑里最忌讳的就是“只有月初才处理跨月”这种特判后面一定会漏场景。3.5 用 Lua 保证签到和发奖的原子性签到和“判断是否已签到、写入、发积分”是一个组合操作。如果全靠客户端多条命令在并发场景下可能出现两个请求同时读到未签到都发积分积分翻倍。最稳妥的方法是把这个流程塞进一个 Lua 脚本Redis 会保证脚本内部命令的原子性-- KEYS[1] sign:{userId}:{yyyyMM} -- ARGV[1] 当天是这个月的第几天1-based -- 返回 1 表示签到成功-1 表示重复签到 local day tonumber(ARGV[1]) local exists redis.call(GETBIT, KEYS[1], day - 1) if exists 1 then return -1 end redis.call(SETBIT, KEYS[1], day - 1, 1) return 1脚本执行成功之后再根据返回值走客户端的发奖逻辑。即使发奖这一步不在 Redis 里签到去重这一层已经在 Redis 侧闭环了不会重复签到。4. 实操中常见的坑与排查实录4.1 位序搞错为什么GET k看到的字节和你想象的不一样这是一个让我吃过亏的细节。Redis 的位 0 在第一个字节的最高位不是说“第一个字节的第 1 位”这种直觉。拿SETBIT k 7 1举例你得到的是一个字节0x01也就是二进制00000001而SETBIT k 0 1得到的是0x80二进制10000000。这个特性在单独使用GETBIT/SETBIT时问题不大因为偏移量直接映射到业务语义。最容易翻车的是你在客户端构造二进制字符串然后整体写入。比如想在 offset 7 的位置写入 1如果你用struct.pack(B, 1)构造一个大端字节没问题但如果你用struct.pack(B, 1)再误以为“第一位”是 offset 0最后会发现数据全拧了。排查这类问题我的习惯是先把一个已知的小字节写进去比如SETBIT test 7 1然后GET test看输出对应预期值再用这个基准去校验代码里的打包逻辑。4.2 偏移量“爆炸”一条 SETBIT 让 Redis 内存飙到数百 MB这是我在别的团队看到的一次真实事故。有人想用时间戳当偏移量写了一句SETBIT sign:10001 1735545600000 1想把 2026 年的某个时间点标记成签到。Redis 收到命令后的第一件事是把字符串扩到偏移量所在的位置1735545600000 位换算下来接近 217GB直接触发内存上限线上 Redis 被打挂。这里要记住Redis 字符串长度最大 512MB所以偏移量理论最大是 2^32 左右但你实际上不可能真的去申请那么大内存。签到这类业务偏移量只允许在 0 到 30 之间。正确做法就是在接入层做非法偏移量校验或者把偏移量计算全部收敛到统一工具函数里任何人都不允许直接调SETBIT。还有一个相关坑BITCOUNT不会因为位没写过就报错没写过的位默认是 0这个没问题但是如果你统计时把未来日期也算进偏移量BITCOUNT 的结果会包含“未来的 1”月度签到天数直接失真。4.3 BITCOUNT 的 start/end 到底是字节还是位在 Redis 7.0 之前BITCOUNT key start end的 start 和 end 都是“字节下标”不是位下标。很多人想统计“第 8 到第 14 位”写成BITCOUNT key 8 14结果统计的是 buffer 里第 8 个字节到第 14 个字节也就是 56 个位结果直接翻好几倍。Redis 7.0 加了BIT参数之后正确的写法是# 统计 offset 8 到 14 的位 redis-cli BITCOUNT sign:10001:202601 8 14 BIT如果是旧版本必须用掩码BITOP AND方案或者用BITFIELD把位段读出来再自行数 1。项目如果还在用 Redis 6.x我的建议是把所有位段统计逻辑封装好明确标注“不要直接用 BITCOUNT 带 start/end”减少误用。4.4 补签和未来日期脏数据是怎么混进来的补签逻辑本身很简单无非是再调一次SETBIT把某个历史日期改成 1。但补签有两个限制必须做只能补最近 N 天比如 3 天内。原因是运营规则防止用户无限回溯刷奖励。不能补未来日期。如果用户请求里带了明天的偏移量而你不校验明天还没到那位的值就已经是 1 了。我的做法是在补签接口里先比较偏移量是否小于等于“今天减 1”同时大于等于“今天减 3”两个条件都满足再执行SETBIT。多余校验不花什么成本但能挡住很多客户端异常。4.5 Key 数量多起来之后的内存与扫描Bitmaps 虽然单个 Key 很小但“每个用户每月一个 Key”意味着 Key 数量等于用户数乘以月数。100 万用户跑一年就是 1200 万个 Key单个实例可能开始出现内存碎片和慢扫描。排查时可以用redis-cli --bigkeys扫大键也可以查INFO memory看碎片率。如果 Key 数量已经大到影响运维考虑两个方向一是用 Redis Cluster 按用户哈希分散二是对超过一年以上的月度 Key 做归档压缩把历史月份的位数据转成紧凑字符串或者直接删除只保留年度汇总哈希。4.6 常见问题速查表现象可能原因检查手段 / 解法1 号签到查出来是 0偏移量用了 day 而不是 day-1统一走偏移量工具函数Redis 内存突然暴涨SETBIT 偏移量使用了时间戳/大数找出调用方校验偏移量范围BITCOUNT 结果明显偏大start/end 被当成位下标Redis 7 加BIT参数旧版用 mask连续签到少算一天没有处理跨月使用第 3.4 节的跨月函数月末报表数据缺失TTL 设置太短TTL 至少 180 天或归档汇总BITOP AND 结果不对mask 没覆盖到目标位段检查 mask key 的位偏移区间5. 从签到出发Bitmaps 的更多适用场景5.1 日活用户DAU统计一天一个 Key一个用户一个位Bitmaps 做 DAU 的思路和签到相反一个固定日期一个 Key用户 ID 当偏移量。用户当天访问就执行SETBIT dau:20260107 10001 1最后用BITCOUNT dau:20260107得到当天活跃用户数。这个方案的厉害之处在于1000 万用户一天的活跃标记只需要 1.25MB一个月 30 个 Key 也才 37.5MB。想算某个月的去重活跃用户数用BITOP OR把当月所有日 Key 合并一次再BITCOUNT几行命令就出了结果。这个需求在关系库里要是没有预先算好的汇总表跑起来非常痛苦。5.2 在线状态 / 活跃心跳在线状态也可以用 Bitmaps 管理比如online:20260107这个 Key用户上线时SETBIT 1下线时SETBIT 0查询某个用户是否在线就是GETBIT。但这个场景有一个明显短板Redis 的位没有“过期时间”你没法单独让某一个位在一分钟后自动归零。如果客户端异常退出没走到下线逻辑这个位会一直停留为 1在线人数就会虚高。我的处理办法是服务端收到任意请求时都重新SETBIT 1刷新该用户同时每天换一个新 Key旧 Key 设 TTL 自然过期。这样即使有脏位也只影响当天不会污染历史统计。5.3 功能开关与灰度放量Bitmaps 做灰度发布也很有意思。假设要给新首页做灰度Key 命名为feature:new_homepage用户 ID 直接当偏移量。先灰度 10% 用户就把偏移量小于总用户数 10% 的那批位全部置 1查询用户是否命中新版本只需要GETBIT feature:new_homepage userId。这种做法的好处是上线瞬间生效不需要等配置中心刷新灰度比例调整只需要继续SETBIT更多用户出问题想快速回滚把对应位改成 0 或者直接删 Key比改配置表快得多。而且和海量用户表拆 TPS 的逻辑完全隔离不会拖累主业务。5.4 一次性标记和长期防重凡是“用户是否做过某事”这种一次性判断也很适合 Bitmaps。比如某用户是否领取过新手奖励、是否参与过某个活动、是否跳过引导页。把不同事件映射成不同的 Key或者同一个 Key 里不同的位段就能把原本散落在多张表的标志位全部压进几个字节。这类标记通常没有严格的时效性所以 TTL 可以设长一点或者干脆不设。唯一注意的是 Key 命名要带业务前缀方便后续按前缀统一清理。最后补一个个人体会Bitmaps 不是银弹它的适用边界非常清晰——状态只有 0/1、数据关心的是“按月/按日”的窗口、能接受用位偏移量换内存和速度。真正把这套方案做好80% 的功夫都花在 Key 设计、偏移量约定、跨月边界这些不起眼的地方。我前期踩得最多的坑全在位数和下标错位上Redis 本身的命令反而没出过问题。如果你也在做签到、日活、灰度这类需求建议先把开头那 6 个命令打熟再把第 4.6 节那张速查表贴在工位旁边能帮你省掉不少值班电话。

相关新闻

Kafka Consumer Group与Rebalance机制深度解析

Kafka Consumer Group与Rebalance机制深度解析

1. 项目概述:为什么一个Consumer Group的“集体行动”比单个Consumer更重要?你有没有遇到过这样的场景:线上Kafka消费服务突然卡顿几秒,日志里刷出一连串Rebalancing、Revoked partitions、Assigned partitions,接着消…

2026/10/15 6:08:41 阅读更多 →
大模型本地部署显存预估与推理优化实战指南

大模型本地部署显存预估与推理优化实战指南

1. 这不是显卡参数表,而是一份“模型运行可行性诊断书”你手里的那张显卡,不是一块静态的硬件,而是一个动态的资源池——它每秒能搬运多少数据、能同时存下多少中间结果、能多快完成一次矩阵乘法,共同决定了它到底能不能把某个大模…

2026/10/15 6:08:41 阅读更多 →
Kafka Consumer与Partition分配关系深度解析

Kafka Consumer与Partition分配关系深度解析

1. 这个问题到底在问什么:从生产环境故障现场说起“kafka中consumer和partition的对应关系”——这短短十几个字,是我在某次凌晨三点的线上告警群里看到最多的一句话。当时某电商大促期间的订单履约服务突然延迟飙升,监控显示Consumer Group的…

2026/10/15 6:08:41 阅读更多 →

最新新闻

SpringBoot+Vue轻量级博客系统设计与实现

SpringBoot+Vue轻量级博客系统设计与实现

1. 项目概述:SpringBootVue轻量级博客系统设计去年帮学弟评审毕业设计时,发现市面上很多博客系统要么功能冗余,要么扩展性差。于是我们决定用SpringBootVue搭建一个轻量级但五脏俱全的在线创作社区。这个系统最核心的特点是采用前后端分离架构…

2026/10/15 6:55:51 阅读更多 →
正念与心流:10分钟呼吸练习,让专注成为生命底色

正念与心流:10分钟呼吸练习,让专注成为生命底色

1. 先说清楚:我们到底在谈什么你有没有过这样的时刻:明明手头有一件重要的事要做,却忍不住五分钟刷一次手机;开会时脑子飘到晚上吃什么;想读几页书,眼睛盯着一行字,心里却已经把明天的待办事项过…

2026/10/15 6:55:51 阅读更多 →
Oracle 数据实时入仓 Doris 和 StarRocks 怎么做?CDC、全量迁移与 5 种方案对比

Oracle 数据实时入仓 Doris 和 StarRocks 怎么做?CDC、全量迁移与 5 种方案对比

在很多企业系统中,Oracle 负责在线事务处理,Doris 或 StarRocks 负责报表、数据分析和实时数据服务。当订单、用户、支付和日志数据持续增长时,直接在 Oracle 上运行复杂统计 SQL,可能影响线上业务。因此,很多团队会建…

2026/10/15 6:55:51 阅读更多 →
SpringBoot+Vue+MyBatis构建企业级电商平台实战

SpringBoot+Vue+MyBatis构建企业级电商平台实战

1. 项目概述"企业级网购平台管理系统"是一个基于SpringBootVueMyBatis技术栈的完整电商解决方案。这套源码包含了电商平台的核心功能模块,采用前后端分离架构设计,数据库使用MySQL,适合快速构建中小型B2C或B2B电商平台。我在实际电…

2026/10/15 6:55:51 阅读更多 →
聚簇索引vs非聚簇索引:从底层原理到实战避坑全解析

聚簇索引vs非聚簇索引:从底层原理到实战避坑全解析

做后端开发这几年,索引相关的坑我踩过不少。面试被问过无数次“聚簇索引和非聚簇索引区别”,带新人的时候也发现,大部分同学对这两个词的理解停留在“一个有序一个无序”或者“聚簇索引就是主键”这种模糊层面。一旦落到实际业务,…

2026/10/15 6:55:51 阅读更多 →
盲盒商城软件开发案例:连接概率说明、微信支付、在线开赏与积分兑换

盲盒商城软件开发案例:连接概率说明、微信支付、在线开赏与积分兑换

盲盒商城的购买过程与普通商品商城有所不同。用户在付款前,需要了解盲盒价格、可抽取内容和相关规则;完成支付后,再进入开赏环节。商品展示、概率说明、支付结果和积分记录之间,需要形成清晰的操作顺序。 某公司的这套盲盒商城软件…

2026/10/15 6:54:51 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →