# :-: 系統冪等性設計與實
## 一、冪等性的定義
就是用戶對于同一操作發起的一次請求或者多次請求的結果是一致的,不會因為多次點擊而產生了副作用。舉個最簡單的例子,那就是支付,用戶購買商品使用支付,支付扣款成功,但是返回結果的時候網絡異常,此時錢已經扣了,用戶再次點擊按鈕,此時會進行第二次扣款,返回結果成功,用戶查詢余額返發現多扣錢了,流水記錄也變成了兩條。
## 二、確定需要冪等性的范圍
### 2.1. 確定大范圍
1. 請求層面:`讀請求`、`寫請求`
* 其中讀請求沒有影響數據變化不需要做冪等性
2. 微服務層面:`負載均衡`、`api網關`、`業務邏輯層`、`數據訪問層`
* 其中負載均衡、api網關、業務邏輯層沒有影響數據變化不需要做冪等性
> 總結:上面的范圍里只有`數據訪問層`和`寫請求`
### 2.2. 數據訪問層-寫請求
1. Insert
* **需要做冪等性**
2. Update
* 直接更新某個值的:不需要做冪等性
* 累加操作等計算式的更新:**需要做冪等性**
3. Delete
* 重復刪除結果是一樣:不需要做冪等性
## 三、冪等性解決方案
* 沒有最優的方案只有最適合的,因為這個和業務的邏輯強相關,所以就簡單列舉通用的方案
### 3.1. Insert冪等方案
1. **數據字段增加唯一索引**
* 優點:實現簡單方便
* 缺點:影響數據庫性能不適合該字段會被頻繁更新的場景,唯一索引比普通索引在寫操作上開銷會大很多
2. **insert時使用臨時表查詢判斷**
~~~
insert into sys_user(name,password)
select 'admin', '123456' from dual
where not exists(select 1 from sys_user where name='admin');
~~~
* 優點:不需要創建唯一索引,語法相對通用(mysql和oracle)
* 缺點:寫操作會增加一次select子查詢開銷,增加sql語法的復雜度可讀性較差
3. **細粒度分布式鎖+select + insert**
* 意思就是先加一個細粒度的分布式鎖,然后select查一下是否存在,不存在再insert
* 例子可參考文檔:[開發說明](http://www.hmoore.net/zlt2000/microservices-platform/919421)中的`方法級冪等性`
* 優點:性能影響較少,使用的是細粒度鎖,所以只有重復提交記錄時才會阻塞
* 缺點:寫操作會增加一次select開銷,實現難度相對較大因為需要分布式細粒度鎖
### 3.2. Update計算操作冪等方案
* 這個需要結合具體業務來設計方案,常用的場景可通過版本號的方式來控制
* 在表里面添加`version`字段
* ~~~
alter table sys_user add version int default 0;
~~~
* 然后更新的時候通過這個`version`來判斷是否為過期無效操作,這是樂觀鎖的一種思路
* ~~~
update sys_user set age=age+1, version=version+1
where version=xx
~~~
- 項目介紹
- 項目聲明
- 項目簡介
- 架構設計
- 項目亮點功能介紹
- 技術棧介紹
- 核心功能
- 運行環境
- 項目更新日志
- 文檔更新日志
- F&Q
- 部署教程
- 環境準備
- JDK安裝
- JDK1.8,17共存
- maven
- 分布式緩存Redis
- 單機版
- 集群
- 注冊&配置中心alibaba/nacos
- 介紹
- Nacos安裝
- Nacos配置中心
- Nacos注冊發現
- Nacos生產部署方案
- 服務監控-BootAdmin
- 基本介紹
- 如何使用
- 整合Admin-Ui
- 客戶端配置
- 鏈路追蹤
- 基本介紹
- SkyWalking-1
- Skywalking-1
- 消息隊列
- Kafka
- docker安裝kafka
- Linux集群
- Maven私服
- nexus安裝部署
- nexus使用介紹
- 全文搜索elasticsearch
- windows集群搭建
- docker安裝es
- ElasticHD
- linux集群部署
- 統一日志解決方案
- 日志解決方案設計
- 介紹與相關資料
- ELK安裝部署
- elasticsearch 7.5
- logstash-7.5
- kibana-7.5
- filebeat
- 服務監控-Prometheus
- Prometheus安裝配置
- Prometheus介紹
- grafana
- 持續集成部署CICD
- 自動化部署Jenkins
- 安裝部署win
- 打包發布遠程執行
- 安裝部署linux
- jenkins+gitlab+docker容器化工程自動化部署
- Git
- CICD說明
- 阿里云效
- CentOS_MYSQL安裝
- docker
- 安裝
- Docker安裝Nginx
- Docker部署啟動springboot
- dockerCompose
- harbor
- Docker私有鏡像倉庫
- Portainer
- Docker遠程連接設置
- 打包工程
- 必要啟動模塊
- 核心模塊
- 登錄認證
- 緩存功能
- 日志模塊
- 分布式鎖
- 消息隊列
- 異常處理
- 系統接口
- 參數驗證
- es檢索
- 數據導出
- 系統設計
- 系統總體架構
- 擴展模塊(可選)
- 限流熔斷alibaba/sentinel
- 使用Sentinel實現gateway網關及服務接口限流
- Sentinel使用Nacos存儲規則及同步
- 服務調用Feign
- Feign基本介紹
- 如何使用
- 負載均衡
- 請求超時
- 請求攔截器
- 分布式任務調度
- XXL-JOB
- 分布式事務
- TX-LCN
- Seata
- Seata原理解析
- 數據庫分庫分表
- swagger文檔
- 分布式ID生成器解決方案
- 服務網關CloudGateway
- 基本介紹
- 使用網關
- 路由配置
- 全局過濾器
- 服務認證授權架構設計
- 認證服務流程
- 授權服務流程
- 系統冪等性設計與實踐
- 分布式日志鏈路跟蹤
- 實時搜索系統設計
- 應用性能
- 壓力測試工具
- Apache JMeter介紹和安裝
- ApacheJMeter使用
- JVM
- JVM性能調優
- 常見JVM內存錯誤及解決方案
- JVM 分析工具詳解
- Spring Cloud性能調優
- Linux運維
- Linux 常用命令
- Linux開啟端口