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

Spring Boot 實現接口冪等性的四種方案

開發 前端
冪等性是開發當中很常見也很重要的一個需求,尤其是支付、訂單等與金錢掛鉤的服務,保證接口冪等性尤其重要。

一、什么是冪等性

冪等是一個數學與計算機學概念,在數學中某一元運算為冪等時,其作用在任一元素兩次后會和其作用一次的結果相同。

在計算機中編程中,一個冪等操作的特點是其任意多次執行所產生的影響均與一次執行的影響相同。冪等函數或冪等方法是指可以使用相同參數重復執行,并能獲得相同結果的函數。這些函數不會影響系統狀態,也不用擔心重復執行會對系統造成改變。

二、什么是接口冪等性

在HTTP/1.1中,對冪等性進行了定義。它描述了一次和多次請求某一個資源對于資源本身應該具有同樣的結果(網絡超時等問題除外),即第一次請求的時候對資源產生了副作用,但是以后的多次請求都不會再對資源產生副作用。

這里的副作用是不會對結果產生破壞或者產生不可預料的結果。也就是說,其任意多次執行對資源本身所產生的影響均與一次執行的影響相同。

三、為什么需要實現冪等性

在接口調用時一般情況下都能正常返回信息不會重復提交,不過在遇見以下情況時可以就會出現問題,如:

  • 前端重復提交表單: 在填寫一些表格時候,用戶填寫完成提交,很多時候會因網絡波動沒有及時對用戶做出提交成功響應,致使用戶認為沒有成功提交,然后一直點提交按鈕,這時就會發生重復提交表單請求。
  • 用戶惡意進行刷單: 例如在實現用戶投票這種功能時,如果用戶針對一個用戶進行重復提交投票,這樣會導致接口接收到用戶重復提交的投票信息,這樣會使投票結果與事實嚴重不符。
  • 接口超時重復提交: 很多時候 HTTP 客戶端工具都默認開啟超時重試的機制,尤其是第三方調用接口時候,為了防止網絡波動超時等造成的請求失敗,都會添加重試機制,導致一個請求提交多次。
  • 消息進行重復消費: 當使用 MQ 消息中間件時候,如果發生消息中間件出現錯誤未及時提交消費信息,導致發生重復消費。

使用冪等性最大的優勢在于使接口保證任何冪等性操作,免去因重試等造成系統產生的未知的問題。

四、引入冪等性后對系統的影響

冪等性是為了簡化客戶端邏輯處理,能放置重復提交等操作,但卻增加了服務端的邏輯復雜性和成本,其主要是:

  • 把并行執行的功能改為串行執行,降低了執行效率。
  • 增加了額外控制冪等的業務邏輯,復雜化了業務功能;

所以在使用時候需要考慮是否引入冪等性的必要性,根據實際業務場景具體分析,除了業務上的特殊要求外,一般情況下不需要引入的接口冪等性。

五、Restful API 接口的冪等性

現在流行的 Restful 推薦的幾種 HTTP 接口方法中,分別存在冪等行與不能保證冪等的方法,如下:

  • √ 滿足冪等
  • x 不滿足冪等
  • - 可能滿足也可能不滿足冪等,根據實際業務邏輯有關

方法類型

是否冪等

描述

Get


Get 方法用于獲取資源。其一般不會也不應當對系統資源進行改變,所以是冪等的。

Post

×

Post 方法一般用于創建新的資源。其每次執行都會新增數據,所以不是冪等的。

Put

-

Put 方法一般用于修改資源。該操作則分情況來判斷是不是滿足冪等,更新操作中直接根據某個值進行更新,也能保持冪等。不過執行累加操作的更新是非冪等。

Delete

-

Delete 方法一般用于刪除資源。該操作則分情況來判斷是不是滿足冪等,當根據唯一值進行刪除時,刪除同一個數據多次執行效果一樣。不過需要注意,帶查詢條件的刪除則就不一定滿足冪等了。例如在根據條件刪除一批數據后,這時候新增加了一條數據也滿足條件,然后又執行了一次刪除,那么將會導致新增加的這條滿足條件數據也被刪除。

六、如何實現冪等性

方案一:數據庫唯一主鍵

方案描述

