# :-: 系统幂等性设计与实
## 一、幂等性的定义
就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。举个最简单的例子,那就是支付,用户购买商品使用支付,支付扣款成功,但是返回结果的时候网络异常,此时钱已经扣了,用户再次点击按钮,此时会进行第二次扣款,返回结果成功,用户查询余额返发现多扣钱了,流水记录也变成了两条。
## 二、确定需要幂等性的范围
### 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
* 例子可参考文档:[开发说明](https://www.kancloud.cn/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开启端口