LRU缓存命中率暴跌?LIRS用复用距离替代访问时间,抗顺序扫描
1. 从一次缓存命中率暴跌说起LRU 到底哪里不够用做过服务端开发的人大概率都经历过这样的场景某个接口平时响应时间稳定在几毫秒某天突然开始间歇性抖动P99 延迟从 8ms 飙到 200ms 以上查了半天数据库、网络、GC 都没问题最后定位到缓存命中率从 92% 掉到了 61%。把缓存淘汰策略从 LRU 换成 LIRS 之后命中率回到 89%延迟也跟着恢复正常。这不是玄学而是访问模式本身在惩罚LRU。LRULeast Recently Used最近最少使用的核心假设是如果一个数据最近被访问过那么它未来被再次访问的概率也更高。这个假设在大多数场景下成立所以 LRU 成了最通用的缓存淘汰策略从操作系统的页缓存到 Redis 的近似 LRU再到各种本地缓存库到处都是它的身影。但问题在于大多数场景不等于所有场景有一类访问模式会让 LRU 的表现急剧退化甚至退化到接近随机淘汰的水平。这类模式就是弱局部性访问模式典型代表是顺序扫描和偶发冷数据访问。举个具体的例子假设缓存容量是 100 个条目现在有一个顺序扫描操作依次读取 200 个不重复的数据块。LRU 会把前 100 个块全部淘汰掉换成后 100 个块。如果这 200 个块里其实有 80 个是热点数据只是被顺序扫描顺带读了一遍那这 80 个热点数据就被无辜地挤出去了。等真正的业务请求再来访问这些热点数据时全部缓存未命中只能回源查数据库。这就是所谓的缓存污染Cache Pollution。LIRSLow Inter-reference Recency Set就是专门为解决这个问题而设计的。它的核心思想不是看最近有没有被访问而是看两次访问之间的间隔有多长。间隔短的叫高复用距离High Reuse间隔长的叫低复用距离Low Reuse。LIRS 优先保留那些复用距离短的数据即使它们最近没有被访问过同时允许复用距离长的数据在缓存里短暂停留但不让它们污染核心缓存区。这篇文章会从 LRU 的失效场景讲起把 LIRS 的核心机制拆开揉碎然后给出一个可运行的 Python 实现最后聊聊在实际项目中怎么选型、怎么调参、怎么避坑。不管你是做后端服务、数据库内核还是嵌入式存储只要涉及缓存淘汰这篇内容都能给你一些可以直接抄作业的思路。2. LRU 在顺序扫描下的失效链路一次完整的命中率崩塌复盘2.1 用一个小实验把问题复现出来光说理论不够直观我写了一段模拟代码用两种访问模式对比 LRU 和 LIRS 的命中率差异。先看 LRU 的实现用 Python 的 OrderedDict 就能搞定from collections import OrderedDict class LRUCache: def __init__(self, capacity): self.capacity capacity self.cache OrderedDict() self.hits 0 self.misses 0 def access(self, key): if key in self.cache: self.hits 1 self.cache.move_to_end(key) return True self.misses 1 if len(self.cache) self.capacity: self.cache.popitem(lastFalse) self.cache[key] True return False def hit_rate(self): total self.hits self.misses return self.hits / total if total else 0.0然后构造一个混合访问序列80 个热点数据编号 0-79被反复访问中间穿插一次顺序扫描编号 1000-1199缓存容量设为 100。访问序列大概是这样的import random def generate_workload(): workload [] # 热点数据反复访问 for _ in range(2000): workload.append(random.randint(0, 79)) # 中间插入一次顺序扫描 for i in range(1000, 1200): workload.append(i) # 继续访问热点数据 for _ in range(2000): workload.append(random.randint(0, 79)) return workload跑下来 LRU 的命中率大概在 78% 左右而如果去掉中间那次顺序扫描命中率能到 95% 以上。也就是说一次顺序扫描直接把命中率拉低了 17 个百分点。这个差距在真实系统里就是数据库 QPS 翻倍、响应时间翻倍的差别。2.2 为什么 LRU 会被一次性数据带偏LRU 的淘汰逻辑是最近最久未使用的先走它隐含了一个假设访问时间越近未来被访问的概率越大。这个假设在强局部性场景下没问题比如热点数据被反复访问LRU 能很好地保留它们。但顺序扫描的数据有一个特点每个数据只被访问一次之后再也不用了。这些数据在 LRU 链表里会不断往头部挤把真正的热点数据往尾部推最终挤出缓存。更麻烦的是LRU 对访问频率完全不敏感。一个数据被访问了 1000 次另一个数据只被访问了 1 次只要后者比前者更晚被访问LRU 就会优先淘汰前者。这在访问模式稳定的时候问题不大但一旦出现突发性的冷数据访问LRU 就会做出错误的淘汰决策。我用一个更极端的例子来说明缓存容量 10访问序列是1,2,3,4,5,6,7,8,9,10,11,1,2,3,4,5。前 10 次访问把缓存填满第 11 次访问淘汰 1然后访问 1 时未命中淘汰 2访问 2 时未命中……最终 1-5 全部未命中。如果缓存容量是 11这 5 次访问就全部命中。这就是 LRU 的顺序扫描退化缓存容量刚好比工作集小一点的时候命中率会断崖式下跌。2.3 命中率崩塌的完整排查链路在实际项目里遇到缓存命中率暴跌我一般按这个顺序排查先看监控曲线命中率是缓慢下降还是断崖式下跌缓慢下降通常是工作集增长断崖式下跌通常是出现了新的访问模式。再看访问日志抽样最近 10 分钟的缓存访问记录统计 key 的访问频次分布。如果出现大量只访问一次的 key基本可以确定是顺序扫描或冷数据批量导入。定位来源根据 key 的前缀或业务标识找到是哪个接口或哪个任务在批量访问。常见的有离线任务全表扫描、运营后台导出数据、新用户首次登录加载全量配置。验证假设临时把这些批量访问的 key 排除掉看命中率是否恢复。如果恢复说明就是缓存污染。选择方案要么在业务层隔离批量访问走独立缓存或直接回源要么在缓存层换淘汰策略LRU 换 LIRS 或 ARC。这个排查链路我走过好几次最坑的一次是某个离线任务每小时跑一次全量扫描每次跑完缓存命中率要花 20 分钟才能恢复。后来把离线任务的缓存单独隔离问题就解决了。但如果隔离成本太高换 LIRS 就是更优雅的方案。3. LIRS 的核心机制用复用距离替代访问时间3.1 复用距离LIRS 的度量衡LIRS 的核心概念是复用距离Reuse Distance定义是同一个数据块两次连续访问之间访问了多少个不同的数据块。举个例子访问序列是A, B, C, AA 的复用距离就是 2中间隔了 B 和 C。复用距离越短说明这个数据被访问得越频繁越应该留在缓存里。LIRS 把数据分成两类LIRLow Inter-reference Recency复用距离短的数据是缓存的核心保留对象。HIRHigh Inter-reference Recency复用距离长的数据是缓存的临时住户。LIRS 的缓存空间被划分为两部分LIR 区通常占 99% 左右和 HIR 区占 1% 左右。LIR 区的数据是铁定保留的HIR 区的数据是随时可淘汰的。当 HIR 区的数据被再次访问时如果它的复用距离足够短就会被提升为 LIR同时把 LIR 区里复用距离最长的数据降级为 HIR。这个机制的精妙之处在于顺序扫描的数据只会进入 HIR 区不会污染 LIR 区。因为顺序扫描的数据复用距离是无穷大只访问一次它们只能在 HIR 区里短暂停留很快就被淘汰。而热点数据因为复用距离短会被提升到 LIR 区得到保护。3.2 LIRS 栈怎么在有限空间里追踪复用距离理论上要精确计算复用距离需要记录每个数据块的所有历史访问记录空间开销太大。LIRS 用了一个巧妙的近似方法维护一个LIRS 栈栈里只保留最近访问的数据块栈顶是最近访问的栈底是最久未访问的。当一个数据块被访问时它在栈里的位置就反映了它的复用距离——位置越靠近栈顶复用距离越短。但 LIRS 栈不能无限大否则空间开销还是太高。实际实现里LIRS 栈的大小通常是缓存容量的数倍比如 3-5 倍只保留最近访问的数据块。栈里不在缓存中的数据块只记录它们的状态是 LIR 还是 HIR不记录实际数据。这里有一个关键细节LIRS 栈里同时包含 LIR 和 HIR 数据块但只有 LIR 数据块会被锁定在栈里。当一个 HIR 数据块从栈里被挤出时如果它还在缓存里就会被淘汰如果它已经不在缓存里就只是从栈里移除。这个机制保证了 LIR 数据块的复用距离信息不会被 HIR 数据块冲掉。3.3 LIR 与 HIR 的动态转换什么时候提升什么时候降级LIRS 的动态转换规则是整套机制里最需要理解清楚的部分。我把它拆成几个场景场景一访问一个不在缓存里的数据块如果缓存没满直接放入 HIR 区。如果缓存满了淘汰 HIR 区里最久未访问的数据块把新数据块放入 HIR 区。如果新数据块在 LIRS 栈里的位置足够靠前复用距离短把它提升为 LIR同时把 LIR 区里栈位置最靠后的数据块降级为 HIR。场景二访问一个在缓存里的 HIR 数据块如果它在 LIRS 栈里的位置足够靠前提升为 LIR同时降级一个 LIR 数据块。如果位置不够靠前保持在 HIR 区但更新它在栈里的位置。场景三访问一个在缓存里的 LIR 数据块直接命中更新它在 LIRS 栈里的位置。这套规则的核心逻辑是LIR 区的容量是固定的HIR 区的数据要竞争才能进入 LIR 区。竞争的标准就是复用距离复用距离短的数据胜出。这样就避免了 LRU 那种谁最近被访问谁就留下的盲目性。4. 手写一个可运行的 LIRS 缓存从数据结构到调参4.1 数据结构选型为什么用双向链表加字典实现 LIRS 需要几个核心数据结构LIRS 栈用双向链表实现支持 O(1) 的插入、删除、移动操作。栈里存储数据块的 key 和状态LIR/HIR。缓存区用字典实现key 到实际数据的映射。LIR 区和 HIR 区分别用两个字典或一个字典加状态标记。栈位置索引用字典记录每个 key 在 LIRS 栈里的节点引用方便 O(1) 定位。这里有一个容易踩的坑LIRS 栈里可能包含不在缓存里的数据块。因为栈的大小比缓存大有些数据块已经被淘汰出缓存了但还在栈里保留着复用距离信息。所以栈节点和缓存条目是两套独立的生命周期不能混在一起管理。4.2 核心操作的伪代码与 Python 实现先看访问操作的完整逻辑class LIRSCache: def __init__(self, capacity, stack_ratio3): self.capacity capacity self.lir_capacity max(1, int(capacity * 0.99)) self.hir_capacity capacity - self.lir_capacity self.stack_size capacity * stack_ratio self.cache {} # key - data self.key_status {} # key - LIR or HIR self.stack OrderedDict() # key - None, 栈顶在末尾 self.hits 0 self.misses 0 def _update_stack(self, key): if key in self.stack: self.stack.move_to_end(key) else: self.stack[key] None if len(self.stack) self.stack_size: self.stack.popitem(lastFalse) def _evict_hir(self): for k in list(self.stack.keys()): if self.key_status.get(k) HIR and k in self.cache: del self.cache[k] del self.key_status[k] return k return None def _demote_lir(self): for k in list(self.stack.keys()): if self.key_status.get(k) LIR: self.key_status[k] HIR return k return None def access(self, key, dataNone): if key in self.cache: self.hits 1 self._update_stack(key) if self.key_status[key] HIR: # 检查是否提升为 LIR stack_pos list(self.stack.keys()).index(key) if stack_pos len(self.stack) - self.lir_capacity: self.key_status[key] LIR self._demote_lir() return self.cache[key] self.misses 1 self._update_stack(key) if len(self.cache) self.capacity: self._evict_hir() self.cache[key] data self.key_status[key] HIR return data这段代码是简化版实际生产环境还需要处理并发、过期时间、统计指标等。但核心逻辑已经完整了访问时更新栈位置HIR 数据块根据栈位置决定是否提升缓存满时优先淘汰 HIR 数据块。4.3 参数调优LIR 比例和栈大小怎么定LIRS 有两个关键参数LIR 区比例和LIRS 栈大小。LIR 区比例默认是 99%这个值在大多数场景下都合适。如果访问模式里热点数据占比很高比如 90% 以上的访问都集中在 10% 的数据上可以适当降低 LIR 比例到 95%给 HIR 区更多空间减少提升/降级的频率。如果访问模式比较均匀热点数据占比不高可以保持 99% 甚至提高到 99.5%。LIRS 栈大小默认是缓存容量的 3 倍。栈越大复用距离的估计越准确但空间开销也越大。实测下来3 倍是一个比较平衡的值。如果内存非常紧张可以降到 2 倍命中率会下降 1-2 个百分点。如果内存充裕可以提到 5 倍命中率提升不明显但栈操作的延迟会略微增加。这里有一个经验值LIRS 栈大小不要超过缓存容量的 10 倍否则栈操作本身的开销会抵消命中率带来的收益。另外栈大小最好是缓存容量的整数倍方便做内存预分配。5. LIRS 与 LRU、ARC、LFU 的选型对比什么场景该用哪个5.1 四种策略的横向对比策略核心思想优点缺点适用场景LRU最近最少使用实现简单强局部性场景命中率高顺序扫描下退化严重访问模式稳定的热点缓存LFU最少使用频率对频率敏感抗扫描频率统计开销大新数据难进入访问频率差异大的场景ARC自适应调整 LRU 和 LFU 比例自适应综合表现好实现复杂参数多访问模式多变的通用场景LIRS复用距离抗扫描命中率高实现复杂栈开销大有顺序扫描的混合访问场景从实测数据看在纯热点访问场景下LRU 和 LIRS 的命中率差不多都在 95% 以上。但在混合了顺序扫描的场景下LRU 命中率掉到 78%LIRS 还能保持 89%ARC 大概在 86% 左右。如果顺序扫描占比更高比如 30% 的访问是扫描LRU 会掉到 60% 以下LIRS 还能维持在 82% 左右。5.2 选型决策树三步确定用哪个第一步看访问模式。如果访问模式非常稳定热点数据固定LRU 就够了没必要上 LIRS。如果访问模式里有明显的顺序扫描或冷数据批量访问优先考虑 LIRS 或 ARC。第二步看实现成本。LRU 用现成的库就行LIRS 需要自己实现或找第三方库。如果团队没有精力维护复杂的缓存逻辑ARC 是更稳妥的选择它的自适应机制能覆盖大多数场景。第三步看内存预算。LIRS 的栈需要额外内存通常是缓存容量的 3 倍。如果内存非常紧张LFU 的计数开销可能更小但 LFU 需要定期衰减频率计数否则新数据永远进不来。我个人的经验是如果缓存命中率对业务影响很大比如直接影响 QPS 和延迟而且访问模式里有扫描直接上 LIRS。如果只是普通的本地缓存LRU 足够。ARC 适合那种不确定访问模式会不会变的场景它的自适应机制能兜底。5.3 一个真实的选型翻车案例之前有个项目缓存用的是 LRU平时命中率 90% 左右。后来加了一个新功能每天凌晨跑一次全量数据同步同步过程中会顺序读取所有数据。结果每天凌晨缓存命中率掉到 50% 以下持续 30 分钟。一开始想用 LIRS 解决但评估后发现 LIRS 的栈开销太大这个服务的缓存条目有上千万栈内存扛不住。最后用的方案是缓存隔离全量同步走独立的缓存实例和在线业务的缓存物理隔离。同步完成后独立缓存直接销毁。这样在线业务的缓存完全不受影响命中率稳定在 90% 以上。这个案例说明换淘汰策略不是唯一解业务层隔离有时候成本更低。6. 落地 LIRS 时的五个坑从栈溢出到并发安全6.1 栈溢出LIRS 栈不是越大越好LIRS 栈的大小直接决定了内存开销。我见过一个实现栈大小设成了缓存容量的 10 倍结果缓存本身占 1GB栈又占了 10GB直接把服务撑爆了。栈里每个节点至少需要存储 key 和前后指针如果 key 是字符串开销更大。正确的做法是先估算缓存条目的平均 key 大小再乘以栈大小得到栈的内存开销。如果栈开销超过缓存本身的 50%就要考虑降低栈大小或者改用 ARC 这种不需要额外栈的策略。另外栈里可以只存 key 的哈希值而不是完整 key这样能省不少内存但会有哈希冲突的风险需要额外处理。6.2 并发安全读写锁的粒度怎么控制LIRS 的访问操作会修改栈和缓存区必须加锁。但锁的粒度很关键如果整个缓存一把大锁高并发下会成为瓶颈如果每个条目一把锁又会有死锁风险。我的做法是分段锁把缓存分成 N 个段每个段独立加锁。访问时根据 key 的哈希值定位到段只锁这个段。段的数量通常是 CPU 核数的 2-4 倍。这样既能保证并发性能又能避免死锁。需要注意的是LIRS 栈的更新操作可能涉及跨段的数据块比如提升 LIR 时需要降级另一个段里的 LIR这时候需要按固定顺序加锁避免死锁。6.3 命中率统计别被平均值骗了命中率是一个平均值指标它会把不同时间段的命中率平均掉。如果缓存命中率是 85%但其中 80% 的时间是 95%20% 的时间是 30%那这个 85% 就有很大的误导性。我在监控里会同时看命中率的 P50、P95、P99以及命中率的滑动窗口曲线。另外要区分全局命中率和热点数据命中率。全局命中率可能被大量冷数据访问拉低但热点数据的命中率才是业务真正关心的。我通常会把访问频次前 10% 的 key 单独统计命中率这个指标更能反映缓存的实际效果。6.4 冷启动新服务上线时怎么快速预热LIRS 在冷启动时表现不如 LRU因为它的 LIR 区需要时间才能学习到哪些是热点数据。新服务刚上线时缓存是空的所有数据都进 HIR 区命中率会很低。预热的方法有两种一是离线预热从历史访问日志里提取热点 key服务启动时批量加载二是在线预热服务启动后先放少量流量进来让 LIRS 自己学习等命中率稳定后再逐步加大流量。我一般用离线预热从过去 7 天的访问日志里提取访问频次前 20% 的 key启动时加载到缓存里。这样冷启动时间能从 30 分钟缩短到 5 分钟以内。6.5 数据一致性淘汰和更新的顺序问题LIRS 淘汰数据时如果数据正在被更新可能会出现淘汰了旧数据但新数据还没写入的空窗期。这个空窗期里其他请求访问这个 key 会缓存未命中回源查到旧数据又写回缓存导致数据不一致。解决方法是淘汰和更新加同一把锁或者用版本号机制每个缓存条目带一个版本号更新时版本号加一淘汰时检查版本号是否变化。如果变化了说明数据已经被更新不能直接淘汰。这个机制会增加一些开销但在数据一致性要求高的场景下是必要的。7. 从 LIRS 到自适应缓存后续可以怎么扩展LIRS 解决了 LRU 在顺序扫描下的退化问题但它本身也有局限LIR 区比例是固定的不能根据访问模式动态调整。如果访问模式发生变化比如热点数据突然变多固定的 LIR 比例可能不是最优的。一个自然的扩展方向是自适应 LIRS根据命中率和访问模式的变化动态调整 LIR 区比例。比如命中率下降时增大 LIR 区比例保护更多热点数据命中率稳定时减小 LIR 区比例给 HIR 区更多空间。这个思路和 ARC 的自适应机制类似但 ARC 调整的是 LRU 和 LFU 的比例自适应 LIRS 调整的是 LIR 和 HIR 的比例。另一个方向是分层 LIRS把缓存分成多层每层用不同的 LIR 比例。热数据层用高 LIR 比例冷数据层用低 LIR 比例。访问时先查热数据层未命中再查冷数据层。这样既能保护热点数据又能利用冷数据的复用距离信息。这个思路在 CPU 缓存里已经有类似的设计多级缓存搬到应用层缓存也是可行的。我在实际项目里试过自适应 LIRS实现复杂度比固定 LIRS 高不少但命中率在访问模式变化时确实更稳定。如果你们的业务访问模式经常变化可以考虑这个方向。如果访问模式比较稳定固定 LIRS 就够了没必要过度设计。最后分享一个我在调参时的小技巧先用 LRU 跑一周收集访问日志离线模拟 LIRS 的命中率。如果模拟下来 LIRS 比 LRU 高 5 个百分点以上再考虑上线 LIRS如果差距不大说明访问模式里扫描占比不高LRU 就够了。这样能避免盲目上线复杂策略带来的维护成本。