數據庫唯一主鍵的實現主要是利用數據庫中主鍵唯一約束的特性,一般來說唯一主鍵比較適用于“插入”時的冪等性,其能保證一張表中只能存在一條帶該唯一主鍵的記錄。

使用數據庫唯一主鍵完成冪等性時需要注意的是,該主鍵一般來說并不是使用數據庫中自增主鍵,而是使用分布式 ID 充當主鍵(可以參考 Java 中分布式 ID 的設計方案 這篇文章),這樣才能能保證在分布式環境下 ID 的全局唯一性。

適用操作:

  • 插入操作
  • 刪除操作

使用限制:

  • 需要生成全局唯一主鍵 ID;

主要流程:

圖片

主要流程:

  • ① 客戶端執行創建請求,調用服務端接口。
  • ② 服務端執行業務邏輯,生成一個分布式 ID,將該 ID 充當待插入數據的主鍵,然后執數據插入操作,運行對應的 SQL 語句。
  • ③ 服務端將該條數據插入數據庫中,如果插入成功則表示沒有重復調用接口。如果拋出主鍵重復異常,則表示數據庫中已經存在該條記錄,返回錯誤信息到客戶端。

方案二:數據庫樂觀鎖

方案描述:

數據庫樂觀鎖方案一般只能適用于執行“更新操作”的過程,我們可以提前在對應的數據表中多添加一個字段,充當當前數據的版本標識。這樣每次對該數據庫該表的這條數據執行更新時,都會將該版本標識作為一個條件,值為上次待更新數據中的版本標識的值。

適用操作:

  • 更新操作

使用限制:

  • 需要數據庫對應業務表中添加額外字段;

描述示例:

圖片

例如,存在如下的數據表中:

id

name

price

1

小米手機

1000

2

蘋果手機

2500

3

華為手機

1600

為了每次執行更新時防止重復更新,確定更新的一定是要更新的內容,我們通常都會添加一個 version 字段記錄當前的記錄版本,這樣在更新時候將該值帶上,那么只要執行更新操作就能確定一定更新的是某個對應版本下的信息。

id

name

price

version

1

小米手機

1000

10

2

蘋果手機

2500

21

3

華為手機

1600

5

這樣每次執行更新時候,都要指定要更新的版本號,如下操作就能準確更新 versinotallow=5 的信息:

UPDATE my_table SET price=price+50,versinotallow=version+1 WHERE id=1 AND versinotallow=5

上面 WHERE 后面跟著條件 id=1 AND versinotallow=5 被執行后,id=1 的 version 被更新為 6,所以如果重復執行該條 SQL 語句將不生效,因為 id=1 AND versinotallow=5 的數據已經不存在,這樣就能保住更新的冪等,多次更新對結果不會產生影響。

方案三:防重 Token 令牌

方案描述:

針對客戶端連續點擊或者調用方的超時重試等情況,例如提交訂單,此種操作就可以用 Token 的機制實現防止重復提交。簡單的說就是調用方在調用接口的時候先向后端請求一個全局 ID(Token),請求的時候攜帶這個全局 ID 一起請求(Token 最好將其放到 Headers 中),后端需要對這個 Token 作為 Key,用戶信息作為 Value 到 Redis 中進行鍵值內容校驗,如果 Key 存在且 Value 匹配就執行刪除命令,然后正常執行后面的業務邏輯。如果不存在對應的 Key 或 Value 不匹配就返回重復執行的錯誤信息,這樣來保證冪等操作。

適用操作:

  • 插入操作
  • 更新操作
  • 刪除操作

使用限制:

  • 需要生成全局唯一 Token 串;
  • 需要使用第三方組件 Redis 進行數據效驗;

主要流程:

圖片

① 服務端提供獲取 Token 的接口,該 Token 可以是一個序列號,也可以是一個分布式 ID 或者 UUID 串。

② 客戶端調用接口獲取 Token,這時候服務端會生成一個 Token 串。

③ 然后將該串存入 Redis 數據庫中,以該 Token 作為 Redis 的鍵(注意設置過期時間)。

④ 將 Token 返回到客戶端,客戶端拿到后應存到表單隱藏域中。

⑤ 客戶端在執行提交表單時,把 Token 存入到 Headers 中,執行業務請求帶上該 Headers。

