zx 5 days ago
parent
commit
50d97013b6

+ 39 - 6
fs-qw-api/src/main/java/com/fs/app/service/QwDataCallbackService.java

@@ -26,6 +26,8 @@ import com.google.gson.JsonParser;
 import com.tencent.wework.Finance;
 import lombok.extern.slf4j.Slf4j;
 import org.json.JSONObject;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Async;
@@ -73,6 +75,9 @@ public class QwDataCallbackService {
     @Autowired
     IQwAutoTagsService qwAutoTagsService;
 
+    @Autowired
+    private RedissonClient redissonClient;
+
     @Autowired
     IQwAutoTagsLogsService qwAutoTagsLogsService;
 
@@ -202,13 +207,41 @@ public class QwDataCallbackService {
                             if(WelcomeCodeList.getLength() > 0) {
                                 WelcomeCode = WelcomeCodeList.item(0).getTextContent();
                             }
-
-                            String qwApiExternal=redisCache.getCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent());
-                            if (StringUtil.strIsNullOrEmpty(qwApiExternal)){
-                                redisCache.setCacheObject("qwApiExternal:"+root.getElementsByTagName("UserID").item(0).getTextContent()+":"+corpId+":"+root.getElementsByTagName("ExternalUserID").item(0).getTextContent() ,"1",10, TimeUnit.MINUTES);
-                                qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
-
+                            String userId = root.getElementsByTagName("UserID").item(0).getTextContent();
+                            String externalUserId = root.getElementsByTagName("ExternalUserID").item(0).getTextContent();
+                            String cacheKey = "qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId;
+                            String lockKey = "lock:qwApiExternal:" + userId + ":" + corpId + ":" + externalUserId; // 锁Key(Hash类型,加前缀lock:)
+
+                            // 2. 获取 Redisson 分布式锁
+                            RLock lock = redissonClient.getLock(lockKey);
+                            boolean isLocked = false;
+                            try {
+                                // 3. 尝试加锁:最多等待 5 秒,锁自动释放时间 15 分钟
+                                isLocked = lock.tryLock(5, 15, TimeUnit.MINUTES);
+                                if (isLocked) {
+                                    // 4. 加锁成功后,再次检查缓存(避免多线程竞争时重复执行业务)
+                                    String qwApiExternal = redisCache.getCacheObject(cacheKey);
+                                    if (StringUtil.strIsNullOrEmpty(qwApiExternal)) {
+                                        try {
+                                            // 5. 新增用户
+                                            qwExternalContactService.insertQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),null,corpId,State,WelcomeCode);
+                                            // 6. 业务逻辑执行成功后,写入 Redis 缓存(有效期 10 分钟)
+                                            redisCache.setCacheObject(cacheKey, "1", 10, TimeUnit.MINUTES);
+                                        } catch (Exception e) {
+                                            // 7. 业务逻辑失败时,删除缓存
+                                            redisCache.deleteObject(cacheKey);
+                                        }
+                                    }
+                                }
+                            } catch (InterruptedException e) {
+                                logger.error("中断异常");
+                            } finally {
+                                // 4. 确保锁最终被释放(只有加锁成功的线程才需要释放)
+                                if (isLocked && lock.isHeldByCurrentThread()) {
+                                    lock.unlock();
+                                }
                             }
+
                             break;
                         case "edit_external_contact":
                             qwExternalContactService.updateQwExternalContactByExternalUserId(root.getElementsByTagName("ExternalUserID").item(0).getTextContent(),root.getElementsByTagName("UserID").item(0).getTextContent(),corpId);