Redis 缓存穿透、缓存雪崩、缓存击穿情况解析及对应解决方案
目录一. 缓存穿透1.1 产生原因1.2 常见解决方案举例缓存空值布隆过滤器二. 缓存雪崩2.1 产生原因2.2 常见解决方案举例随机时间设置集群构建多级缓存三. 缓存击穿3.1 产生原因3.2 常见解决方案举例互斥锁逻辑过期一. 缓存穿透1.1 产生原因用户请求的数据在 Redis 和数据库都不存在并且大量线程重复不断的发送请求导致所有查询请求全部打到数据库造成巨大压力可能是恶意攻击(比如用户请求商品号为0的商品大概率不存在) 或 业务漏洞。1.2 常见解决方案举例缓存空值布隆过滤器方案一缓存空值示例代码如下优点实现逻辑简单方便维护缺点1缓存控制导致额外内存消耗少量 null 值缓存尚可若缓存大量 null 数据不合理2此外还可能导致短期数据不一致假设现在马上查询商品A数据库和缓存都没有数据缓存了 null 值有效期3分钟1分钟后数据库插入了有效数据商品A但未能及时删除或更新缓存那么接下来的两分钟数据库数据与缓存 null 数据就会出现数据不一致的情况也可以在INSERTUPDATE代码逻辑添加缓存同步解决此问题。Autowired private RedissonClient redissonClient; Autowired private StringRedisTemplate stringRedisTemplate; Autowired private ShopMapper shopMapper; public static final String SHOP_CACHE_PREFIX cache:shop:; public static final String NULL_VALUE ; public static final String LOCK_PREFIX lock:shop:; /** * 查询商户缓存击穿代码 * */ public Shop queryShopById(Long id) { // 1. 先组装 key 查询缓存 String key SHOP_CACHE_PREFIX id; String shopJson stringRedisTemplate.opsForValue().get(key); // 2. 判断缓存是否为空值,不为空则解析返回 if (StrUtil.isNotBlank(shopJson)){ return JSONUtil.toBean(shopJson, Shop.class); } // 3. 判断缓存是否为null不为null则说明查询到的是缓存的空字符串则返回 null if (shopJson ! null){ return null; } // 4. 缓存为null则查询数据库加互斥锁防止击穿所以先获取锁 String lockKey LOCK_PREFIX id; RLock lock redissonClient.getLock(lockKey); try { // 5. 先尝试加锁防止其他线程已经上锁, 这里设置 2s 尝试加锁10s 释放锁防止死锁 if(lock.tryLock(2,10, TimeUnit.SECONDS)){ // 6. 加锁成功先双重检查防止在此期间其他线程已经读取数据并写入缓存避免无效查询 shopJson stringRedisTemplate.opsForValue().get(key); // 7. 再次查询缓存判断缓存值与上面同样的逻辑先判断是否空值 if (StrUtil.isNotBlank(shopJson)){ return JSONUtil.toBean(shopJson, Shop.class); } if (shopJson ! null){ return null; } // 8. 缓存仍为空查询数据库 Shop shop shopMapper.selectById(id); // 9. 判断数据库返回值不为空写入缓存为空则缓存空值3分钟 if (shop ! null){ stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), 3, TimeUnit.MINUTES); } else { stringRedisTemplate.opsForValue().set(key, NULL_VALUE, 3, TimeUnit.MINUTES); } return shop; } else { // 获取锁失败略作等待后再次尝试从缓存获取 log.info(未能获取锁 id{}等待后重试读缓存, id); Thread.sleep(100); // 递归重试演示方便直接简单调用实际业务逻辑需添加重试次数 return queryShopById(id); } } catch (InterruptedException e) { log.info(获取锁失败 id{}请稍后重试, id); return null; } finally { // 释放锁,但需要判断锁是否是当前线程持有 if (lock.isHeldByCurrentThread()){ lock.unlock(); } } }方案二使用布隆过滤器布隆过滤器简单理解为在业务服务层做前置判断客户端请求 Redis 之前需要先由布隆过滤器判断当前数据 key 是否可能属于合法数据在缓存中是否存在布隆过滤器底层是由 BitMap 多个 hash 函数实现。bitmap 是一段二进制位数组每一位只有0或1。当一个 key 加入布隆过滤器时会被多个 hash 函数计算出多个下标然后把 bitmap 中这些位置都置为1。查询时再用同样的 hash 函数计算下标如果有任意一位是0说明这个 key 一定不存在如果所有位都是1只能说明它可能存在。向布隆过滤器加入数据会被多个哈希函数进行计算得到的指定位置的值会置为1当请求过来时经过哈希函数计算若指定位置的值为1则大概率说明该数据存在于布隆过滤器也存在于Redis所以说布隆过滤器的判断并非100%准确因为两个不同的值经过哈希函数之后可能会得到相同的结果比如数据A数据B经过哈希函数后结果都为3将id 3的值置为1若此时Redis中只缓存了数据A未缓存数据B但由于哈希计算之后得到的结果为3到id 3发现值为1初步判断数据B可能存在于缓存但是若某一处值始终为0则说明没有任何数据哈希计算后落于此处说明缓存中不可能存在此数据所以我们不难发现布隆过滤器的一个判断特点即若布隆过滤器认为此数据在Redis存在则此数据只是可能存在并非一定存在若布隆过滤器判断此数据在Redis一定不存在则一定不存在另外普通布隆过滤器不擅长删除数据因为多个元素可能共享同一个 bit 位如果业务需要删除可以考虑 Counting Bloom Filter 或重建过滤器。此外布隆过滤器的使用也可以搭配缓存空值方案一起使用可以进一步提高系统健壮性防止缓存穿透情况发生。布隆过滤器与 bitmap 的内在关联bitmap 是布隆过滤器的底层存储结构布隆过滤器是在 bitmap 之上叠加多 hash 映射和概率判断规则。普通 bitmap 更像“一个位置对应一个状态”而布隆过滤器是“一个元素映射到多个 bit 位”。补充方案除了上述做法之外还有以下部分补充方案供参考增加 id 复杂度防止被猜到id规律进行恶意攻击比如使用雪花算法做好参数的基础格式校验对于明显不是id参数的请求入参直接拦截加强用户权限校验部分接口及网站信息需要拥有相关权限才可访问做好热点参数的限流使用相关微服务限流组件如 SentinelHystrix二. 缓存雪崩2.1 产生原因大量缓存在同一时段同时过期或者缓存服务器宕机导致所有请求都打到数据库造成数据库压力过大甚至崩溃。2.2 常见解决方案举例随机时间设置集群构建多级缓存大量缓存同一时间过期常用且易于实现的方法就是在设置缓存的时候不设置一个固定的默认值而是设置一个TTL随机值防止集体过期方案一随机TTL过期时间防止大量缓存同时过期在上面的防止缓存穿透的代码基础上只需要将过期时间出的逻辑稍微做一下修改给不同的缓存添加随机TTL过期时间如下所示就完成了防止缓存穿透 缓存雪崩两大功能public static final String SHOP_CACHE_PREFIX cache:shop:; public static final String NULL_VALUE ; public static final String LOCK_PREFIX lock:shop:; /** * 查询商户 - 解决缓存穿透和缓存雪崩 * 缓存穿透通过互斥锁 空值缓存 * 缓存雪崩通过 TTL 随机化30-90秒避免大量缓存同时失效 */ public Shop queryShopById(Long id) { // 1. 先组装 key 查询缓存 String key SHOP_CACHE_PREFIX id; String shopJson stringRedisTemplate.opsForValue().get(key); // 2. 判断缓存是否为空值不为空则解析返回 if (StrUtil.isNotBlank(shopJson)) { return JSONUtil.toBean(shopJson, Shop.class); } // 3. 判断缓存是否为 null不为 null 则说明查询到的是缓存的空字符串则返回 null if (shopJson ! null) { return null; } // 4. 缓存为 null则查询数据库加互斥锁防止击穿所以先获取锁 String lockKey LOCK_PREFIX id; RLock lock redissonClient.getLock(lockKey); try { // 5. 先尝试加锁防止其他线程已经上锁, 这里设置 2s 尝试加锁10s 释放锁防止死锁 if (lock.tryLock(2, 10, TimeUnit.SECONDS)) { // 6. 加锁成功先双重检查防止在此期间其他线程已经读取数据并写入缓存避免无效查询 shopJson stringRedisTemplate.opsForValue().get(key); // 7. 再次查询缓存判断缓存值与上面同样的逻辑先判断是否空值 if (StrUtil.isNotBlank(shopJson)) { return JSONUtil.toBean(shopJson, Shop.class); } if (shopJson ! null) { return null; } // 8. 缓存仍为空查询数据库 Shop shop shopMapper.selectById(id); // 9. 判断数据库返回值使用随机 TTL 写入缓存 if (shop ! null) { // 缓存雪崩解决设置随机过期时间 60-180 秒1-3分钟也可以更长视具体业务场景而定这里只举例说明 long randomTtl generateRandomTtl(60, 180); stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), randomTtl, TimeUnit.SECONDS); log.debug(写入缓存成功key{}, TTL{}秒, key, randomTtl); } else { // 空值缓存也使用随机 TTL避免同时失效30-90秒 long randomTtl generateRandomTtl(30, 90); stringRedisTemplate.opsForValue().set(key, NULL_VALUE, randomTtl, TimeUnit.SECONDS); log.debug(写入空值缓存key{}, TTL{}秒, key, randomTtl); } return shop; } else { // 获取锁失败略作等待后再次尝试从缓存获取 log.info(未能获取锁 id{}等待后重试读缓存, id); Thread.sleep(100); // 递归重试演示方便直接简单调用实际业务逻辑需添加重试次数 return queryShopById(id); } } catch (InterruptedException e) { log.error(获取锁失败 id{}请稍后重试, id, e); Thread.currentThread().interrupt(); // 恢复中断状态 return null; } finally { // 释放锁但需要判断锁是否是当前线程持有 if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } /** * 生成随机 TTLTime To Live * param minSeconds 最小秒数 * param maxSeconds 最大秒数 * return 随机秒数 */ private long generateRandomTtl(int minSeconds, int maxSeconds) { // 使用 ThreadLocalRandom 提高性能避免并发冲突 return java.util.concurrent.ThreadLocalRandom.current().nextInt(minSeconds, maxSeconds 1); }方案二设置 Redis 集群防止 Redis 服务器宕机相比起大量缓存同时失效Redis 服务器宕机带来的问题则更加严重等于所有缓存全部失效为了防止此问题则可以设置 Redis 集群依赖于哨兵检测功能即使某一台Redis 服务器挂了其他 Redis 服务器依然可以正常对外提供服务但使用集群也会带来更多需要解决的其他问题如分布式锁Redis集群数据一致性等问题需要解决方案三构建多级缓存如 nginx 缓存不同层级的缓存相互配合可靠性更强此外还可以给缓存添加降级限流策略防止过高的并发量也能在线程出现问题时及时阻断防止影响整体业务三. 缓存击穿3.1 产生原因缓存中的热点数据 key 在某一时刻过期而恰好这时有大量并发请求过来由于缓存失效所有请求都去查数据库造成数据库压力瞬时增大其实和缓存穿透有些类似只是这个在数据库中确实存在数据只是缓存失效了而且在重新构建缓存的过程中可能由于数据量大或数据需要多表连接查询导致比较慢。会出现缓存真空期一旦出现高并发大量线程访问数据库可能导致崩溃3.2 常见解决方案举例互斥锁逻辑过期了解了缓存击穿的产生原因其实不难看出他完全也可以使用互斥锁的方式来解决只是相比于缓存穿透代码不考虑缓存空值不需要额外判断空值其余代码逻辑与上面的举例代码完全一样所以总的来说下面这段代码已经基本解决了缓存穿透、缓存雪崩、缓存击穿三个问题方案一互斥锁解决缓存击穿public static final String SHOP_CACHE_PREFIX cache:shop:; public static final String NULL_VALUE ; public static final String LOCK_PREFIX lock:shop:; /** * 查询商户 - 解决缓存穿透和缓存雪崩 * 缓存穿透通过互斥锁 空值缓存 * 缓存雪崩通过 TTL 随机化30-90秒避免大量缓存同时失效 */ public Shop queryShopById(Long id) { // 1. 先组装 key 查询缓存 String key SHOP_CACHE_PREFIX id; String shopJson stringRedisTemplate.opsForValue().get(key); // 2. 判断缓存是否为空值不为空则解析返回 if (StrUtil.isNotBlank(shopJson)) { return JSONUtil.toBean(shopJson, Shop.class); } // 3. 判断缓存是否为 null不为 null 则说明查询到的是缓存的空字符串则返回 null if (shopJson ! null) { return null; } // 4. 缓存为 null则查询数据库加互斥锁防止击穿所以先获取锁 String lockKey LOCK_PREFIX id; RLock lock redissonClient.getLock(lockKey); try { // 5. 先尝试加锁防止其他线程已经上锁, 这里设置 2s 尝试加锁10s 释放锁防止死锁 if (lock.tryLock(2, 10, TimeUnit.SECONDS)) { // 6. 加锁成功先双重检查防止上锁期间其他线程已经读取数据写入缓存并释放了锁避免无效查询 shopJson stringRedisTemplate.opsForValue().get(key); // 7. 再次查询缓存判断缓存值与上面同样的逻辑先判断是否空值 if (StrUtil.isNotBlank(shopJson)) { return JSONUtil.toBean(shopJson, Shop.class); } if (shopJson ! null) { return null; } // 8. 缓存仍为空查询数据库 Shop shop shopMapper.selectById(id); // 9. 判断数据库返回值使用随机 TTL 写入缓存 if (shop ! null) { // 缓存雪崩解决设置随机过期时间 60-180 秒1-3分钟也可以更长视具体业务场景而定这里只举例说明 long randomTtl generateRandomTtl(60, 180); stringRedisTemplate.opsForValue().set(key, JSONUtil.toJsonStr(shop), randomTtl, TimeUnit.SECONDS); log.debug(写入缓存成功key{}, TTL{}秒, key, randomTtl); } else { // 空值缓存也使用随机 TTL避免同时失效30-90秒 long randomTtl generateRandomTtl(30, 90); stringRedisTemplate.opsForValue().set(key, NULL_VALUE, randomTtl, TimeUnit.SECONDS); log.debug(写入空值缓存key{}, TTL{}秒, key, randomTtl); } return shop; } else { // 获取锁失败略作等待后再次尝试从缓存获取 log.info(未能获取锁 id{}等待后重试读缓存, id); Thread.sleep(100); // 递归重试演示方便直接简单调用实际业务逻辑需添加重试次数 return queryShopById(id); } } catch (InterruptedException e) { log.error(获取锁失败 id{}请稍后重试, id, e); Thread.currentThread().interrupt(); // 恢复中断状态 return null; } finally { // 释放锁但需要判断锁是否是当前线程持有 if (lock.isHeldByCurrentThread()) { lock.unlock(); } } } /** * 生成随机 TTLTime To Live * param minSeconds 最小秒数 * param maxSeconds 最大秒数 * return 随机秒数 */ private long generateRandomTtl(int minSeconds, int maxSeconds) { // 使用 ThreadLocalRandom 提高性能避免并发冲突 return java.util.concurrent.ThreadLocalRandom.current().nextInt(minSeconds, maxSeconds 1); }方案二设置逻辑过期时间异步线程更新缓存解决缓存击穿此方案也很好理解缓存的数据可以设置为永不过期或数天之后过期(一个较长的过期时间)但可以再额外设置一个逻辑过期时间。举个简单的例子假设今天中午1200线程A读取商品A到缓存中设置为永不过期但同时在缓存的数据中设置一个逻辑过期时间比如当前时间再加30分钟那么逻辑过期时间就是1230分假设过了过了30分钟之后1231分线程B获取商品A数据因为缓存永不过期所以可以读取到商品A数据同时也获取逻辑过期时间发现是1230分早于当前时间1231分说明此时获取的数据虽然没有缓存失效但从逻辑上来讲已经失效了已经是比较旧的数据了可能不是最新的所以再开辟一个新线程更新商品A缓存同时再设置一个30分钟的逻辑过期时间当前时间是1231分再添加30分钟逻辑过期时间那么下次的逻辑过期时间就是1301分若1301分之后又有新线程来访问商品A则重复此操作重新查询数据库刷新商品A的缓存。循环往复......示例代码逻辑如下a.首先需要对商品类重构可以创建一个公共的缓存数据类通过泛型控制具体数据类型再添加逻辑过期时间字段Data AllArgsConstructor NoArgsConstructor //我们给所有要放入缓存的数据对象都统一添加一个逻辑过期时间字段实际数据通过泛型进行控制即可 public class RedisDataT { /** * 逻辑过期时间 */ private LocalDateTime expireTime; /** * 实际数据 */ private T data; }b.添加新的常量和线程池// 逻辑过期时间30分钟 public static final long LOGIC_EXPIRE_MINUTES 30; // 缓存重建线程池 private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10);c.编写新的逻辑代码// 商品缓存层级前缀字符串 public static final String SHOP_CACHE_PREFIX cache:shop:; // 空字符串空缓存值 public static final String NULL_VALUE ; // 互斥锁前缀 public static final String LOCK_PREFIX lock:shop:; // 逻辑过期时间30分钟 public static final long LOGIC_EXPIRE_MINUTES 30; // 缓存重建线程池 private static final ExecutorService CACHE_REBUILD_EXECUTOR Executors.newFixedThreadPool(10); /** * 逻辑过期解决缓存击穿 */ public Shop queryShopById2(Long id) { // 1. 先组装 key 查询缓存 String key SHOP_CACHE_PREFIX id; String shopJson stringRedisTemplate.opsForValue().get(key); // 2. 判断缓存是否为空值为空直接返回 null if (StrUtil.isBlank(shopJson)) { return null; } // 3. 缓存不为空则解析数据序列化为对象 RedisDataShop shopRedisData JSONUtil.toBean(shopJson, RedisData.class); // 4. 序列化后获取逻辑过期时间判断当前数据是否已经逻辑过期 // 4.1若未过期直接返回解析后的数据即可 LocalDateTime expireTime shopRedisData.getExpireTime(); if (expireTime.isAfter(LocalDateTime.now())){ return shopRedisData.getData(); } // 4.2若已逻辑过期则开辟新线程重建缓存但当前缓存仍然返回旧数据开辟新线程使用互斥锁同一时刻只允许一个线程重建缓存 String lockKey LOCK_PREFIX id; RLock lock redissonClient.getLock(lockKey); boolean isLock lock.tryLock(); if (isLock) { // 如果加锁成功则开启新线程重建缓存使用线程池线程 CACHE_REBUILD_EXECUTOR.submit(() - { // 为确保锁最终能被释放要对当前重建缓存线程添加 try...catch...finally... try { // 查询商品数据 Shop shop shopMapper.selectById(id); // 封装逻辑过期时间30分钟 RedisDataShop redisData new RedisData(LocalDateTime.now().plusMinutes(LOGIC_EXPIRE_MINUTES), shop); // 重建商品缓存 stringRedisTemplate.opsForValue().set(SHOP_CACHE_PREFIX id, JSONUtil.toJsonStr(redisData)); } catch (Exception e){ log.error(重建缓存失败{}, e.getMessage()); throw new RuntimeException(e); } finally { // 释放锁 lock.unlock(); if (isLock lock.isHeldByCurrentThread()) { lock.unlock(); } } }); } // 如果加锁失败说明已经存在线程重建缓存则直接返回旧数据 return shopRedisData.getData(); }OK通过上述两个不同的方案我们可以得出以下结论解决方案优点缺点互斥锁1没有额外内存消耗2互斥锁保证数据一致性3实现相对简单1由于是互斥锁线程需要等待性能受到一定影响2在庞大复杂的业务中可能会存在其它业务锁可能存在死锁风险逻辑过期线程无需等待性能较好1不保证数据一致性高并发情况下若未获取到锁线程会返回旧数据2有额外内存消耗3使用了线程池及逻辑过期实现相比互斥锁更复杂在实际业务中需要考虑的则会更多更复杂

相关新闻

人形机器人横向测评:硬件拆解、软件智能与协同应用全解析

人形机器人横向测评:硬件拆解、软件智能与协同应用全解析

1. 项目概述:一次深度的人形机器人“全都要”体验最近在科技圈和社交媒体上,人形机器人又掀起了一波不小的讨论热潮。作为一个长期关注前沿科技动态的从业者,我经常被问到:“现在市面上这么多款人形机器人,到底哪一款最…

2026/7/18 5:58:14 阅读更多 →
SteamOS 3.8.10更新解析:硬件支持与性能优化

SteamOS 3.8.10更新解析:硬件支持与性能优化

1. SteamOS 3.8.10更新深度解析Valve近日正式推送了SteamOS 3.8.10稳定版更新,这次升级最引人注目的变化是加入了对新一代Steam Machine的初步支持。作为专为游戏优化的Linux发行版,SteamOS正在逐步完善其硬件生态体系。我在Steam Deck上实测发现&#x…

2026/7/18 5:58:14 阅读更多 →
PC+RK3588连板在线调试模型推理

PC+RK3588连板在线调试模型推理

1 环境搭建 1.1 PC 端环境搭建 包下载地址为:https://github.com/airockchip/rknn-toolkit2.git。此外,RK 官方也针对部分模型给出了相关部署例子,其工具库名为 rknn_model_zoo,下载地址为:https://github.com/airockc…

2026/7/18 5:58:14 阅读更多 →

最新新闻

嵌入式网络协议栈开发实战与优化技巧

嵌入式网络协议栈开发实战与优化技巧

1. 为什么嵌入式工程师需要掌握网络协议栈在STM32H7这类高性能MCU上实现网络功能,网络协议栈是绕不开的核心技术。作为从传统单片机转型到网络嵌入式开发的工程师,我最初对TCP/IP协议栈的理解仅限于"能联网"的层面,直到在实际项目中…

2026/7/18 6:44:36 阅读更多 →
AR桌面Launcher开发:三维空间交互与优化实践

AR桌面Launcher开发:三维空间交互与优化实践

1. AR桌面(Launcher)项目背景与需求分析2023年12月28日这个时间节点,恰好是AR技术从专业领域向消费级市场渗透的关键时期。我在实际开发中发现,传统手机Launcher已经无法满足用户对空间交互的需求——当人们开始习惯通过AR眼镜浏览信息时,平面…

2026/7/18 6:44:36 阅读更多 →
如何在ComfyUI中部署WanVideo FP8优化模型:实战指南与深度解析[特殊字符]

如何在ComfyUI中部署WanVideo FP8优化模型:实战指南与深度解析[特殊字符]

如何在ComfyUI中部署WanVideo FP8优化模型:实战指南与深度解析🚀 【免费下载链接】WanVideo_comfy_fp8_scaled 项目地址: https://ai.gitcode.com/hf_mirrors/Kijai/WanVideo_comfy_fp8_scaled WanVideo FP8优化模型系列代表了当前AI视频生成领域…

2026/7/18 6:44:36 阅读更多 →
Langchain.js智能体架构与openclaw引擎实战指南

Langchain.js智能体架构与openclaw引擎实战指南

在实际前端架构和 AI 应用开发中,直接调用大模型 API 往往只能完成单轮问答。真正需要解决的是多步骤任务编排、工具调用、状态管理和错误恢复——这正是 AI 智能体(AI Agent)要处理的核心问题。Langchain.js 作为 JavaScript/TypeScript 生态…

2026/7/18 6:44:36 阅读更多 →
Processing图形渲染架构深度解析:从PGraphics到PShape的硬件协同实现

Processing图形渲染架构深度解析:从PGraphics到PShape的硬件协同实现

Processing图形渲染架构深度解析:从PGraphics到PShape的硬件协同实现 【免费下载链接】processing ⚠️ Processing moved to processing/processing4 ⚠️ 项目地址: https://gitcode.com/gh_mirrors/processing3/processing Processing作为创意编程领域的核…

2026/7/18 6:44:36 阅读更多 →
基于《痴迷》电影主题的情感分析工具部署与实战指南

基于《痴迷》电影主题的情感分析工具部署与实战指南

这次我们来看一个很有意思的项目——基于《痴迷》电影主题的情感分析工具。这个开源项目能够对文本中的情感倾向进行深度分析,特别擅长识别"痴迷""诅咒"等强烈情感表达。对于内容创作者、影视评论分析、情感计算研究来说,这是个很实…

2026/7/18 6:43:35 阅读更多 →

日新闻

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则

更多请点击: https://kaifayun.com 第一章:从模糊意图到可执行指令:Claude PRD中Prompt Engineering与需求颗粒度的5级映射法则 在Claude驱动的产品需求文档(PRD)生成实践中,原始业务意图往往以自然语言片…

2026/7/18 0:00:38 阅读更多 →
Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

Cursor配置生成失效?3大隐藏陷阱+4行修复代码,资深工程师连夜整理的紧急补救清单

更多请点击: https://codechina.net 第一章:Cursor配置生成失效?3大隐藏陷阱4行修复代码,资深工程师连夜整理的紧急补救清单 Cursor 配置生成突然失效,是近期高频报障场景。表面看是 cursor.config.json 未更新或 LSP…

2026/7/18 0:00:38 阅读更多 →
某智驾大牛创业

某智驾大牛创业

作者:钟声编辑:Mark出品:红色星际头图:智能驾驶图片据悉,国内某头部智驾公司端到端模型技术大牛Z投身创业,并且已经拿到融资。Z不仅是该头部公司内部最年轻的对标阿里P10级别技术负责⼈,更是业内…

2026/7/18 0:00:38 阅读更多 →

周新闻

月新闻