⑥ 服務端接收到請求后從 Headers 中拿到 Token,然后根據 Token 到 Redis 中查找該 key 是否存在。

⑦ 服務端根據 Redis 中是否存該 key 進行判斷,如果存在就將該 key 刪除,然后正常執行業務邏輯。如果不存在就拋異常,返回重復提交的錯誤信息。

注意,在并發情況下,執行 Redis 查找數據與刪除需要保證原子性,否則很可能在并發下無法保證冪等性。其實現方法可以使用分布式鎖或者使用 Lua 表達式來注銷查詢與刪除操作。

方案四、下游傳遞唯一序列號

方案描述:

所謂請求序列號,其實就是每次向服務端請求時候附帶一個短時間內唯一不重復的序列號,該序列號可以是一個有序 ID,也可以是一個訂單號,一般由下游生成,在調用上游服務端接口時附加該序列號和用于認證的 ID。

當上游服務器收到請求信息后拿取該 序列號 和下游 認證ID 進行組合,形成用于操作 Redis 的 Key,然后到 Redis 中查詢是否存在對應的 Key 的鍵值對,根據其結果:

  • 如果存在,就說明已經對該下游的該序列號的請求進行了業務處理,這時可以直接響應重復請求的錯誤信息。
  • 如果不存在,就以該 Key 作為 Redis 的鍵,以下游關鍵信息作為存儲的值(例如下游商傳遞的一些業務邏輯信息),將該鍵值對存儲到 Redis 中 ,然后再正常執行對應的業務邏輯即可。

適用操作:

  • 插入操作
  • 更新操作
  • 刪除操作

使用限制:

  • 要求第三方傳遞唯一序列號;
  • 需要使用第三方組件 Redis 進行數據效驗;

主要流程:

圖片圖片

主要步驟:

① 下游服務生成分布式 ID 作為序列號,然后執行請求調用上游接口,并附帶“唯一序列號”與請求的“認證憑據ID”。

② 上游服務進行安全效驗,檢測下游傳遞的參數中是否存在“序列號”和“憑據ID”。

③ 上游服務到 Redis 中檢測是否存在對應的“序列號”與“認證ID”組成的 Key,如果存在就拋出重復執行的異常信息,然后響應下游對應的錯誤信息。如果不存在就以該“序列號”和“認證ID”組合作為 Key,以下游關鍵信息作為 Value,進而存儲到 Redis 中,然后正常執行接來來的業務邏輯。

上面步驟中插入數據到 Redis 一定要設置過期時間。這樣能保證在這個時間范圍內,如果重復調用接口,則能夠進行判斷識別。如果不設置過期時間,很可能導致數據無限量的存入 Redis,致使 Redis 不能正常工作。

七、實現接口冪等示例

這里使用防重 Token 令牌方案,該方案能保證在不同請求動作下的冪等性,實現邏輯可以看上面寫的”防重 Token 令牌”方案,接下來寫下實現這個邏輯的代碼。

1、Maven 引入相關依賴

這里使用 Maven 工具管理依賴,這里在 pom.xml 中引入 SpringBoot、Redis、lombok 相關依賴。

<?xml versinotallow="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.4.RELEASE</version>
    </parent>

    <groupId>mydlq.club</groupId>
    <artifactId>springboot-idempotent-token</artifactId>
    <version>0.0.1</version>
    <name>springboot-idempotent-token</name>
    <description>Idempotent Demo</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <!--springboot web-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <!--springboot data redis-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-pool2</artifactId>
        </dependency>
        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2、配置連接 Redis 的參數

在 application 配置文件中配置連接 Redis 的參數。Spring Boot 基礎就不介紹了,最新教程推薦看下面的教程。

如下:

spring:
  redis:
    ssl: false
    host: 127.0.0.1
    port: 6379
    database: 0
    timeout: 1000
    password:
    lettuce:
      pool:
        max-active: 100
        max-wait: -1
        min-idle: 0
        max-idle: 20

3、創建與驗證 Token 工具類