相关新闻

内斗学概论:17、内斗的阶段

内斗学概论:17、内斗的阶段

内斗也是分阶段的。就某事而言:酝酿、挑起、战斗、结束,然后等下次内斗。就公司而言:团伙的形成,团伙间的战斗,战败团伙的消失和战胜团伙的分裂,然后等下次内斗。

2026/10/11 0:29:20 阅读更多 →
内斗学概论:16、怎样简单判断哪方是坏的

内斗学概论:16、怎样简单判断哪方是坏的

好坏是相对的,又是绝对的。内斗双方自然存在好坏。那么怎样快速简单的判断好坏呢?一般来说,有这么几条:急功近利的。主动挑起的。说的特别好听的。对外软弱无能的。不干活的。

2026/10/9 22:57:29 阅读更多 →
第 34 章 · 性能优化与别名陷阱

第 34 章 · 性能优化与别名陷阱

这一章能帮你少踩 Eigen 最经典的坑:别名问题、auto 陷阱,以及一系列性能优化技巧。34.1 别名问题:左右两边共用内存 别名(aliasing):赋值语句左右两边引用同一块内存时,可能"边读边写&quo…

2026/10/11 1:03:07 阅读更多 →

最新新闻

基于 Raft 协议的强一致分布式锁选型:Etcd vs Redis 在金融级场景下的对比

