偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Redis+唯一序列號的方案實(shí)現(xiàn)接口冪等性

開發(fā) 前端
接口冪等性是指同一接口被多次調(diào)用時,產(chǎn)生的業(yè)務(wù)結(jié)果是一致的,不會因?yàn)橹貜?fù)調(diào)用而導(dǎo)致非預(yù)期的副作用。在分布式系統(tǒng)中,由于網(wǎng)絡(luò)延遲、重試機(jī)制、負(fù)載均衡等因素,接口重復(fù)調(diào)用幾乎是不可避免的,因此保證接口冪等性是系統(tǒng)設(shè)計(jì)中至關(guān)重要的一環(huán)。

前言

接口冪等性是指同一接口被多次調(diào)用時,產(chǎn)生的業(yè)務(wù)結(jié)果是一致的,不會因?yàn)橹貜?fù)調(diào)用而導(dǎo)致非預(yù)期的副作用。在分布式系統(tǒng)中,由于網(wǎng)絡(luò)延遲、重試機(jī)制、負(fù)載均衡等因素,接口重復(fù)調(diào)用幾乎是不可避免的,因此保證接口冪等性是系統(tǒng)設(shè)計(jì)中至關(guān)重要的一環(huán)。

冪等性實(shí)現(xiàn)方案對比

方案

優(yōu)點(diǎn)

缺點(diǎn)

適用場景

Redis + 唯一序列號

高性能,支持分布式

依賴 Redis,需客戶端生成序列號

大部分分布式接口場景

數(shù)據(jù)庫唯一索引

實(shí)現(xiàn)簡單,不依賴其他組件

性能較低,對數(shù)據(jù)庫有壓力

數(shù)據(jù)插入類接口

令牌機(jī)制

服務(wù)端生成令牌,安全性高

增加一次請求交互,流程復(fù)雜

安全性要求高的場景

狀態(tài)機(jī)控制

符合業(yè)務(wù)邏輯,天然冪等

僅適用于有狀態(tài)流轉(zhuǎn)的業(yè)務(wù)

訂單狀態(tài)變更等場景

悲觀鎖

實(shí)現(xiàn)簡單,安全性高

并發(fā)性能差

并發(fā)量低的場景

樂觀鎖

并發(fā)性能好

實(shí)現(xiàn)相對復(fù)雜

并發(fā)量高的場景

Redis + 唯一序列號方案介紹

Redis+唯一序列號方案是實(shí)現(xiàn)接口冪等性的常用方案之一,其核心思想是:

  • 客戶端發(fā)起請求時,生成一個全局唯一的序列號(Serial Number
  • 服務(wù)端接收到請求后,先檢查該序列號在Redis中是否存在
  • 如果不存在,將序列號存入Redis,并執(zhí)行業(yè)務(wù)邏輯
  • 如果已存在,說明是重復(fù)請求,直接返回成功或相應(yīng)結(jié)果,不重復(fù)執(zhí)行業(yè)務(wù)邏輯

該方案利用Redis的高性能、原子操作和過期時間特性,能夠高效地實(shí)現(xiàn)分布式環(huán)境下的接口冪等性控制。

效果圖

圖片

實(shí)現(xiàn)細(xì)節(jié)

唯一序列號需要滿足以下特性:

  • 全局唯一性:確保不同請求不會產(chǎn)生相同的序列號
  • 不可預(yù)測性:防止惡意猜測序列號
  • 高效生成:生成過程不能成為系統(tǒng)瓶頸
  • 包含業(yè)務(wù)含義(可選):便于問題排查和追蹤

常用的生成方式:

  • UUID/GUID:通用唯一識別碼,本地生成,性能高
  • 雪花算法(Snowflake):生成64位全局唯一ID,包含時間戳信息
  • 數(shù)據(jù)庫自增ID:通過數(shù)據(jù)庫生成唯一ID,性能較低
  • 業(yè)務(wù)信息 + 隨機(jī)數(shù):結(jié)合用戶ID、時間戳等業(yè)務(wù)信息生成

Redis 存儲設(shè)計(jì)

鍵(Key)設(shè)計(jì):
idempotent:{業(yè)務(wù)類型}:{序列號}
值(Value)設(shè)計(jì):

可以存儲請求相關(guān)信息,如用戶ID、請求時間等,便于后續(xù)分析和問題排查。

過期時間(TTL):

根據(jù)業(yè)務(wù)場景設(shè)置合理的過期時間,避免Redis內(nèi)存溢出。例如:

  • 支付類接口:24小時
  • 訂單類接口:7
  • 一般查詢接口:1小時
處理流程
客戶端 -> 生成唯一序列號 -> 攜帶序列號發(fā)起請求 -> 服務(wù)端
服務(wù)端 -> 檢查Redis中是否存在該序列號
       -> 不存在:存儲序列號到Redis,執(zhí)行業(yè)務(wù)邏輯,返回結(jié)果
       -> 存在:直接返回之前的處理結(jié)果

實(shí)現(xiàn)示例

生成唯一序列號工具類
public class SerialNumberGenerator {
    
    /**
     * 生成UUID作為唯一序列號
     */
    public static String generateUUID() {
        return UUID.randomUUID().toString();
    }
    
    /**
     * 生成包含業(yè)務(wù)前綴的唯一序列號
     */
    public static String generateWithPrefix(String prefix) {
        return prefix + ":" + UUID.randomUUID().toString().replaceAll("-", "");
    }
}
Redis 操作工具類
@Component
public class RedisIdempotentUtils {
    
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    
    /**
     * 檢查并設(shè)置序列號
     * @param key 序列號鍵
     * @param value 存儲的值
     * @param expireTime 過期時間
     * @param timeUnit 時間單位
     * @returntrue-首次請求,false-重復(fù)請求
     */
    public boolean checkAndSet(String key, Object value, long expireTime, TimeUnit timeUnit) {
        // 使用Redis的setIfAbsent實(shí)現(xiàn)原子操作,確保線程安全
        Boolean result = redisTemplate.opsForValue().setIfAbsent(key, value, expireTime, timeUnit);
        return Boolean.TRUE.equals(result);
    }
    
    /**
     * 獲取序列號對應(yīng)的值
     */
    public Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }
    
    /**
     * 構(gòu)建Redis鍵
     */
    public String buildKey(String businessType, String serialNumber) {
        return"idempotent:" + businessType + ":" + serialNumber;
    }
}
接口冪等性控制實(shí)現(xiàn)
@RestController
public class PaymentController {
    
