精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

接口冪等性解決方案:深入理解 “一鎖、二判、三更新”

開發 前端
解決接口冪等問題的核心邏輯可濃縮為一句口令一鎖、二判、三更新。這三個步驟環環相扣,缺一不可,嚴格遵循即可有效抵御并發重復請求,保障數據一致性。下面我們逐一拆解每個步驟的原理、實現方式及注意事項。

前言

在分布式系統和高并發業務場景中,接口冪等性是保障數據一致性的關鍵環節。無論是網絡延遲導致的重試、用戶誤操作的重復提交,還是分布式服務間的異步調用重試,都可能引發重復執行問題,進而導致數據重復插入、金額重復扣減、狀態異常變更等嚴重后果。

本文將圍繞一鎖、二判、三更新核心口令,詳細拆解接口冪等性的解決方案。

一鎖、二判、三更新

解決接口冪等問題的核心邏輯可濃縮為一句口令一鎖、二判、三更新。這三個步驟環環相扣,缺一不可,嚴格遵循即可有效抵御并發重復請求,保障數據一致性。下面我們逐一拆解每個步驟的原理、實現方式及注意事項。

一鎖:加互斥鎖,阻斷并發重復請求

核心目標:通過加鎖確保同一時間內,只有一個請求能進入后續的判斷和更新流程,從源頭阻斷并發導致的重復執行。

為什么需要鎖?

在高并發場景下,即使后續有冪等判斷,若多個請求同時繞過判斷步驟(如并發查詢時均未查到歷史數據),仍會導致重復更新。例如:兩個并發的下單請求同時查詢是否已有該用戶的訂單,均返回無,隨后同時執行創建訂單操作,最終生成兩筆重復訂單。

因此,鎖的作用是強制并發請求排隊執行,確保同一業務場景下,只有一個請求能進入后續流程。

鎖的類型與選擇
  • 分布式鎖:適用于分布式系統(多服務實例、多機器部署),常見實現方式包括Redis分布式鎖、ZooKeeper分布式鎖、etcd鎖等。核心要求是跨服務、跨機器的互斥性。
  • 悲觀鎖:適用于單體應用或數據庫層面的并發控制,通常通過數據庫的SELECT ... FOR UPDATE語句實現,鎖定查詢行,阻止其他事務修改或查詢。核心要求是數據庫事務內的互斥性。

二判:冪等性判斷,識別重復請求

核心目標:在獲取鎖后,通過預先定義的規則判斷當前請求是否為重復請求,若已執行過則直接返回結果,避免重復處理,常見的冪等判斷方式:

基于狀態機判斷:

適用于業務存在明確狀態流轉的場景(如訂單狀態:待支付→已支付→已發貨→已完成)。通過判斷當前業務數據的狀態是否符合執行條件,來識別重復請求。例如:已支付狀態的訂單,若再次收到支付回調請求,則直接返回已處理,不執行后續邏輯。

基于流水表判斷:

適用于需要記錄請求軌跡的場景。通過建立冪等流水表,存儲每次請求的唯一標識(如請求ID、用戶ID + 業務ID),每次請求先查詢流水表:若已存在則為重復請求,若不存在則記錄流水并繼續執行。

基于唯一性索引判斷:

適用于數據庫層面的冪等控制,通過在業務表的關鍵字段上建立唯一索引(如訂單表的用戶ID + 商品ID + 下單時間戳聯合唯一索引),若重復請求執行插入操作,數據庫會拋出唯一鍵沖突異常,捕獲異常后即可判斷為重復請求。

關鍵注意事項:

  • 唯一標識需全局唯一:例如用戶ID + 業務場景標識 + 請求唯一ID,避免不同業務場景的標識沖突;
  • 判斷邏輯需高效:若基于數據庫查詢判斷,需確保查詢字段已建立索引,避免全表掃描導致性能問題;
  • 結果需緩存(可選):對于高頻重復請求,可將判斷結果緩存至Redis,減少數據庫查詢次數。

三更新:執行數據更新,確保原子性

核心目標:在確認請求為非重復請求后,執行業務邏輯并更新數據,同時確保更新操作的原子性,避免因中間異常導致數據部分更新。