基于 Raft 协议的强一致分布式锁选型:Etcd vs Redis 在金融级场景下的对比

在分布式锁的选型会议上,架构师们经常会面对两派激烈的技术争吵: 一派是“性能实用主义者”,他们力挺 Redis:“Redisson 封装完备,单机吞吐破 10 万 QPS,看门狗自动续期极其优雅,全网普及度最高…

2026/10/11 1:52:42 阅读更多 →
会务信息载体的演进:纸质、PDF 与结构化数据源的分发成本与版本一致性

会务信息载体的演进:纸质、PDF 与结构化数据源的分发成本与版本一致性

会务信息管理的本质问题,和很多分布式系统面对的问题很像:一份数据要在多个地方、多个时间点被多个人正确读到,而这期间数据本身还会变。会议这个场景把这个问题放大了。它一次性、不可回滚,所有读者集中在同一时间出现&#xff0…

2026/10/11 1:52:42 阅读更多 →
3Blue1Brown的手写数字图像识别实验复现

3Blue1Brown的手写数字图像识别实验复现

深度学习框架这里用到的是Pytorch。一、加载数据(一)import部分导入一些我们需要的库:import torch from torch import nn #包括sigmoid() linear()等宝藏函数捏 from torch.utils.data import DataLoader #数据集加载器,主要是为…