    @Resource
    private RedisIdempotentUtils redisIdempotentUtils;
    
    @Resource
    private PaymentService paymentService;
    
    /**
     * 支付接口
     * @param serialNumber 唯一序列號,從請求頭獲取
     * @param paymentRequest 支付請求參數(shù)
     */
    @PostMapping("/api/payment")
    public Result<PaymentResponse> processPayment(
            @RequestHeader("Idempotent-Serial") String serialNumber,
            @RequestBody PaymentRequest paymentRequest) {
        
        // 1. 構(gòu)建Redis鍵
        String redisKey = redisIdempotentUtils.buildKey("payment", serialNumber);
        
        // 2. 檢查是否為重復(fù)請求
        boolean isFirstRequest = redisIdempotentUtils.checkAndSet(
                redisKey, 
                paymentRequest.getUserId(), 
                24, 
                TimeUnit.HOURS);
        
        if (!isFirstRequest) {
            // 重復(fù)請求,返回之前的處理結(jié)果或提示
            Object userId = redisIdempotentUtils.get(redisKey);
            PaymentResponse cachedResponse = getCachedPaymentResponse(serialNumber);
            return Result.success("重復(fù)請求,已處理", cachedResponse);
        }
        
        try {
            // 3. 首次請求,執(zhí)行業(yè)務(wù)邏輯
            PaymentResponse response = paymentService.processPayment(paymentRequest);
            
            // 4. 緩存處理結(jié)果(可選)
            cachePaymentResponse(serialNumber, response);
            
            return Result.success("支付成功", response);
        } catch (Exception e) {
            // 5. 業(yè)務(wù)處理失敗,刪除序列號(根據(jù)業(yè)務(wù)需求決定)
            // redisTemplate.delete(redisKey);
            return Result.fail("支付失?。? + e.getMessage());
        }
    }
    
    // 緩存和獲取支付結(jié)果的方法(實(shí)際實(shí)現(xiàn)略)
    private void cachePaymentResponse(String serialNumber, PaymentResponse response) {
        // 實(shí)現(xiàn)緩存邏輯
    }
    
    private PaymentResponse getCachedPaymentResponse(String serialNumber) {
        // 實(shí)現(xiàn)獲取緩存邏輯
        return new PaymentResponse();
    }
}

使用注意事項(xiàng)

  • 序列號傳遞方式:建議通過請求頭(Header)傳遞,避免侵入業(yè)務(wù)參數(shù)
  • 過期時間設(shè)置:根據(jù)業(yè)務(wù)場景合理設(shè)置,一般應(yīng)大于業(yè)務(wù)最大處理時間
  • 異常處理:業(yè)務(wù)處理失敗時,根據(jù)實(shí)際需求決定是否刪除 Redis 中的序列號
  • Redis 高可用:確保Redis服務(wù)的高可用,可采用主從復(fù)制、哨兵或集群模式
  • 監(jiān)控告警:對Redis的內(nèi)存使用、接口重復(fù)請求數(shù)等指標(biāo)進(jìn)行監(jiān)控
  • 序列號生成:確保序列號的唯一性,避免因生成策略問題導(dǎo)致的沖突

方案優(yōu)化建議

  • 序列號壓縮:對序列號進(jìn)行壓縮處理,減少Redis存儲占用
  • 本地緩存:在服務(wù)端增加本地緩存(如Caffeine),減少對Redis的訪問
  • 批量清理:對于過期數(shù)據(jù),可采用定時任務(wù)批量清理,減輕Redis負(fù)擔(dān)
  • 分級存儲:根據(jù)業(yè)務(wù)重要性,對不同接口設(shè)置不同的存儲策略和過期時間
  • 異步處理:對于非核心流程,可采用異步方式處理,提高響應(yīng)速度
責(zé)任編輯:武曉燕 來源: 一安未來
相關(guān)推薦

2017-11-22 09:46:53

分布式架構(gòu)系統(tǒng)

2024-11-01 09:28:02

2024-08-29 09:01:39

2024-06-24 01:00:00

2025-02-23 08:00:00

冪等性Java開發(fā)

2024-03-13 15:18:00

接口冪等性高并發(fā)

2020-11-12 07:43:06

Redis冪等性接口

2022-05-23 11:35:16

jiekou冪等性

2021-01-18 14:34:59

冪等性接口客戶端

2025-02-26 08:20:18

2020-07-15 08:14:12

高并發(fā)

2025-03-17 08:07:11

2021-01-13 11:23:59

分布式冪等性支付

2025-10-24 07:52:56

2023-08-29 13:53:00

前端攔截HashMap

2023-03-07 08:19:16

接口冪等性SpringBoot

2022-04-25 11:26:16

開發(fā)SpringBoot

2009-09-04 08:17:04

Windows 7序列號檢查器

2021-03-28 09:45:05

冪等性接口數(shù)據(jù)

2011-04-19 09:25:51

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號