創建用于操作 Token 相關的 Service 類,里面存在 Token 創建與驗證方法,其中:

  • Token 創建方法: 使用 UUID 工具創建 Token 串,設置以 “idempotent_token:“+“Token串” 作為 Key,以用戶信息當成 Value,將信息存入 Redis 中。
  • Token 驗證方法: 接收 Token 串參數,加上 Key 前綴形成 Key,再傳入 value 值,執行 Lua 表達式(Lua 表達式能保證命令執行的原子性)進行查找對應 Key 與刪除操作。執行完成后驗證命令的返回結果,如果結果不為空且非0,則驗證成功,否則失敗。
import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class TokenUtilService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 存入 Redis 的 Token 鍵的前綴
     */
    private static final String IDEMPOTENT_TOKEN_PREFIX = "idempotent_token:";

    /**
     * 創建 Token 存入 Redis,并返回該 Token
     *
     * @param value 用于輔助驗證的 value 值
     * @return 生成的 Token 串
     */
    public String generateToken(String value) {
        // 實例化生成 ID 工具對象
        String token = UUID.randomUUID().toString();
        // 設置存入 Redis 的 Key
        String key = IDEMPOTENT_TOKEN_PREFIX + token;
        // 存儲 Token 到 Redis,且設置過期時間為5分鐘
        redisTemplate.opsForValue().set(key, value, 5, TimeUnit.MINUTES);
        // 返回 Token
        return token;
    }

    /**
     * 驗證 Token 正確性
     *
     * @param token token 字符串
     * @param value value 存儲在Redis中的輔助驗證信息
     * @return 驗證結果
     */
    public boolean validToken(String token, String value) {
        // 設置 Lua 腳本,其中 KEYS[1] 是 key,KEYS[2] 是 value
        String script = "if redis.call('get', KEYS[1]) == KEYS[2] then return redis.call('del', KEYS[1]) else return 0 end";
        RedisScript<Long> redisScript = new DefaultRedisScript<>(script, Long.class);
        // 根據 Key 前綴拼接 Key
        String key = IDEMPOTENT_TOKEN_PREFIX + token;
        // 執行 Lua 腳本
        Long result = redisTemplate.execute(redisScript, Arrays.asList(key, value));
        // 根據返回結果判斷是否成功成功匹配并刪除 Redis 鍵值對,若果結果不為空和0,則驗證通過
        if (result != null && result != 0L) {
            log.info("驗證 token={},key={},value={} 成功", token, key, value);
            return true;
        }
        log.info("驗證 token={},key={},value={} 失敗", token, key, value);
        return false;
    }

}

4、創建測試的 Controller 類

創建用于測試的 Controller 類,里面有獲取 Token 與測試接口冪等性的接口,內容如下:

import lombok.extern.slf4j.Slf4j;
import mydlq.club.example.service.TokenUtilService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@Slf4j
@RestController
public class TokenController {

    @Autowired
    private TokenUtilService tokenService;

    /**
     * 獲取 Token 接口
     *
     * @return Token 串
     */
    @GetMapping("/token")
    public String getToken() {
        // 獲取用戶信息(這里使用模擬數據)
        // 注:這里存儲該內容只是舉例,其作用為輔助驗證,使其驗證邏輯更安全,如這里存儲用戶信息,其目的為:
        // - 1)、使用"token"驗證 Redis 中是否存在對應的 Key
        // - 2)、使用"用戶信息"驗證 Redis 的 Value 是否匹配。
        String userInfo = "mydlq";
        // 獲取 Token 字符串,并返回
        return tokenService.generateToken(userInfo);
    }

    /**
     * 接口冪等性測試接口
     *
     * @param token 冪等 Token 串
     * @return 執行結果
     */
    @PostMapping("/test")
    public String test(@RequestHeader(value = "token") String token) {
        // 獲取用戶信息(這里使用模擬數據)
        String userInfo = "mydlq";
        // 根據 Token 和與用戶相關的信息到 Redis 驗證是否存在對應的信息
        boolean result = tokenService.validToken(token, userInfo);
        // 根據驗證結果響應不同信息
        return result ? "正常調用" : "重復調用";
    }

}

5、創建 SpringBoot 啟動類

創建啟動類,用于啟動 SpringBoot 應用。基礎教程就不介紹了,建議看下下面的教程,很全了。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

6、寫測試類進行測試