2026/10/11 1:52:42 阅读更多 →
JavaScript 的原型与继承——对象之间是怎么扯上关系的

JavaScript 的原型与继承——对象之间是怎么扯上关系的

引言如果说作用域和闭包是 JS 的"空间"问题,那原型和继承就是 JS 的"血缘"问题。JS 没有传统面向对象语言里的类继承体系,它用的是另一套逻辑:原型链。这套逻辑让很多人初学时一头雾水,但一旦想通&#xff0c…

2026/10/11 1:52:42 阅读更多 →
枚举类型全解析:从代码可读性到状态机与设备枚举的编程之道

枚举类型全解析:从代码可读性到状态机与设备枚举的编程之道

枚举(enum)类型算是编程里最被低估的关键字了。很多人一提到 enum 就只想到“给数字起名字”,觉得它无非是让type 1变成type TYPE_A,值没变,只是顺眼了一点。我早先也这么觉得,直到后来在业务代码、算法题…

2026/10/11 1:52:42 阅读更多 →
WPF贝塞尔曲线绘制平滑折线图实战指南

WPF贝塞尔曲线绘制平滑折线图实战指南

简介:本资源是一个基于WPF与C#实现的贝塞尔曲线动态折线图可视化项目,面向.NET桌面开发初学者及图形学实践者,解决传统折线图缺乏平滑过渡与动态量程适配的问题。项目完整封装为RAR压缩包(65KB),共36个文件…

2026/10/11 1:51:41 阅读更多 →

日新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

周新闻

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

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

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

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

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

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

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

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

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

2026/10/11 0:00:27 阅读更多 →

月新闻

我发现了一个新思路:用 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/10 5:23:50 阅读更多 →
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/9 21:32:20 阅读更多 →
黑夜航拍船只数据集训练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/10 10:38:42 阅读更多 →