尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Redis分布式锁从SETNX到Redisson看门狗:原理、坑与实战
1. 项目背景单体锁失效之后分布式系统靠什么兜底先别急着看代码。所有分布式锁的文章都会直接甩出SETNX、Redisson、看门狗这些词但很少有人认真聊聊为什么单机版的synchronized和Lock到了分布式环境就不好使了。我在早期做电商库存扣减的时候踩过一次很深的坑。当时服务只有两个节点库存表里有个stock字段扣减逻辑用的是synchronized保护起来本地压测怎么跑都没问题。结果上线之后发现库存偶尔会超卖排查了半天才意识到synchronized锁的是JVM内部的monitor两个节点各自持有一把锁A节点锁住的临界区B节点的线程照样能往里冲。本质上是“多个互不感知的锁守护同一份共享资源”锁的语义被完全破坏了。这个问题正是分布式锁要解决的。所谓分布式锁就是让多个进程、多台机器之间对同一个资源的访问做到互斥。它和单机锁最大的区别在于锁的存储和协调不再依赖单一JVM而是落在某个所有节点都能访问的第三方组件上比如Redis、Zookeeper、etcd。基于Redis的那一套因为性能高、接入简单、生态成熟成了目前中小团队的主流选择。如果你正在做微服务拆分、多实例部署或者面试准备分布式锁相关题目这篇文章应该能帮你把整个技术脉络理顺。我会从Redis原生命令一步步演进到生产级方案把SETNX的坑、Lua脚本的必要性、看门狗原理、锁误删问题一次讲透最后附上我在实际项目中排查问题的完整记录。2. 技术选型思考为什么主流方案偏偏是Redis2.1 Redis凭什么成为分布式锁的首选载体Redis能做分布式锁核心在于三点单线程执行模型、丰富的数据结构、可用的原子操作。单线程意味着所有客户端的命令在Redis服务端是串行执行的不存在并发竞争问题。这一点相当关键——分布式锁的本质就是在多节点之间制造一个“串行化入口”Redis天然具备这个特性。再看性能。基于内存的读写单实例QPS可以轻松到十万级别相比基于磁盘的数据库实现比如用MySQL行锁延迟低一两个数量级。库存扣减、秒杀、防重提交这类高频热点操作对锁服务的要求首先是快然后才是可靠。当然Redis方案也有争议主要是锁的可靠性做不到绝对。比如主从架构下master节点宕机后锁数据还没来得及同步到slave就会造成锁丢失。这个我在第5部分会重点展开不同业务场景对这个问题的容忍度是不一样的。2.2 从Zookeeper和etcd的对比中理解Redis的取舍如果只聊Redis不提其他方案很容易让人误以为它就是唯一答案。实际选型时Zookeeper和etcd也有一批忠实用户。Zookeeper的分布式锁基于临时顺序节点客户端和服务端维持心跳会话超时则自动释放锁这把锁的“自动续期”和“服务端兜底”能力做得更彻底。etcd则是通过Lease租约加上Revision机制模型和Zookeeper非常接近API更现代。这两个方案的可靠性确实比Redis高因为它们在设计上就是强一致性优先。但代价是性能上限更低部署运维复杂度也更高。Redis走的是AP路线在极端情况下可能丢失锁Zookeeper走的是CP路线在极端情况下可能短暂不可用。没有绝对的谁好谁坏关键是看业务能接受哪类故障。我的经验是电商、社区、大部分后台业务对数据一致性的要求是“最终一致”短暂极端情况下丢一把锁顶多多放行一个请求后面靠幂等兜底就能补回来用Redis划算。而涉及资金结算、订单状态流转这种强一致场景我会倾向etcd或Zookeeper。Redis的定位不是万能锁而是“高吞吐场景下性价比最优的锁”。3. 核心原理拆解从SETNX到Lindge完整演进3.1 最原始的SETNX加锁为什么三天就被淘汰Redis从2.6.12版本开始支持在SET命令上附加多种选项最核心的组合是SET key value NX EX。但早期实现分布式锁大家用的是单独的SETNX命令SET if Not eXists然后再用EXPIRE单独设置过期时间。# 第一步尝试加锁 SETNX lock_order_1001 node-a-thread-1 # 第二步单独设置过期时间 EXPIRE lock_order_1001 30这套逻辑的bug很直观SETNX和EXPIRE是两次独立的命令如果第一次执行完SETNX成功之后服务进程突然宕机EXPIRE压根没机会执行这把锁就会永远存在所有后续请求全部阻塞。第一次上线时我就因为这段间隙吃过一次大亏——进程被kill -9之后线上库存接口集体超时手动到Redis里删了一把锁才恢复。这个问题的本质是“加锁”和“设置过期时间”需要原子性。一句话总结单独用SETNX加锁可以但不带EXPIRE的SETNX是灾难带了EXPIRE但不是原子的SETNX也是隐患。3.2 演进一SET NX EX原子加锁SET命令带上NX和EX参数之后加锁和设过期时间在Redis服务端一步完成原子性问题从根上解决了。这也是目前手写分布式锁最基础、最通用的形态。SET order_stock_lock_1001 node-a-thread-1 NX EX 30这里有个很容易忽略的细节value字段很多人随手填个1这在单机demo里没问题一旦涉及锁的释放和归属校验就麻烦了。正确的做法是把value设置为一个唯一标识比如UUID、机器IP加线程ID的组合。为什么必须这么做因为释放锁的操作不能是无脑DEL——你有可能把别人持有的锁删掉。想象一个真实场景线程A加锁成功执行业务逻辑耗时过长锁在30秒后自动过期了。此时线程B加锁成功开始执行临界区。这时线程A终于执行完了调DEL释放锁结果删掉的是线程B的锁。线程C趁机加锁成功于是B和C同时进入临界区互斥失效。这就是经典的“误删他人锁”问题。解决方案就是删除之前先比较锁的value是自己当初设置的那个值才能执行DEL。3.3 演进二Lua脚本保证释放锁的原子性value比较加删除如果把它翻译成两步操作又回到了原子性问题。即先GET比较value一致后再DEL这两步之间锁可能刚好过期然后被其他线程重新持有那么你的判断和删除就不再是一一对应的了。正确姿势是借助Lua脚本让Redis服务端一次性执行完整逻辑if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end这段脚本的含义是只有当锁的value等于当前线程设置的唯一标识时才执行删除。整个过程在Redis服务端原子执行不受并发干扰。到这里一把“带过期时间、可归属校验、释放安全”的分布式锁的手写版本就成立了。3.4 演进三过期时间吃紧看门狗续期机制出炉原子释放问题解决之后下一个拦路虎是“锁的持有时间不可控”。过期时间设短了业务还没执行完锁就没了其他线程闯进来设长了持有锁的线程宕机后其他线程要白等很久。死锁和误入只能二选一怎么调都不舒服。Redisson的看门狗WatchDog机制就是来填这个坑的。它的思路是加锁成功后后台起一个定时任务每过锁租期的三分之一时间就自动续期一次。只要业务线程还活着锁就一直在续期一旦线程挂了续期任务自然停止锁到期后自动释放。看门狗的默认处理逻辑是每10秒续期一次锁默认租期30秒。这个参数组合不是随便拍的——30秒的租期给业务留出了充足的执行时间10秒的续期间隔又远小于30秒能有效防止锁提前过期。但要注意的是看门狗机制的前提是客户端进程存活。如果业务线程长时间阻塞在远程调用上锁也会被无限续期最终拖垮Redis这一点需要结合业务超时来控制。4. 从零手写一把生产级Redis分布式锁这部分我会用Java配合Jedis把核心流程完整走一遍重点展示每个环节的代码长什么样以及每一步为什么要这么写。实际生产不建议重复造轮子但理解原理最有效的方式永远是“自己实现一遍”。4.1 环境准备与Maven依赖我用的是Spring Boot 2.7 Jedis 4.3.1Redis服务端版本是6.2。Jedis足够轻量适合拿来演示底层协议如果团队已经在用LettuceSpring Data Redis默认客户端思路完全一样只是API不同。dependency groupIdredis.clients/groupId artifactIdjedis/artifactId version4.3.1/version /dependency4.2 完整加锁/解锁工具类下面这个类可以看作手写Redis分布式锁的最小可行实现import redis.clients.jedis.Jedis; import redis.clients.jedis.params.SetParams; import java.util.Collections; import java.util.UUID; public class RedisDistributedLock { private static final String LOCK_SUCCESS OK; private static final Long UNLOCK_SUCCESS 1L; private static final String LUA_UNLOCK_SCRIPT if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) else return 0 end; private final Jedis jedis; private final String lockKey; private final String lockValue; private final int expireSeconds; public RedisDistributedLock(Jedis jedis, String lockKey, int expireSeconds) { this.jedis jedis; this.lockKey lockKey; this.lockValue UUID.randomUUID().toString() : Thread.currentThread().getId(); this.expireSeconds expireSeconds; } public boolean tryLock() { SetParams params SetParams.setParams().nx().ex(expireSeconds); String result jedis.set(lockKey, lockValue, params); return LOCK_SUCCESS.equals(result); } public boolean tryLock(long waitMillis) { long deadline System.currentTimeMillis() waitMillis; while (System.currentTimeMillis() deadline) { if (tryLock()) { return true; } try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; } public boolean unlock() { Object result jedis.eval(LUA_UNLOCK_SCRIPT, Collections.singletonList(lockKey), Collections.singletonList(lockValue)); return UNLOCK_SUCCESS.equals(result); } }这个示例的核心价值不在代码量而在于三个关键点都比较完整加锁的原子性、锁的归属标识、解锁的原子性。如果你去看很多老项目里的手写实现缺的往往就是第三个用GET加DEL两步法替代Lua脚本迟早出事故。4.3 与Spring Boot集成锁的优雅释放实际项目中不能像上面那样手动创建Jedis实例再手动释放需要把锁的管理封装成模板方法配合try-with-resources释放更稳妥。下面给出一个简单的使用示例Service public class InventoryService { Autowired private JedisPool jedisPool; public boolean deductStock(String skuId, Integer count) { String lockKey lock:stock: skuId; try (Jedis jedis jedisPool.getResource()) { RedisDistributedLock lock new RedisDistributedLock(jedis, lockKey, 30); if (!lock.tryLock(3000)) { throw new RuntimeException(系统繁忙请稍后重试); } try { // 1. 查询库存 int stock getStock(skuId); // 2. 业务校验 if (stock count) { return false; } // 3. 扣减库存 updateStock(skuId, stock - count); return true; } finally { lock.unlock(); } } } }这里有几个细节值得展开。第一锁的key要设计得有区分度通常用业务前缀加业务ID避免不同业务之间互相干扰。第二tryLock设置了一个等待时间加锁失败不会直接报错而是短暂重试这在流量高峰期能显著降低接口的错误率。第三unlock放在finally里保证无论业务逻辑成功失败锁都能被释放。4.4 自旋等待的代价与控制上面的tryLock(long waitMillis)实现了一个简单的自旋重试每隔50毫秒尝试一次加锁直到总等待时间耗尽。这种自旋在Redis分布式锁中是必要的因为SETNX失败后如果立刻返回false调用方就只能走失败分支体验很生硬但如果自旋间隔太短、等待时间太长又会把Redis的压力打上去。根据我的压测经验50毫秒的间隔对大部分业务都合适既不会造成Redis QPS暴增也不会让用户感知到明显的等待。如果你对响应时间要求更高可以把间隔缩短到20毫秒但一定要设置合理的总超时时间防止大量线程挤在同一把锁上疯狂重试。4.5 手写方案的局限为什么最后还是要用Redisson上面的代码在功能上“能用”但离“生产级”还有一段距离。局限主要有四个。第一没有自动续期机制锁的过期时间要么拍脑袋定要么任它提前失效。第二不具备可重入能力同一个线程递归进入被锁代码块时自己会被自己的锁挡在外面。第三没有锁等待队列多个线程竞争同一把锁时全靠自旋CPU浪费比较明显。第四缺少公平性无法保证等待时间最长的线程优先获得锁。这些能力手写起来的成本会成倍增加而且很容易引入新的bug。Redisson把这些都封装好了还经过了大规模生产验证这也是我说“生产环境不要重复造轮子”的原因。理解手写方案是为了让你知道底层发生了什么而使用Redisson是为了让你的项目稳定运行。5. Redisson实战生产级分布式锁的正确打开方式5.1 快速接入与基础配置Redisson接入非常简单首先是添加依赖dependency groupIdorg.redisson/groupId artifactIdredisson-spring-boot-starter/artifactId version3.22.1/version /dependency然后在application.yml里配置连接信息spring: redis: redisson: config: | singleServerConfig: address: redis://127.0.0.1:6379 database: 0如果你已经是Spring Boot项目这个starter会用Redisson替换掉默认的Redis客户端同时保持RedisTemplate、StringRedisTemplate等用法不变迁移成本很低。5.2 只需要记住一个RLockRedisson的锁API核心就是RLock用法和Java并发包里的Lock非常像。最简洁的写法是下面这种Autowired private RedissonClient redissonClient; public void createOrder(String orderId) { RLock lock redissonClient.getLock(lock:order: orderId); boolean locked false; try { locked lock.tryLock(3, 30, TimeUnit.SECONDS); if (!locked) { throw new RuntimeException(系统繁忙); } // 业务逻辑 } catch (InterruptedException e) { Thread.currentThread().interrupt(); } finally { if (locked) { lock.unlock(); } } }tryLock的三个参数分别是等待时间、锁租期、时间单位。这里有个关键点如果指定了锁租期Redisson就按这个值来不再启动看门狗自动续期如果没有指定租期即只传等待时间Redisson会使用默认30秒租期并启动看门狗进行自动续期。刚开始接触时很容易被这个差异坑到建议一开始就搞清楚自己在用哪种模式。5.3 看门狗到底是怎么续期的我在源码里追踪过看门狗的实现整个过程其实很精巧。加锁成功后Redisson会注册一个定时任务延迟10秒执行默认leaseTime的1/3执行时判断锁是否还在且还属于当前线程如果是就把锁的过期时间重置为30秒并再次注册下一次续期任务。这样循环往复直到解锁。这个机制的价值在于“按需续期”。业务2秒执行完锁在第2秒手动释放看门狗自然停止业务超过30秒还没执行完看门狗在20秒左右已经完成了一次续期锁不会提前消失。相比手写方案里“过期时间定死了”的僵硬它把锁的生命周期和业务生命周期解耦了。但也别把看门狗当成万能神器。如果业务线程真的卡死了比如调用的下游接口迟迟不返回看门狗会一直续期锁就永远释放不了。这种情况建议在业务逻辑里加上超时控制或者对接分布式链路追踪及时发现问题不能只看锁层面的指标。5.4 可重入锁、公平锁、读写锁的差异化场景Redisson提供的锁类型不止一种我按自己的使用频率排个序。最常用的是可重入锁它允许同一线程重复获取锁比如一个方法内部又调用了另一个加锁方法不会死锁。Redisson的可重入锁通过HSET结构实现key下保存一个hash字段是线程标识值是重入次数每次加锁加1解锁减1减到0才真正删除。其次是用到较多的是公平锁它保证线程按照请求顺序获得锁底层依赖Redis的ZSet和队列。我看到有些文章说公平锁性能差、不推荐使用我的观点是分场景。对用户侧操作比如抢购公平性其实无所谓但对后台任务、定时调度公平锁能有效避免“饿死”现象代价可以接受。读写锁我用的不算多适合“读多写少”且要求读写互斥的场景。举个例子配置管理服务中多个线程可以同时读配置但写配置时必须独占。用Redisson的RReadWriteLock读锁之间共享写锁独占代码上切换也很简单一个getReadWriteLock就能拿到。5.5 集群部署下的锁策略选择Redisson官方文档把集群环境下的分布式锁分成两种模式普通RLock和MultiLock。普通RLock运行在单节点或主从模式它依赖的是单个Redis节点上的锁数据MultiLock要求客户端同时对多个独立Redis实例加锁全部成功才判定加锁成功这对应了分布式锁经典算法Redlock的思想。我在生产环境用主从模式比较多这个时候要心里有数master节点上的锁如果master宕机且slave还没来得及同步锁就会丢失。对于非资金类业务我接受这个风险因为业务侧有幂等兜底。如果你对锁的可靠性格外敏感可以部署3个以上独立Redis实例用MultiLock代价是加锁耗时成倍增加、可用性从“单点故障”变成了“多数派可用”。6. 常见问题与排查实录这些坑我一个个踩过6.1 锁被误删的概率远比你想象的高前面讲手写方案时提过这个坑这里用一个真实的线上案例复盘一下。当时我们的订单服务有A、B两个实例A实例加锁成功但它在处理订单回调时因为GC停顿了40秒锁在30秒时自动过期。B实例随后加锁成功开始处理同一笔订单。A实例GC结束后继续执行原本的删除锁逻辑一执行直接把B的锁删掉了。这个案例的教训有两个。第一只要用Redis分布式锁锁提前失效是必然会发生的事件不要在概率上心存侥幸重点是释放锁前必须校验归属。第二即使校验了归属也不能完全避免因为A的GC时间超过锁的租期后A和B同时并发处理同一笔订单的问题依然存在只是从“误删锁”变成了“锁过期后并发执行”。解决思路是双管齐下一方面用Redisson看门狗尽量减少锁过期的概率另一方面业务上要有幂等兜底比如数据库的唯一索引、状态机的流转校验这些是比分布式锁更底层的安全网。6.2 锁粒度过大导致的接口雪崩还有一个非常典型的案例有人把整个订单接口的所有逻辑都包在锁里包括远程调用、数据库查询、消息发送导致锁持有时间飙升到秒级同时并发一上来Redis里堆积了大量等待线程每个线程都在自旋重试最终把连接池打满服务整体不可用。锁的粒度设计要遵循“最小化原则”。锁只应该保护真正需要互斥的那段临界区比如“检查库存并扣减库存”这个组合操作。远程调用、IO操作、慢SQL这些都不应该放在锁内。如果确实需要一个长事务的一致性保证你应该考虑的是分布式事务方案而不是一把万能大锁。6.3 用Redis Desktop Manager排查锁残留锁出现异常残留时排查工具能帮上大忙。我习惯用Another Redis Desktop Manager热词里也出现了这个软件来检查锁的分布情况。它的界面比老牌的Redis Desktop Manager更清爽支持按key前缀模糊搜索能直接看到key的TTL、value的值还能手动删除指定的key。定位锁残留的常规流程是先通过KEYS lock:*或SCAN lock:*找到可疑的锁key然后查看TTL判断锁是否还在持有期内再看value里的线程标识结合日志找到持有锁的线程。手动删除时要格外谨慎确认没有业务在跑否则会引发并发问题。6.4 主从切换、时钟跳跃这些“极端情况”怎么应对Redis主从模式下的锁丢失问题网上讨论很多但真正遇到的人不多。应对方式无非三个方向用MultiLock多实例加锁、接受丢失并依靠幂等兜底、切换etcd/Zookeeper换取强一致。没有万金油方案只能在可靠性和性能之间做权衡。时钟跳跃的坑出现在依赖expireTime计算续期的老方案里。如果Redis服务器的时钟突然回拨锁的过期时间可能被延长或缩短影响锁的语义。Redisson已经改为基于当前时间动态计算不再直接依赖系统时钟的单调性这个问题基本被规避了。但是如果你所在的环境有NTP时钟同步建议还是关注一下Redis服务器的时钟状态避免系统层面出了问题。6.5 分布式锁面试题的常见考察维度相关热词里“分布式锁面试题”搜索量很大这也从侧面说明这个话题同样是面试高频区。面试官一般会按照下面这条线去深入先问“为什么synchronized不能用于分布式环境”再问“Redis实现分布式锁的基本命令”然后追问“SETNX加锁后宕机怎么办”“过期时间怎么设置”“释放锁时为什么要用Lua脚本”“Redisson的看门狗原理是什么”“主从切换会不会丢锁”最后上升到“RedLock算法有什么争议你怎么看”。我的建议是不要死记硬背答案。把这篇文章里的演进过程理清楚再说出每个方案解决的问题和引入的新问题面试官会认为你是真的理解而不只是在背题。6.6 常见问题速查表问题现象可能原因排查方式解决方案加锁偶尔失败接口报错频繁并发量高锁被长时间持有查看锁key的TTL和value优化锁内逻辑、缩短持锁时间锁一直存在其他线程无法进入持有锁的线程异常退出通过Redis管理工具查看锁改用Redisson看门狗异常自动过期两个线程同时进入临界区锁提前过期或主从切换丢锁查业务日志和锁操作日志缩短业务耗时、启用看门狗、幂等兜底锁被误删释放锁时未校验归属查看value归属使用Lua脚本校验后删除服务启动后大量线程阻塞连接池耗尽查看Redis连接数和慢日志减小锁粒度重试间隔加大7. 写在最后的实操心得如果只让我总结一个经验那就是分布式锁不是越多越好也不是技术越高级越好。能用数据库唯一约束解决的就别引入Redis锁能用Redis锁解决的就别把架构搞得过于复杂。以我个人的使用习惯来说手写SETNX加Lua脚本的方式适合中小型项目、快速上线、团队对Redisson不熟的场景Redisson适合大部分微服务项目因为看门狗和可重入特性能省去很多手工细节RedLock和MultiLock只在你确认业务无法接受锁丢失而且有足够预算支撑多个独立Redis实例时才需要考虑。还有一个细节很多人会忽略锁相关的日志一定要打好。加锁成功、解锁成功、等待锁超时、续期失败这些关键节点都要有日志记录最好带上锁的key、线程标识、耗时。线上排查问题的时候这些日志是定位故障最重要的线索比事后翻代码高效得多。Redis分布式锁不是一个复杂的算法但它的坑几乎全部藏在边界条件里。希望你读完这篇文章之后不只是会用一个工具类而是能从原理层面上理解每一步设计背后的取舍。这样无论是维护现有系统还是面试时面对考官的追问你都能从容应对。
RELATED