寫個測試類進行測試,多次訪問同一個接口,測試是否只有第一次能否執行成功。

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class IdempotenceTest {

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Test
    public void interfaceIdempotenceTest() throws Exception {
        // 初始化 MockMvc
        MockMvc mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
        // 調用獲取 Token 接口
        String token = mockMvc.perform(MockMvcRequestBuilders.get("/token")
                .accept(MediaType.TEXT_HTML))
                .andReturn()
                .getResponse().getContentAsString();
        log.info("獲取的 Token 串:{}", token);
        // 循環調用 5 次進行測試
        for (int i = 1; i <= 5; i++) {
            log.info("第{}次調用測試接口", i);
            // 調用驗證接口并打印結果
            String result = mockMvc.perform(MockMvcRequestBuilders.post("/test")
                    .header("token", token)
                    .accept(MediaType.TEXT_HTML))
                    .andReturn().getResponse().getContentAsString();
            log.info(result);
            // 結果斷言
            if (i == 0) {
                Assert.assertEquals(result, "正常調用");
            } else {
                Assert.assertEquals(result, "重復調用");
            }
        }
    }

}

 阿里面試考題 | 沖擊一線大廠,可下載 pdf

顯示如下:

[main] IdempotenceTest:  獲取的 Token 串:980ea707-ce2e-456e-a059-0a03332110b4
[main] IdempotenceTest:  第1次調用測試接口
[main] IdempotenceTest:  正常調用
[main] IdempotenceTest:  第2次調用測試接口
[main] IdempotenceTest:  重復調用
[main] IdempotenceTest:  第3次調用測試接口
[main] IdempotenceTest:  重復調用
[main] IdempotenceTest:  第4次調用測試接口
[main] IdempotenceTest:  重復調用
[main] IdempotenceTest:  第5次調用測試接口
[main] IdempotenceTest:  重復調用

八、最后總結

冪等性是開發當中很常見也很重要的一個需求,尤其是支付、訂單等與金錢掛鉤的服務,保證接口冪等性尤其重要。在實際開發中,我們需要針對不同的業務場景我們需要靈活的選擇冪等性的實現方式:

  • 對于下單等存在唯一主鍵的,可以使用“唯一主鍵方案”的方式實現。
  • 對于更新訂單狀態等相關的更新場景操作,使用“樂觀鎖方案”實現更為簡單。
  • 對于上下游這種,下游請求上游,上游服務可以使用“下游傳遞唯一序列號方案”更為合理。
  • 類似于前端重復提交、重復下單、沒有唯一ID號的場景,可以通過 Token 與 Redis 配合的“防重 Token 方案”實現更為快捷。

上面只是給與一些建議,再次強調一下,實現冪等性需要先理解自身業務需求,根據業務邏輯來實現這樣才合理,處理好其中的每一個結點細節,完善整體的業務流程設計,才能更好的保證系統的正常運行。最后做一個簡單總結

方案名稱

適用方法

實現復雜度

方案缺點

數據庫唯一主鍵

插入操作 刪除操作

簡單

- 只能用于插入操作;- 只能用于存在唯一主鍵場景;

數據庫樂觀鎖

更新操作

簡單

- 只能用于更新操作;- 表中需要額外添加字段;

請求序列號

插入操作 更新操作 刪除操作

簡單

- 需要保證下游生成唯一序列號;- 需要 Redis 第三方存儲已經請求的序列號;

防重 Token 令牌

插入操作 更新操作 刪除操作

適中

- 需要 Redis 第三方存儲生成的 Token 串;


責任編輯:武曉燕 來源: JAVA日知錄
相關推薦

2024-06-24 01:00:00

2024-11-07 11:17:50

2022-04-25 11:26:16

開發SpringBoot

2020-11-12 07:43:06

Redis冪等性接口

2022-05-23 11:35:16

jiekou冪等性

2024-11-01 09:28:02

2025-09-02 07:16:37

2025-03-17 08:07:11

2023-08-29 13:53:00

前端攔截HashMap

2025-10-24 07:52:56

2025-04-18 03:00:00

2024-03-13 15:18:00

接口冪等性高并發

2025-01-15 12:43:23

2025-07-25 01:00:00

Redis+接口冪等性

2025-02-23 08:00:00

冪等性Java開發

2021-01-18 14:34:59

冪等性接口客戶端

2025-02-18 16:27:01

2011-03-16 09:05:53

NATiptables

2025-06-06 08:28:56

2021-01-13 11:23:59

