<commit_before>---
layout: post
title:  "高并发系统数据幂等的技术尝试"
date:   2015-06-10 
categories: 高并发

---

* content
{:toc}

## 前言介绍

> 在系统开发过程中，经常遇到数据重复插入、重复更新、消息重发发送等等问题，因为应用系统的复杂逻辑以及网络交互存在的不确定性，会导致这一重复现象，但是有些逻辑是需要有幂等特性的，否则造成的后果会比较严重，例如订单重复创建，这时候带来的问题可是非同一般啊。
 
--- 
## 什么是系统的幂等性

> 幂等是数据中得一个概念，表示N次变换和1次变换的结果相同。
 
---
## 高并发的系统如何保证幂等性？
 
### 查询API

> 查询的API，可以说是天然的幂等性，因为你查询一次和查询两次，对于系统来讲，没有任何数据的变更，所以，查询一次和查询多次一样的。

--- 
### MVCC方案

> 多版本并发控制，update with condition，更新带条件，这也是在系统设计的时候，合理的选择乐观锁，通过version或者其他条件，来做乐观锁，这样保证更新及时在并发的情况下，也不会有太大的问题。
例如update table_xxx set name=#name#,version=version+1 where version=#version# ,或者是 update table_xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0 。

--- 
### 单独的去重表

> 如果涉及到的去重的地方特别多，例如ERP系统中有各种各样的业务单据，每一种业务单据都需要去重，这时候，可以单独搞一张去重表，在插入数据的时候，插入去重表，利用数据库的唯一索引特性，保证唯一的逻辑。
 
---
### 分布式锁

> 还是拿插入数据的例子，如果是分布是系统，构建唯一索引比较困难，例如唯一性的字段没法确定，这时候可以引入分布式锁，通过第三方的系统，在业务系统插入数据或者更新数据，获取分布式锁，然后做操作，之后释放锁，这样其实是把多线程并发的锁的思路，引入多多个系统，也就是分布式系统中得解决思路。

---
###删除数据
> 删除数据，仅仅第一次删除是真正的操作数据，第二次甚至第三次删除，直接返回成功，这样保证了幂等。

--- 
###插入数据的唯一索引
> 插入数据的唯一性，可以通过业务主键来进行约束，例如一个特定的业务场景，三个字段肯定确定唯一性，那么，可以在数据库表添加唯一索引来进行标示。
这里有一个场景，API层面的幂等，例如提交数据，如何控制重复提交，这里可以在提交数据的form表单或者客户端软件，增加一个唯一标示，然后服务端，根据这个UUID来进行去重，这样就能比较好的做到API层面的唯一标示。
 
---
###状态机幂等 
> 在设计单据相关的业务，或者是任务相关的业务，肯定会涉及到状态机，就是业务单据上面有个状态，状态在不同的情况下会发生变更，一般情况下存在有限状态机，这时候，如果状态机已经处于下一个状态，这时候来了一个上一个状态的变更，理论上是不能够变更的，这样的话，保证了有限状态机的幂等。<commit_msg>update 幂等<commit_after>---
layout: post
title:  "高并发系统数据幂等的技术尝试"
date:   2015-06-10 
categories: 高并发

---

* content
{:toc}

## 前言介绍

> 在系统开发过程中，经常遇到数据重复插入、重复更新、消息重发发送等等问题，因为应用系统的复杂逻辑以及网络交互存在的不确定性，会导致这一重复现象，但是有些逻辑是需要有幂等特性的，否则造成的后果会比较严重，例如订单重复创建，这时候带来的问题可是非同一般啊。
 
--- 

## 什么是系统的幂等性

> 幂等是数据中得一个概念，表示N次变换和1次变换的结果相同。
 
---

## 高并发的系统如何保证幂等性？
 
### 查询API

> 查询的API，可以说是天然的幂等性，因为你查询一次和查询两次，对于系统来讲，没有任何数据的变更，所以，查询一次和查询多次一样的。

--- 

### MVCC方案

> 多版本并发控制，update with condition，更新带条件，这也是在系统设计的时候，合理的选择乐观锁，通过version或者其他条件，来做乐观锁，这样保证更新及时在并发的情况下，也不会有太大的问题。
例如update table_xxx set name=#name#,version=version+1 where version=#version# ,或者是 update table_xxx set quality=quality-#subQuality# where quality-#subQuality# >= 0 。

--- 

### 单独的去重表

> 如果涉及到的去重的地方特别多，例如ERP系统中有各种各样的业务单据，每一种业务单据都需要去重，这时候，可以单独搞一张去重表，在插入数据的时候，插入去重表，利用数据库的唯一索引特性，保证唯一的逻辑。
 
---

### 分布式锁

> 还是拿插入数据的例子，如果是分布是系统，构建唯一索引比较困难，例如唯一性的字段没法确定，这时候可以引入分布式锁，通过第三方的系统，在业务系统插入数据或者更新数据，获取分布式锁，然后做操作，之后释放锁，这样其实是把多线程并发的锁的思路，引入多多个系统，也就是分布式系统中得解决思路。

---

###删除数据
> 删除数据，仅仅第一次删除是真正的操作数据，第二次甚至第三次删除，直接返回成功，这样保证了幂等。

--- 

###插入数据的唯一索引
> 插入数据的唯一性，可以通过业务主键来进行约束，例如一个特定的业务场景，三个字段肯定确定唯一性，那么，可以在数据库表添加唯一索引来进行标示。
这里有一个场景，API层面的幂等，例如提交数据，如何控制重复提交，这里可以在提交数据的form表单或者客户端软件，增加一个唯一标示，然后服务端，根据这个UUID来进行去重，这样就能比较好的做到API层面的唯一标示。
 
---

###状态机幂等 
> 在设计单据相关的业务，或者是任务相关的业务，肯定会涉及到状态机，就是业务单据上面有个状态，状态在不同的情况下会发生变更，一般情况下存在有限状态机，这时候，如果状态机已经处于下一个状态，这时候来了一个上一个状态的变更，理论上是不能够变更的，这样的话，保证了有限状态机的幂等。
{'fraction_non_alphanumeric': 0.13040396881644223, 'fraction_numerical': 0.007795889440113395, 'mean_word_length': 8.73448275862069, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6815344', 'n_tokens_mistral': 2364, 'n_tokens_neox': 2714, 'n_words': 96}