相关推荐

环境变量与 PATH 完全指南:从命令查找到 API 密钥安全的实战手册

环境变量与 PATH 完全指南:从命令查找到 API 密钥安全的实战手册

环境变量与 PATH 完全指南:从命令查找到 API 密钥安全的实战手册 【免费下载链接】easy-vibe 💻 vibe coding 101|The first course for AI-native product builders. 项目地址: https://gitcode.com/GitHub_Trending/ea/easy-vibe 导读…

📅 2026/9/13 7:19:32
MAA 更换主题任务全解析:从任务配置到源码级实现原理

MAA 更换主题任务全解析:从任务配置到源码级实现原理

MAA 更换主题任务全解析:从任务配置到源码级实现原理 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supporting all clients. 项目地址: https://gitc…

📅 2026/9/13 7:19:32
用 fairseq 复现多样化机器翻译混合专家模型:unilm 仓库 translation_moe 实战解析

用 fairseq 复现多样化机器翻译混合专家模型:unilm 仓库 translation_moe 实战解析

用 fairseq 复现多样化机器翻译混合专家模型:unilm 仓库 translation_moe 实战解析 【免费下载链接】unilm Large-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities 项目地址: https://gitcode.com/GitHub_Trending/un/unilm 本…

📅 2026/9/13 7:19:32
MORE NEWS