數據更新的核心要求
  • 原子性:更新操作需作為一個整體執行,要么全部成功,要么全部失敗(如創建訂單時,需同時插入訂單表、扣減庫存表,兩步操作需在同一個數據庫事務內);
  • 冪等性兼容:即使因極端情況(如鎖過期)導致重復進入更新步驟,也需通過業務邏輯或數據庫約束(如唯一索引)避免數據異常;
  • 狀態同步:更新完成后,需同步更新相關狀態(如流水表標記已處理、業務表更新狀態字段),為后續重復請求的判斷提供依據。
常見的更新方式
  • 數據庫事務:單體應用或單庫場景下,通過@Transactional注解或手動開啟事務,確保多表操作的原子性;
  • 分布式事務:跨庫、跨服務場景下,需通過TCC、SAGA、Seata等分布式事務框架,保障多節點更新的一致性(需注意分布式事務的性能開銷);
  • 狀態標記:更新完成后,立即更新業務數據的狀態或流水表的記錄,避免后續請求誤判。

代碼案例

數據庫表結構

-- 訂單表(t_order)
CREATE TABLE `t_order` (
  `order_id` bigint NOT NULL AUTO_INCREMENT COMMENT '訂單ID',
  `user_id` bigint NOT NULL COMMENT '用戶ID',
  `product_id` bigint NOT NULL COMMENT '商品ID',
  `quantity` int NOT NULL COMMENT '購買數量',
  `total_amount` decimal(10,2) NOT NULL COMMENT '訂單總金額',
  `order_status` tinyint NOT NULL DEFAULT '0' COMMENT '訂單狀態:0-待支付,1-已支付,2-已取消,3-已完成',
  `identifier` varchar(64) NOT NULL COMMENT '請求唯一標識(冪等判斷)',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  `is_deleted` tinyint NOT NULL DEFAULT '0' COMMENT '邏輯刪除:0-未刪除,1-已刪除',
  PRIMARY KEY (`order_id`),
  UNIQUE KEY `uk_identifier` (`identifier`) COMMENT '唯一索引:確保同一請求不會重復創建訂單',
  KEY `idx_user_id` (`user_id`) COMMENT '用戶ID索引:便于查詢用戶訂單'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='訂單表';

-- 冪等流水表(t_idempotent_flow)
CREATE TABLE `t_idempotent_flow` (
  `flow_id` bigint NOT NULL AUTO_INCREMENT COMMENT '流水ID',
  `business_scene` varchar(32) NOT NULL COMMENT '業務場景:ORDER-下單,PAY-支付',
  `identifier` varchar(64) NOT NULL COMMENT '請求唯一標識',
  `user_id` bigint NOT NULL COMMENT '用戶ID',
  `handle_status` tinyint NOT NULL DEFAULT '0' COMMENT '處理狀態:0-待處理,1-處理成功,2-處理失敗',
  `business_result` varchar(128) DEFAULT NULL COMMENT '業務結果:如訂單ID',
  `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '創建時間',
  `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
  PRIMARY KEY (`flow_id`),
  UNIQUE KEY `uk_business_identifier` (`business_scene`,`identifier`) COMMENT '唯一索引:同一業務場景下,請求標識唯一'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='冪等流水表';

自定義分布式鎖實現(核心一鎖)

/**
 * 自定義分布式鎖注解:用于方法級別的鎖控制
 */
@Target(ElementType.METHOD) // 注解作用于方法
@Retention(RetentionPolicy.RUNTIME) // 運行時生效
@Documented // 生成文檔
public @interface DistributeLock {
    /**
     * 業務場景標識(如ORDER:下單,PAY:支付)
     * 用于區分不同業務的鎖,避免鎖key沖突
     */
    String scene();

    /**
     * 鎖的key表達式(支持SpEL表達式,如#request.identifier)
     * 用于動態生成鎖的key,確保同一請求/業務的鎖唯一
     */
    String keyExpression();

    /**
     * 鎖的過期時間(單位:毫秒)
     * 避免服務宕機導致鎖永久持有,默認3000ms
     */
    long expire() default 3000;

    /**
     * 獲取鎖的超時時間(單位:毫秒)
     * 超過該時間未獲取到鎖,直接返回失敗,默認1000ms
     */
    long timeout() default 1000;
}

分布式鎖切面

可以使用Redisson替換案例while循環

/**
 * 分布式鎖切面:實現@DistributeLock注解的核心邏輯
 */
@Aspect
@Component
@Slf4j
public class DistributeLockAspect {
    // Redis鎖的前綴(避免與其他Redis key沖突)
    private static final String LOCK_PREFIX = "distribute:lock:";
    // RedisTemplate:操作Redis
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    // SpEL表達式解析器:用于解析keyExpression(如#request.identifier)
    private final ExpressionParser parser = new SpelExpressionParser();

    /**
     * 環繞通知:攔截被@DistributeLock注解的方法
     */
    @Around("@annotation(distributeLock)")
    public Object around(ProceedingJoinPoint joinPoint, DistributeLock distributeLock) throws Throwable {
        // 1. 解析鎖的key(根據scene和keyExpression動態生成)
        String lockKey = generateLockKey(joinPoint, distributeLock);
        // 2. 生成鎖的value(UUID:用于釋放鎖時校驗,避免誤釋放其他線程的鎖)
        String lockValue = UUID.randomUUID().toString();

        // 3. 嘗試獲取分布式鎖
        boolean lockAcquired = false;
        try {
            // 計算獲取鎖的超時時間(當前時間 + timeout)
            long timeout = distributeLock.timeout();
            long endTime = System.currentTimeMillis() + timeout;

            // 循環獲取鎖,直到超時
            while (System.currentTimeMillis() < endTime) {
                // Redis命令:SET lockKey lockValue NX EX expireTime
                // NX:只在key不存在時設置(確保互斥);EX:設置過期時間(避免死鎖)
                Boolean success = stringRedisTemplate.opsForValue()
                        .setIfAbsent(lockKey, lockValue, distributeLock.expire(), TimeUnit.MILLISECONDS);

                if (Boolean.TRUE.equals(success)) {
                    lockAcquired = true;
                    log.info("獲取分布式鎖成功,lockKey:{},lockValue:{}", lockKey, lockValue);
                    // 4. 獲取鎖成功,執行目標方法(業務邏輯)
                    return joinPoint.proceed();
                }

                // 獲取鎖失敗,短暫休眠后重試(避免頻繁請求Redis)
                TimeUnit.MILLISECONDS.sleep(100);
            }

            // 5. 超時未獲取到鎖,拋出異常
            log.error("獲取分布式鎖超時,lockKey:{},超時時間:{}ms", lockKey, timeout);
            throw new RuntimeException("系統繁忙,請稍后再試");
        } finally {
            // 6. 釋放鎖(僅釋放當前線程持有的鎖,避免誤釋放)
            if (lockAcquired) {
                releaseLock(lockKey, lockValue);
            }
        }
    }

    /**
     * 生成分布式鎖的key:lockPrefix + scene + ":" + dynamicKey
     */
    private String generateLockKey(ProceedingJoinPoint joinPoint, DistributeLock distributeLock) {
        // 解析SpEL表達式,獲取動態key(如#request.identifier的值)
        String dynamicKey = parseSpelExpression(joinPoint, distributeLock.keyExpression());
        // 拼接完整的lockKey
        return LOCK_PREFIX + distributeLock.scene() + ":" + dynamicKey;
    }

    /**
     * 解析SpEL表達式:根據方法參數動態生成key(如#request.identifier)
     */
    private String parseSpelExpression(ProceedingJoinPoint joinPoint, String keyExpression) {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Object[] args = joinPoint.getArgs(); // 方法參數數組
        String[] paramNames = signature.getParameterNames(); // 方法參數名數組

        // 構建SpEL上下文:將參數名和參數值綁定,便于表達式解析
        EvaluationContext context = new StandardEvaluationContext();
        for (int i = 0; i < paramNames.length; i++) {
            context.setVariable(paramNames[i], args[i]);
        }

        // 解析SpEL表達式,獲取動態key
        Expression expression = parser.parseExpression(keyExpression);
        return expression.getValue(context, String.class);
    }

    /**
     * 釋放分布式鎖:僅當鎖的value與當前線程的lockValue一致時才釋放(避免誤釋放)
     */
    private void releaseLock(String lockKey, String lockValue) {
        try {
            // 獲取Redis中當前鎖的value
            String currentValue = stringRedisTemplate.opsForValue().get(lockKey);
            // 校驗value:只有當前線程持有該鎖時,才刪除鎖
            if (lockValue.equals(currentValue)) {
                stringRedisTemplate.delete(lockKey);
                log.info("釋放分布式鎖成功,lockKey:{},lockValue:{}", lockKey, lockValue);
            } else {
                log.warn("釋放分布式鎖失敗:鎖已被其他線程持有,lockKey:{},當前value:{},期望value:{}",
                        lockKey, currentValue, lockValue);
            }
        } catch (Exception e) {
            log.error("釋放分布式鎖異常,lockKey:{},lockValue:{}", lockKey, lockValue, e);
        }
    }
}

Service 層實現(核心二判、三更新)

/**
 * 訂單服務實現類
 */
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {

    @Resource
    private OrderMapper orderMapper;

    @Resource
    private IdempotentFlowMapper idempotentFlowMapper;

    /**
     * 二判:冪等判斷(查詢訂單是否已存在)
     * 邏輯:通過“商品ID + 請求標識(identifier)”查詢,確保同一請求不會重復創建訂單
     */
    @Override
    public OrderDTO queryOrder(Long productId, String identifier) {
        // 1. 構建查詢條件(商品ID + 標識 + 未刪除)
        LambdaQueryWrapper<Order> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Order::getProductId, productId)
                .eq(Order::getIdentifier, identifier)
                .eq(Order::getIsDeleted, 0); // 邏輯刪除:僅查詢未刪除的訂單

        // 2. 執行查詢
        Order order = orderMapper.selectOne(queryWrapper);
        if (order == null) {
            log.info("冪等判斷:未查詢到訂單,productId:{},identifier:{}", productId, identifier);
            return null;
        }

        // 3. 轉換為DTO返回
        OrderDTO orderDTO = new OrderDTO();
        BeanUtils.copyProperties(order, orderDTO);
        log.info("冪等判斷:查詢到已存在訂單,orderId:{},identifier:{}", order.getOrderId(), identifier);
        return orderDTO;
    }

    /**
     * 三更新:創建訂單(事務原子性保障)
     * 邏輯:1. 扣減庫存(此處簡化,實際需調用庫存服務);2. 創建訂單;3. 記錄冪等流水
     */
    @Override
    @Transactional(rollbackFor = Exception.class) // 事務:任何異常都回滾
    public OrderDTO order(OrderRequest request) {
        try {
            // 1. 業務參數校驗(簡化:實際需更詳細的校驗,如庫存是否充足)
            validateOrderRequest(request);

            // 2. 扣減庫存(此處為簡化邏輯,實際應調用庫存服務,且需確保庫存服務的冪等性)
            boolean stockDeducted = deductStock(request.getProductId(), request.getQuantity());
            if (!stockDeducted) {
                throw new RuntimeException("庫存不足,商品ID:" + request.getProductId());
            }

            // 3. 創建訂單(插入t_order表)
            Order order = buildOrder(request);
            orderMapper.insert(order);
            log.info("訂單創建成功,orderId:{},userId:{}", order.getOrderId(), request.getUserId());

            // 4. 記錄冪等流水(插入t_idempotent_flow表,便于后續追溯)
            recordIdempotentFlow(request, order.getOrderId());

            // 5. 轉換為DTO返回
            OrderDTO orderDTO = new OrderDTO();
            BeanUtils.copyProperties(order, orderDTO);
            return orderDTO;

        } catch (Exception e) {
            log.error("創建訂單失敗,identifier:{},原因:{}", request.getIdentifier(), e.getMessage(), e);
            // 拋出異常,觸發事務回滾
            throw new RuntimeException("創建訂單失敗:" + e.getMessage());
        }
    }

    /**
     * 構建訂單實體(將Request轉換為Order)
     */
    private Order buildOrder(OrderRequest request) {
        Order order = new Order();
        order.setUserId(request.getUserId());
        order.setProductId(request.getProductId());
        order.setQuantity(request.getQuantity());
        // 計算總金額:數量 * 單價
        BigDecimal totalAmount = request.getPrice().multiply(new BigDecimal(request.getQuantity()));
        order.setTotalAmount(totalAmount);
        order.setOrderStatus(0); // 初始狀態:待支付
        order.setIdentifier(request.getIdentifier());
        return order;
    }

    /**
     * 記錄冪等流水(用于后續追溯和冪等判斷)
     */
    private void recordIdempotentFlow(OrderRequest request, Long orderId) {
        IdempotentFlow flow = new IdempotentFlow();
        flow.setBusinessScene("ORDER"); // 業務場景:下單
        flow.setIdentifier(request.getIdentifier());
        flow.setUserId(request.getUserId());
        flow.setHandleStatus(1); // 處理狀態:成功
        flow.setBusinessResult("orderId:" + orderId); // 業務結果:訂單ID
        idempotentFlowMapper.insert(flow);
        log.info("冪等流水記錄成功,flowId:{},orderId:{}", flow.getFlowId(), orderId);
    }

    /**
     * 扣減庫存(簡化邏輯:實際需調用庫存服務,且需加鎖避免超賣)
     */
    private boolean deductStock(Long productId, Integer quantity) {
        // 此處為模擬扣減:實際應操作庫存表(如t_stock),通過UPDATE t_stock SET stock = stock - quantity WHERE product_id = ? AND stock >= quantity
        log.info("扣減庫存成功,productId:{},扣減數量:{}", productId, quantity);
        returntrue;
    }

    /**
     * 訂單請求參數校驗
     */
    private void validateOrderRequest(OrderRequest request) {
        if (request.getQuantity() <= 0) {
            throw new IllegalArgumentException("購買數量必須大于0");
        }
        if (request.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("商品單價必須大于0");
        }
    }
}

落地實踐

@Service
public class OrderApplyService {

    private final OrderService orderService;

    // 構造函數注入訂單服務
    public OrderApplyService(OrderService orderService) {
        this.orderService = orderService;
    }

    /**
     * 下單接口:嚴格遵循“一鎖、二判、三更新”
     * @param request 下單請求(包含用戶ID、商品ID、請求唯一標識identifier等)
     * @return 下單響應
     */
    // 一鎖:加Redis分布式鎖,鎖的場景為“ORDER”,鎖的key為請求唯一標識(確保同一請求僅一個線程執行)
    @DistributeLock(
            scene = "ORDER",          // 鎖的業務場景標識
            keyExpression = "#request.identifier", // 鎖的key:使用請求中的唯一標識(如UUID)
            expire = 3000             // 鎖的過期時間:3秒(避免死鎖)
    )
    public OrderResponse apply(OrderRequest request) {
        OrderResponse response = new OrderResponse();

        // 二判:冪等性判斷(查詢是否已有該請求對應的訂單)
        // 此處通過“商品ID+請求唯一標識”查詢,確保同一請求不會重復創建訂單
        OrderDTO orderDTO = orderService.queryOrder(
                request.getProductId(),  // 商品ID
                request.getIdentifier()  // 請求唯一標識(如前端生成的UUID)
        );

        // 若查詢到訂單,說明是重復請求,直接返回“已處理”結果
        if (orderDTO != null) {
            response.setSuccess(true);
            response.setResponseCode("DUPLICATED"); // 重復請求編碼
            response.setMessage("訂單已存在,無需重復創建");
            response.setOrderId(orderDTO.getOrderId()); // 返回已存在的訂單ID
            return response;
        }

        // 三更新:執行下單業務邏輯(創建訂單、扣減庫存等,確保原子性)
        // 此處orderService.order()方法內部需開啟數據庫事務,保障多表操作的原子性
        OrderDTO createdOrder = orderService.order(request);

        // 組裝并返回成功響應
        response.setSuccess(true);
        response.setResponseCode("SUCCESS");
        response.setMessage("訂單創建成功");
        response.setOrderId(createdOrder.getOrderId());
        return response;
    }
}


責任編輯:武曉燕 來源: 一安未來
相關推薦

2025-08-06 01:25:00

2024-12-09 09:35:00

2021-07-26 07:47:37

無鎖編程CPU

2022-07-04 08:01:01

鎖優化Java虛擬機

2023-10-13 13:30:00

MySQL鎖機制

2009-06-19 14:10:42

Java多態性

2021-08-04 17:40:42

代碼Java消息冪等

2024-03-13 15:18:00

接口冪等性高并發

2021-01-18 14:34:59

冪等性接口客戶端

2024-06-24 01:00:00

2022-05-23 11:35:16

jiekou冪等性

2024-08-29 09:01:39

2009-11-09 17:40:33

WCF配置可靠性

2022-02-18 09:20:43

消息中間件分布式MQ 冪等

2024-11-01 09:28:02

2025-07-25 01:00:00

Redis+接口冪等性

2018-03-22 18:30:22

數據庫MySQL并發控制

2025-02-23 08:00:00

冪等性Java開發

2022-11-07 18:12:54

Go語言函數

2016-12-08 15:36:59

HashMap數據結構hash函數
點贊
收藏

51CTO技術棧公眾號

人妻少妇被粗大爽9797pw| 亚洲一区制服诱惑| mm131丰满少妇人体欣赏图| 精品亚洲美女网站| 亚洲欧美一区二区三区极速播放| 91在线网站视频| 欧美福利视频一区二区| 加勒比久久综合| 日韩午夜在线影院| 亚洲自偷自拍熟女另类| 免费高清在线观看| 不卡的av电影| 成人福利视频网| 天天爽夜夜爽夜夜爽精品| 色综合五月天| 国产视频精品va久久久久久| 成人亚洲免费视频| 欧美亚洲大片| 欧美日韩国产中文字幕| eeuss中文| 暖暖视频在线免费观看| 国产成人免费视频一区| 国产精品27p| 亚洲精品www久久久久久| 婷婷中文字幕一区| 国产亚洲精品一区二区| 中文字幕无码人妻少妇免费| 国产一区二区三区免费观看在线| 日韩欧美一区二区三区| 国产高清www| 黄色一级片在线观看| 久久久久久99精品| 国产在线播放一区二区| 国产丝袜视频在线观看| 日韩精品一二区| 欧美在线视频免费播放| 97人人澡人人爽人人模亚洲| 国产综合自拍| 超碰日本道色综合久久综合| 成年人网站在线观看视频| 欧美日韩xxxx| 亚洲欧美视频在线| 一本色道综合久久欧美日韩精品| 国产精品115| 欧美www视频| 日本一二三四区视频| 午夜精品久久久久久毛片| 欧美日韩亚洲另类| 人人爽人人av| av在线一区不卡| 在线影院国内精品| 白嫩少妇丰满一区二区| 一级毛片久久久| 激情成人中文字幕| 国产主播在线看| 蜜桃麻豆影像在线观看| 精品成人国产在线观看男人呻吟| 成人免费视频91| 丰乳肥臀在线| 午夜精品aaa| 国产精品丝袜久久久久久消防器材| 第一av在线| 亚洲成av人综合在线观看| 欧美一级视频在线播放| 美女露胸视频在线观看| 欧美视频在线观看 亚洲欧| 成年人观看网站| 欧洲精品一区二区三区| 欧美色视频一区| 亚洲精品成人在线播放| 日韩有吗在线观看| 日韩av一卡二卡| 性色av蜜臀av色欲av| 国产99久久| zzijzzij亚洲日本成熟少妇| 青草影院在线观看| 亚洲韩日在线| 国产精品观看在线亚洲人成网| 又污又黄的网站| 国产精品白丝jk黑袜喷水| 成人av电影免费| 欧美女同网站| 自拍偷拍亚洲激情| 欧美又粗又长又爽做受| 欧美美女日韩| 欧美高清视频www夜色资源网| 91香蕉视频在线观看视频| 激情小说亚洲色图| 国产一区二区三区日韩欧美| 成人免费毛片东京热| 一区在线免费| 国产v综合v亚洲欧美久久| 国产视频手机在线观看| 91丝袜高跟美女视频| 艳色歌舞团一区二区三区| 黄污视频在线观看| 91久久国产综合久久| 国产精品熟女一区二区不卡| 亚洲人成网站77777在线观看 | 黄色一级片免费播放| 欧洲亚洲视频| 久久成人人人人精品欧| 国产又黄又猛又粗又爽| 国产一区二区91| 欧美日韩成人一区二区三区| av网站导航在线观看免费| 岛国av一区二区| 欧美专区第二页| 欧美艳星介绍134位艳星| 欧美情侣性视频| 夜夜躁很很躁日日躁麻豆| 91片在线免费观看| 福利视频免费在线观看| 亚洲精品aaa| 亚洲嫩模很污视频| 欧美日韩在线视频免费播放| 日韩国产精品91| 国严精品久久久久久亚洲影视 | 91chinesevideo永久地址| 伊人免费在线观看| 久久先锋资源网| 真人抽搐一进一出视频| 日韩欧洲国产| 久久精品一偷一偷国产| 最近中文字幕免费观看| 久久久综合精品| 久久国产精品网| 免费观看在线一区二区三区| 久久久99久久精品女同性| 美女黄页在线观看| 国产清纯在线一区二区www| 免费成人在线视频网站| 超碰97成人| 久久久久久国产精品三级玉女聊斋| 国产又黄又大又爽| 国产精品乱人伦中文| 国产wwwxx| 国产一区二区区别| 欧美与黑人午夜性猛交久久久| 亚洲精品国产精| 依依成人精品视频| 在线视频观看一区二区| 99久久www免费| 国产精品中文字幕在线| 91精彩在线视频| 欧美日韩一区二区在线观看视频| 能免费看av的网站| 久久久国产亚洲精品| 蜜桃久久精品乱码一区二区| 精品三级久久| 亚洲精品一二区| 亚洲午夜18毛片在线看| 久久久影视传媒| 精品日韩久久久| 999成人网| 亚洲一区免费网站| 高h视频在线播放| 亚洲国产精品字幕| 中文字幕精品无码一区二区| 久久精品夜夜夜夜久久| 992kp快乐看片永久免费网址| 欧美午夜精品一区二区三区电影| 国产欧美日韩中文字幕| 黄色在线免费看| 欧美成人官网二区| 日本少妇在线观看| 91蝌蚪porny| 91插插插插插插插插| 亚洲乱码电影| 国产精品我不卡| 韩漫成人漫画| 久久精品成人欧美大片| 午夜久久久久久久久久| 精品国产乱码久久久久久天美| 亚洲av综合一区二区| 免费的成人av| 无码av天堂一区二区三区| 久久99国内| 成人免费网视频| 一色桃子av在线| 亚洲精品视频在线观看视频| 在线观看免费黄色小视频| 夜夜夜精品看看| 波多野结衣一本| 久久成人久久鬼色| 成年人午夜免费视频| av中文字幕一区二区| 国产日本欧美一区二区三区| 成年人国产在线观看| 在线观看国产成人av片| а√中文在线资源库| 色综合天天综合在线视频| 日韩在线一卡二卡| 91网站最新网址| 国产999免费视频| 久久久蜜桃一区二区人| 韩国黄色一级大片| 国产精品手机在线播放| 97自拍视频| 香蕉成人影院| 午夜精品福利视频| 老司机在线看片网av| 亚洲精品福利免费在线观看| 国产精品久久久久久在线| 懂色aⅴ精品一区二区三区蜜月| 亚洲一级片在线播放| 白白色亚洲国产精品| 91pony九色| 久久一区国产| 国产高清av在线播放| 99视频精品视频高清免费| 免费精品视频一区| 国产一级成人av| 91嫩草免费看| 亚洲欧洲二区| 国产精品v片在线观看不卡| 国产传媒在线观看| 美女精品视频一区| 午夜免费视频在线国产| 亚洲欧美日韩精品久久| 人人妻人人澡人人爽精品日本| 777亚洲妇女| 中文字幕乱码在线观看| 色偷偷久久一区二区三区| 久久精品这里有| 亚洲激情图片小说视频| 午夜精品福利在线视频| 国产精品福利一区| 美国黄色特级片| 欧美极品少妇xxxxⅹ高跟鞋| www.色多多| av网站免费线看精品| 老司机免费视频| 成人午夜激情在线| 人妻激情偷乱视频一区二区三区| 免费成人在线影院| 182午夜在线观看| 喷水一区二区三区| 成人免费在线观看视频网站| 日本午夜精品一区二区三区电影 | 精品在线播放免费| 欧美黄色性生活| 日本成人中文字幕在线视频| 日本男人操女人| 日韩国产精品久久久久久亚洲| 黄色三级视频片| 日产国产高清一区二区三区| 日韩欧美精品在线观看视频| 久久精品官网| 天天综合网日韩| 韩国av一区二区三区在线观看| 五月天婷婷影视| 国产精品影视在线观看| 免费黄视频在线观看| 国产v综合v亚洲欧| 欧美一区二区免费在线观看| 久久综合狠狠综合久久激情 | www.国产视频| 亚洲国产欧美一区二区三区同亚洲 | 久久在线91| 天天干天天干天天干天天干天天干| 毛片av中文字幕一区二区| 看看黄色一级片| 国产91精品一区二区| 99精品一区二区三区无码吞精| 久久免费视频一区| 美国精品一区二区| 亚洲美女区一区| 国产亚洲精品av| 欧美三级xxx| 伊人网综合在线| 欧美一区二区三区在线视频 | av日韩一区| 官网99热精品| 国产探花一区二区| 秋霞在线一区二区| 在线日韩视频| 亚洲成人av免费看| 国产精品456露脸| 蜜桃传媒一区二区亚洲av| 国产精品乱人伦中文| 国产精品9191| 欧美亚洲国产一区二区三区va| 国内精品国产成人国产三级| 亚洲黄一区二区| 在线观看国产原创自拍视频| 欧美激情视频三区| 成人黄色免费短视频| 成人网在线视频| 先锋影音国产精品| 精品国产三级a∨在线| 日韩一级大片| 国产精品嫩草影视| 国产日韩欧美综合在线| 美女的奶胸大爽爽大片| 色悠悠久久综合| 精品久久久无码中文字幕| 亚洲欧美一区二区精品久久久| 国产在线看片| 日本精品视频在线播放| 香蕉大人久久国产成人av| 日韩av一区二区三区在线观看| 欧美日韩精品一本二本三本| 色悠悠久久综合网| 91丨九色丨蝌蚪富婆spa| 亚洲欧美精品aaaaaa片| 欧美日韩国产色视频| 99久久精品日本一区二区免费| 亚洲欧美精品在线| 91白丝在线| 亚洲一区二区三区sesese| 国产成人影院| 成 年 人 黄 色 大 片大 全| 国内精品免费在线观看| 美女被到爽高潮视频| 亚洲国产一二三| 国产色片在线观看| 日韩在线中文字| 香蕉视频亚洲一级| 精品在线不卡| 国产综合自拍| 亚洲熟女乱综合一区二区| 国产精品久久久久影院老司 | 538精品在线观看| 欧美午夜精品免费| 狠狠狠综合7777久夜色撩人| 欧美亚洲国产视频| 欧美黑白配在线| 久久99久久99精品| 高清在线不卡av| 精品爆乳一区二区三区无码av| 69p69国产精品| 91看片在线观看| 国产精品一区专区欧美日韩| 精品国产精品国产偷麻豆| 波多野结衣家庭教师视频| 91网站黄www| 欧美一区二区三区网站| 亚洲欧洲午夜一线一品| 一区二区三区短视频| 欧美久久在线| 日韩精品一区第一页| av永久免费观看| 欧美性色黄大片手机版| 2017亚洲天堂1024| 成人黄色在线免费| 伊人久久大香线蕉精品组织观看| 一级黄色高清视频| 亚洲九九爱视频| 亚洲精品无amm毛片| 欧美激情一区二区三区成人| 91免费精品国偷自产在线在线| 成人小视频在线观看免费| 成人av网址在线观看| 国产高清中文字幕| 亚洲视频在线播放| 欧美成人一二区| 麻豆传媒网站在线观看| 成人免费福利片| 秋霞av一区二区三区| 色偷偷av一区二区三区乱| 视频在线一区| 国产一区二区在线视频播放| 国产欧美精品区一区二区三区 | 怡红院av久久久久久久| 中文字幕日本精品| 亚洲一区二区三区日本久久九| 日本中文字幕亚洲| 国产欧美一区二区精品性色| 国产精品高潮呻吟AV无码| 久久久久久久激情视频| 国产精品一在线观看| 午夜视频在线网站| 亚洲一区二区三区在线看| 日本一区视频| 成人激情在线播放| 99亚洲一区二区| 又嫩又硬又黄又爽的视频| 欧美成人伊人久久综合网| 色吧亚洲日本| 亚洲午夜精品一区二区| 国产成人av福利| 欧美日韩在线视频播放| 久久999免费视频| 国产中文字幕一区二区三区 | 97成人超碰视| 在线观看毛片av| 97在线视频一区| 亚洲电影影音先锋| 一级做a爰片毛片| 欧美高清视频www夜色资源网| 在线看片福利| 日本一二三区视频在线| 久久久久久久网| 成人福利小视频| 国产精品男人的天堂| 最新日韩在线| 无码黑人精品一区二区| 国产亚洲a∨片在线观看| 第四色中文综合网|