分布式冪等性支付
點贊
收藏

51CTO技術棧公眾號

久久久久久久电影一区| 7777精品伊人久久久大香线蕉的| 粉嫩高清一区二区三区精品视频| 久久免费播放视频| 美国成人xxx| 日本精品一区二区三区四区的功能| 视频一区国产精品| 国产哺乳奶水91在线播放| 欧美日韩国产亚洲一区| 亚洲人成在线播放| 91aaa精品| 黄视频网站在线观看| 国产清纯在线一区二区www| 国产日韩欧美视频| 日韩经典在线观看| 99久久激情| 亚洲精品wwww| www.日本久久| 国产精品伦理| 亚洲精品国产a| 午夜欧美性电影| 少妇高潮一区二区三区99小说| 蜜桃视频一区二区| 91av网站在线播放| 国产精品九九九九九九| 日韩三级在线| 亚洲奶大毛多的老太婆| 无码人妻丰满熟妇区毛片蜜桃精品 | 国产精品综合二区| 国产精品com| 91精品国产乱码久久久张津瑜| 久久久久国产精品| 一区二区三区 在线观看视| 美女久久久久久久久| 成人激情久久| 精品视频免费在线| 欧在线一二三四区| 高清精品在线| 午夜久久久久久久久久一区二区| 秋霞在线一区二区| 二区在线视频| 国产偷国产偷精品高清尤物| 国产在线精品一区| 人人妻人人玩人人澡人人爽| 国产成人免费av在线| 亚洲综合在线小说| 99久久精品国产一区色| 精品一区二区三区在线观看| 国产精品久久久久久久久久| 色av性av丰满av| 亚洲永久视频| 欧美一区二区.| 亚洲 欧美 日韩 综合| 亚洲精品九九| 97avcom| 四虎成人永久免费视频| 国产精品嫩草99av在线| 91成人在线视频| 国产超碰人人爽人人做人人爱| 99av国产精品欲麻豆| 国外成人性视频| 国产在线视频第一页| 激情亚洲网站| 69av在线视频| 日韩在线 中文字幕| 久久尤物视频| 国产剧情久久久久久| 在线视频欧美亚洲| 国产一区二区影院| 99视频国产精品免费观看| 亚洲xxxx天美| 97se亚洲国产综合自在线不卡| 久久日韩精品| 91精品专区| 亚洲免费av网站| www.av蜜桃| 亚洲永久av| 欧美日韩精品二区第二页| 网站在线你懂的| 亚洲视频精选| 精品亚洲一区二区三区在线播放 | 亚洲欧洲国产专区| 日本a在线天堂| 日本三级一区| 欧美日韩国产大片| 乱码一区二区三区| 国产a久久精品一区二区三区 | 日韩欧美久久久| 日本黄色动态图| 精品亚洲成人| 欧美福利视频在线| 无码人妻精品一区二| 麻豆国产欧美日韩综合精品二区 | 亚洲人成伊人成综合图片| 在线观看不卡av| 九九热精品在线观看| 母乳一区在线观看| 成人精品在线观看| 亚洲欧洲国产综合| 亚洲视频 欧洲视频| 欧美 日本 亚洲| 亚洲一区二区三区久久久| 亚洲激情在线观看视频免费| 调教驯服丰满美艳麻麻在线视频 | 午夜精品久久久久久久无码| 97人人做人人爽香蕉精品| 欧美成人一级视频| 手机毛片在线观看| 亚洲精品欧美| 成人精品视频在线| 国产人成在线视频| 亚洲国产视频直播| 亚洲图色中文字幕| 国产精品三级| 久久男人的天堂| 亚洲天堂999| 91网站黄www| 大地资源网在线观看免费官网| 欧美三级精品| 亚洲国产另类 国产精品国产免费| 久草福利资源在线| 免费国产自线拍一欧美视频| 成人影片在线播放| 日本激情在线观看| 在线观看成人小视频| 中文字幕人妻一区二区三区| 中国精品18videos性欧美| 国产精品国产三级国产aⅴ浪潮 | 99这里只有精品| 一道本在线观看视频| 999国产精品亚洲77777| 国产午夜精品理论片a级探花| 欧美精品久久久久性色| 极品美女销魂一区二区三区免费| 日韩欧美亚洲精品| 成人做爰视频www网站小优视频| 亚洲第一免费播放区| 黄色在线观看免费| 国产在线视频不卡二| 亚洲日本一区二区三区在线不卡| 国产伦精品一区二区三区视频金莲| 亚洲成人999| 国产第一页在线播放| 国产剧情一区二区| 中文字幕の友人北条麻妃| 9999精品视频| 欧美成人精品xxx| av综合在线观看| 亚洲男人的天堂在线观看| 国产高清av片| 亚洲午夜精品一区二区国产 | 欧美精品激情视频| 成人av无码一区二区三区| 亚洲女同一区二区| 97免费公开视频| 亚洲自拍偷拍网| 亚洲综合日韩在线| av资源在线看片| 日韩精品免费在线视频观看| 亚洲精品男人的天堂| 久久老女人爱爱| 91热这里只有精品| 99久久精品费精品国产风间由美 | 国产精品男女| 欧美自拍大量在线观看| 黄色大片在线免费观看| 欧美午夜电影在线播放| 久久久久麻豆v国产| 狠狠网亚洲精品| 国产精品无码免费专区午夜| 精品国产18久久久久久洗澡| 热草久综合在线| h视频在线播放| 欧美一区二区视频在线观看2022 | 嫩草成人www欧美| 四虎影视永久免费在线观看一区二区三区 | 亚洲黄一区二区三区| 欧美图片自拍偷拍| 久久国产99| 在线观看一区二区三区三州| 日韩三级av高清片| 欧美在线xxx| 日韩精品黄色| 亚洲第一av在线| 在线观看av大片| 一级特黄大欧美久久久| 免费黄色在线视频| 韩国av一区二区三区四区| 给我免费播放片在线观看| 欧洲乱码伦视频免费| 97伦理在线四区| 91精品影视| 久久久久久久久久久人体| 第一页在线观看| 精品日产卡一卡二卡麻豆| 中文字幕在线天堂| 亚洲一区二区综合| 精品人妻中文无码av在线| 福利一区福利二区| 亚洲综合在线网站| 1024日韩| 亚洲一区二区在线看| 日韩极品在线| 91中文字幕在线| 天天综合网站| 欧美激情喷水视频| 色欧美激情视频在线| 亚洲国产中文字幕在线观看| 一区二区三区亚洲视频| 五月激情丁香一区二区三区| 久久99久久99精品免费看小说| 91丨九色porny丨蝌蚪| 一级片免费在线观看视频| 日韩激情中文字幕| 久激情内射婷内射蜜桃| 91精品亚洲| 日韩免费av电影| 欧美一区 二区| 99国产精品久久久久老师| 成人日韩av| 日本一区二区三区在线播放| 电影k8一区二区三区久久 | 精品国产一二三区| 国产又粗又黄又爽视频| 91国产精品成人| 中文字幕视频网站| 午夜精品福利视频网站| 欧美丰满艳妇bbwbbw| 日韩一区在线免费观看| 国产黄色大片免费看| 久久综合99re88久久爱| 青青草视频网站| 成人免费视频一区| 中文字幕视频观看| 国产98色在线|日韩| 人妻少妇偷人精品久久久任期| 麻豆精品一区二区av白丝在线| 男人操女人免费| 麻豆精品91| av观看免费在线| 免费看黄裸体一级大秀欧美| 无罩大乳的熟妇正在播放| 99国产精品久久久久久久成人热| 国产 国语对白 露脸| 女人香蕉久久**毛片精品| 日韩第一页在线观看| 欧美69视频| 成人免费在线视频播放| 欧美日韩中文| 国产一区二区视频播放| 在线亚洲自拍| 黄色a级片免费| 日本视频在线一区| 在线免费观看视频黄| 老色鬼精品视频在线观看播放| 伊人网在线综合| 狠狠色综合日日| 无码人妻丰满熟妇啪啪网站| 成人av电影在线观看| av无码一区二区三区| 91麻豆123| 亚洲第一视频区| 亚洲欧美日韩中文播放| 国产在线视频99| 色狠狠色噜噜噜综合网| 在线黄色av网站| 日韩欧美一级在线播放| 天堂中文在线看| 亚洲欧美日韩在线高清直播| 成人在线免费看| 美女av一区二区| ****av在线网毛片| 国产成人极品视频| 成人黄色理论片| 好吊色欧美一区二区三区四区| 伊人成综合网yiren22| 亚洲成人精品电影在线观看| 亚洲精品888| 国产精品裸体瑜伽视频| 日本人妖一区二区| 中文字幕乱妇无码av在线| av综合在线播放| 久久精品色妇熟妇丰满人妻| 一区二区三区国产| 精品不卡一区二区| 91精品国产综合久久精品麻豆| 亚洲国产精品欧美久久| 亚洲欧洲偷拍精品| 在线视频观看国产| 日韩av手机在线| 免费精品一区| 日本欧洲国产一区二区| 亚洲最新色图| 久久精品网站视频| 国产成人日日夜夜| 东方伊人免费在线观看| 亚洲成人www| 亚洲自拍第二页| 亚洲精品福利资源站| 麻豆系列在线观看| 国产精品18久久久久久首页狼| 精品国产第一国产综合精品| 三级三级久久三级久久18| 欧美日韩ab| 国产精品v日韩精品v在线观看| 99re在线精品| 日本一级二级视频| 欧美在线一区二区三区| 蜜桃av中文字幕| www亚洲精品| 成人美女视频| 国产日韩欧美二区| 欧美.日韩.国产.一区.二区| 日韩一级片播放| 成人av在线网站| 中文字幕影音先锋| 欧美人xxxx| gogogo高清在线观看免费完整版| 欧美性受xxxx白人性爽| 91蜜桃臀久久一区二区| 中文字幕一区二区三区四区五区 | 清纯唯美日韩制服另类| 日韩精品一区二区三区中文字幕| 日韩视频精品| 久久精品成人| 五十路六十路七十路熟婆| 亚洲国产日韩一区二区| 国产青青草视频| 久久精品国产电影| 国产成+人+综合+亚洲欧美| 欧洲成人一区二区| 久久aⅴ国产紧身牛仔裤| 蜜桃精品成人影片| 五月婷婷另类国产| 蜜臀久久99精品久久久| 色综合久综合久久综合久鬼88| 91国产精品| 亚洲成年人专区| 青青草国产成人av片免费| 男人操女人动态图| 日本丶国产丶欧美色综合| 视频在线观看你懂的| 91av网站在线播放| 久久不见久久见中文字幕免费| 欧美精品一区免费| 91蜜桃网址入口| 国产伦精品一区二区三区视频我| 精品亚洲一区二区三区四区五区| 人人草在线视频| 久久一区二区三区欧美亚洲| 99精品国产在热久久| 日本xxxx裸体xxxx| 偷拍亚洲欧洲综合| 飘雪影院手机免费高清版在线观看| 51午夜精品视频| 国产中文字幕一区二区三区| 国产成人亚洲精品无码h在线| 久久综合成人精品亚洲另类欧美| 日韩黄色片网站| 中文字幕一精品亚洲无线一区| 日本亚洲欧洲无免费码在线| 在线码字幕一区| 国产成人在线视频网址| 国产午夜激情视频| 亚洲欧美日韩网| 欧美天堂一区| 996这里只有精品| 97se亚洲国产综合自在线观| 欧美brazzers| 精品国偷自产在线| 1769国产精品视频| 无码精品a∨在线观看中文| 久久免费偷拍视频| 91精品国产乱码久久| 欧美日韩国产成人高清视频| 欧美久久香蕉| 欧美午夜aaaaaa免费视频| 亚洲精品一卡二卡| 亚洲av片一区二区三区| 国产精品美女久久久久av超清| 亚洲国产精品久久久久蝴蝶传媒| 无码人妻精品一区二区三| 色综合一个色综合亚洲| 色欧美激情视频在线| 精品视频高清无人区区二区三区| 老司机午夜精品视频在线观看| 久艹在线观看视频| 亚洲精品久久久久久久久久久久| 亚洲a∨精品一区二区三区导航| 成人在线观看www| 99re热视频精品| 国产男女裸体做爰爽爽| 6080yy精品一区二区三区| 91精品电影| av电影网站在线观看| 日韩欧美视频在线| 色香欲www7777综合网| 欧美亚洲黄色片| 国产精品电影院| 欧美孕妇孕交|