更多资讯

📰

像老乡鸡那样做香辣鸡杂:炖菜标准化配方、鸡杂料与分步炖煮流程全解析

像老乡鸡那样做香辣鸡杂:炖菜标准化配方、鸡杂料与分步炖煮流程全解析 【免费下载链接】CookLikeHOC 🥢像老乡鸡🐔那样做饭。已添加2026年发布的《老乡鸡菜品溯源报告 2.0中新出现的菜品。主要部分于2024年完工,非老乡鸡官方仓库。…

📰

Transformer与MoE架构:大模型演进与核心技术解析

1. 大模型架构演进背景2017年Transformer架构的横空出世,彻底改变了自然语言处理领域的游戏规则。这个基于自注意力机制的模型架构,在机器翻译任务上首次实现了完全基于注意力机制的端到端训练,其并行计算特性使得模型训练效率大幅提升。但当…

📰

Zulip Delighted 集成指南:将客户满意度调查反馈实时同步到团队聊天

Zulip Delighted 集成指南:将客户满意度调查反馈实时同步到团队聊天 【免费下载链接】zulip Zulip server and web application. Open-source team chat that helps teams stay productive and focused. 项目地址: https://gitcode.com/GitHub_Trending/zu/zulip …

📰

GoFr vs Fiber:性能导向的 fasthttp 框架与生产级全栈框架的选型对比

GoFr vs Fiber:性能导向的 fasthttp 框架与生产级全栈框架的选型对比 【免费下载链接】gofr An opinionated GoLang framework for accelerated microservice development. Built in support for databases and observability. 项目地址: https://gitcode.com/Git…

📰

MaaAssistantArknights Issue Bot 使用指南:自动标签、手动触发命令与 issue-checker 配置解析

MaaAssistantArknights Issue Bot 使用指南:自动标签、手动触发命令与 issue-checker 配置解析 【免费下载链接】MaaAssistantArknights 《明日方舟》小助手,全日常一键长草!| A one-click tool for the daily tasks of Arknights, supportin…

📰

Wasp 社交内容技能深度解析:用六步逆向工程框架提取爆款内容模式

Wasp 社交内容技能深度解析:用六步逆向工程框架提取爆款内容模式 【免费下载链接】wasp The batteries-included full-stack framework for the AI era. Develop JS/TS web apps (React, Node.js, and Prisma) using declarative code that abstracts away complex …

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