{"record":{"id":"b997bd6e24acdf3c","repo":"xkcoding/spring-boot-demo","slug":"error-b997bd","errorCode":null,"errorMessage":"请勿重复提交","messagePattern":"请勿重复提交","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"warning","filePath":"demo-zookeeper/src/main/java/com/xkcoding/zookeeper/aspectj/ZooLockAspect.java","lineNumber":77,"sourceCode":"     * @throws Throwable 异常信息\n     */\n    @Around(\"doLock()\")\n    public Object around(ProceedingJoinPoint point) throws Throwable {\n        MethodSignature signature = (MethodSignature) point.getSignature();\n        Method method = signature.getMethod();\n        Object[] args = point.getArgs();\n        ZooLock zooLock = method.getAnnotation(ZooLock.class);\n        if (StrUtil.isBlank(zooLock.key())) {\n            throw new RuntimeException(\"分布式锁键不能为空\");\n        }\n        String lockKey = buildLockKey(zooLock, method, args);\n        InterProcessMutex lock = new InterProcessMutex(zkClient, lockKey);\n        try {\n            // 假设上锁成功，以后拿到的都是 false\n            if (lock.acquire(zooLock.timeout(), zooLock.timeUnit())) {\n                return point.proceed();\n            } else {\n                throw new RuntimeException(\"请勿重复提交\");\n            }\n        } finally {\n            lock.release();\n        }\n    }\n\n    /**\n     * 构造分布式锁的键\n     *\n     * @param lock   注解\n     * @param method 注解标记的方法\n     * @param args   方法上的参数\n     * @return\n     * @throws NoSuchFieldException\n     * @throws IllegalAccessException\n     */\n    private String buildLockKey(ZooLock lock, Method method, Object[] args) throws NoSuchFieldException, IllegalAccessException {\n        StringBuilder key = new StringBuilder(KEY_SEPARATOR + KEY_PREFIX + lock.key());","sourceCodeStart":59,"sourceCodeEnd":95,"githubUrl":"https://github.com/xkcoding/spring-boot-demo/blob/87a142f9604c1a5365b4d24d22c2c11c26a9d5ab/demo-zookeeper/src/main/java/com/xkcoding/zookeeper/aspectj/ZooLockAspect.java#L59-L95","documentation":"ZooLockAspect.around acquires a Curator InterProcessMutex; if lock.acquire(timeout, unit) returns false (lock not acquired within the timeout), it throws RuntimeException('请勿重复提交') at ZooLockAspect.java:77. Distributed-lock contention is treated as duplicate-submission prevention.","triggerScenarios":"Two concurrent invocations of the same @ZooLock method/lock key; the current holder exceeds the acquire timeout; the ZooKeeper quorum is slow so acquire times out.","commonSituations":"Double-click submit on the client; high concurrency on an idempotent endpoint; an unhealthy/latent ZooKeeper cluster; @ZooLock timeout set too short.","solutions":["Increase the @ZooLock timeout to outlast the critical section","Make the client idempotent (disable the button, send an idempotency token)","Verify ZooKeeper quorum health and session-timeout settings","Retry with backoff where the operation is safe to retry"],"exampleFix":"// before\nif (lock.acquire(zooLock.timeout(), zooLock.timeUnit())) {\n    return point.proceed();\n} else {\n    throw new RuntimeException('请勿重复提交');\n}\n// after (caller-side)\ntry {\n    lockedService.doWork(req);\n} catch (RuntimeException e) {\n    if ('请勿重复提交'.equals(e.getMessage())) {\n        return ApiResponse.of(429, '请求处理中，请勿重复提交', null);\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// client-side: guard against double submit before invoking the locked method\nif (submitting) { return; }\nsubmitting = true;\ntry { lockedService.doWork(req); } finally { submitting = false; }","typeGuard":null,"tryCatchPattern":"try {\n    lockedService.doWork(req);\n} catch (RuntimeException e) {\n    if ('请勿重复提交'.equals(e.getMessage())) {\n        return ApiResponse.of(429, '请求处理中，请勿重复提交', null);\n    }\n    throw e;\n}","preventionTips":["Make the client idempotent (disable the button, idempotency key)","Size @ZooLock timeout to exceed the critical section","Keep the ZooKeeper quorum healthy to avoid spurious acquire timeouts"],"tags":["zookeeper","distributed-lock","curator","concurrency"],"backgroundTag":null,"analyzedSha":"87a142f9604c1a5365b4d24d22c2c11c26a9d5ab","analyzedAt":"2026-08-14T01:16:58.217Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}