Il existe de nombreuses opérations dans notre système actuel, qui devraient produire le même effet ou renvoyer le même résultat, quel que soit le nombre de fois qu'elles sont effectuées.
Par exemple :
Si le front-end soumet à plusieurs reprises les données sélectionnées, l'arrière-plan ne doit générer qu'un seul résultat de réponse correspondant à ces données.
Lorsque nous lançons une demande de paiement, le compte utilisateur ne doit être déduit qu'une seule fois. En cas de renvoi d'un réseau ou d'un bug du système, l'argent ne doit être déduit qu'une seule fois.
L'envoi d'un message ne doit également être envoyé qu'une seule fois. une fois, le même message texte est envoyé à l'utilisateur, et l'utilisateur criera :
Créez une commande commerciale. Une seule demande commerciale peut être créée à la fois. Si vous en créez plusieurs, de gros problèmes surviendront.
et bien d'autres situations importantes, ces logiques nécessitent des fonctionnalités idempotentes pour être prises en charge.
L'idempotence (idempotent, idempotence) est un concept mathématique et informatique que l'on retrouve couramment en algèbre abstraite.
En programmation, la caractéristique d'une opération idempotente est que l'impact de toute exécution multiple est le même que l'impact d'une seule exécution. Une fonction idempotente, ou méthode idempotente, est une fonction qui peut être exécutée de manière répétée avec les mêmes paramètres et obtenir le même résultat.
Ces fonctions n'affecteront pas l'état du système et il n'y a pas lieu de s'inquiéter des modifications du système causées par une exécution répétée. Par exemple, les fonctions "getUsername() et setTrue()" sont des fonctions idempotentes.
Les opérations plus complexes sont garanties idempotentes en utilisant un numéro de transaction unique (numéro de série).
Ma compréhension : l'idempotence est une opération, peu importe le nombre de fois qu'elle est exécutée, l'effet et le résultat renvoyés sont les mêmes
1. Opération de requête Si vous interrogez une fois ou plusieurs fois, les résultats de la requête seront les mêmes lorsque les données restent inchangées. La sélection est une opération idempotente naturelle
2. Opération de suppression Les opérations de suppression sont également idempotentes. La suppression une fois et la suppression plusieurs fois supprimeront les données. (Notez que les résultats renvoyés peuvent être différents. Les données supprimées n'existent pas, donc 0 est renvoyé. S'il y a plusieurs données supprimées, plusieurs résultats seront renvoyés)
3. Index unique pour éviter de nouvelles données sales Pour. Exemple : compte capital d'Alipay, Alipay Il existe également des comptes d'utilisateurs. Chaque utilisateur ne peut avoir qu'un seul compte de fonds. Comment empêcher la création de plusieurs comptes de fonds pour un utilisateur ? Ajoutez ensuite un index unique à l'ID utilisateur dans le tableau des comptes de fonds, afin qu'un utilisateur puisse ajouter avec succès un enregistrement de compte de fonds
Points clés : Utilisez des index uniques ou des index combinés uniques pour éviter les données sales dans les nouvelles données (lorsque la table a un index unique et qu'une erreur est signalée lors de l'ajout de nouvelles données pendant la concurrence , interrogez-le simplement à nouveau. Les données devraient déjà exister et renvoyez simplement le résultat)
4. Mécanisme de jeton pour empêcher la soumission répétée de pages
.Exigences commerciales :
Les données de la page ne peuvent être cliquées et soumises qu'une seule fois
Cause de l'occurrence : en raison de clics répétés, de renvois réseau ou de renvois nginx, etc., les données seront soumises à plusieurs reprises
Solution : Cluster environnement : utilisez un jeton Ajoutez un redis (redis est monothread, le traitement doit être mis en file d'attente) Environnement JVM unique : utilisez un jeton plus redis ou un jeton plus de la mémoire jvm
Processus de traitement :
Avant de soumettre des données, vous devez demander un jeton du service, et le jeton est placé dans la mémoire redis ou jvm, durée de validité du jeton
Après la soumission, l'arrière-plan vérifie le jeton, supprime le jeton en même temps et génère un nouveau jeton à renvoyer
Caractéristiques du jeton :
Pour postuler, il est valable une fois et le courant peut être limité
Remarque : redis nécessite d'utiliser l'opération de suppression pour juger la suppression réussie signifie que la vérification du jeton a réussi si vous utilisez select+. supprimez pour vérifier le jeton, il y aura des problèmes de concurrence. Il n'est pas recommandé de l'utiliser
Verrouillage pessimiste Verrouillez l'acquisition lors de l'obtention des données
.sélectionnez * from table_xxx où id='xxx' pour la mise à jour ;
Remarque : le champ id doit être la clé primaire ou le seul index, sinon la table sera verrouillée, ce qui tuera des gens
Les verrous pessimistes sont généralement utilisés ensemble avec les transactions et le temps de verrouillage des données Cela peut être très long, veuillez choisir en fonction de la situation réelle
6. Verrouillage optimiste Le verrouillage optimiste ne verrouille la table qu'au moment où les données sont mises à jour, et ne verrouille pas la table. à d’autres moments, il est donc plus efficace que le verrouillage pessimiste.
Le verrouillage optimiste peut être implémenté de différentes manières via la version ou d'autres conditions de statut :
1. Implémenté via le numéro de version
update table_xxx set name=#name#,version=version+1 where version=#version#
Comme indiqué ci-dessous (à partir d'Internet) :
2. Grâce à des restrictions conditionnelles
update tablexxx set avaiamount=avaiamount-#subAmount# where avaiamount-#subAmount# >= 0
. Exigences :quality-#subQuality# >= , ce scénario ne convient à aucun numéro de version, seule la mise à jour est destinée à la vérification de la sécurité des données, convient au modèle d'inventaire, à la déduction de partage et au partage de restauration, des performances plus élevées
注意:乐观锁的更新操作,最好用主键或者唯一索引来更新,这样是行锁,否则更新时会锁表,上面两个sql改成下面的两个更好
update tablexxx set name=#name#,version=version+1 where id=#id# and version=#version#update tablexxx set avaiamount=avaiamount-#subAmount# where id=#id# and avai_amount-#subAmount# >= 0
7. 分布式锁 还是拿插入数据的例子,如果是分布是系统,构建全局唯一索引比较困难,例如唯一性的字段没法确定
这时候可以引入分布式锁,通过第三方的系统(redis或zookeeper),在业务系统插入数据或者更新数据,获取分布式锁,然后做操作,之后释放锁
这样其实是把多线程并发的锁的思路,引入多多个系统,也就是分布式系统中得解决思路。
要点:某个长流程处理过程要求不能并发执行,可以在流程执行之前根据某个标志(用户ID+后缀等)获取分布式锁,其他流程执行时获取锁就会失败,也就是同一时间该流程只能有一个能执行成功,执行完成后,释放分布式锁(分布式锁要第三方系统提供)
8. select + insert 并发不高的后台系统,或者一些任务JOB,为了支持幂等,支持重复执行,简单的处理方法是,先查询下一些关键数据,判断是否已经执行过,在进行业务处理,就可以了
注意:核心高并发流程不要用这种方法
9. 状态机幂等 在设计单据相关的业务,或者是任务相关的业务,肯定会涉及到状态机(状态变更图),就是业务单据上面有个状态,状态在不同的情况下会发生变更,一般情况下存在有限状态机
Si la machine à états est déjà dans l'état suivant et qu'un changement vers l'état précédent se produit à ce moment-là, le changement ne peut pas être effectué en théorie. Dans ce cas, l'idempotence de la machine à états finie est garantie.
Remarque : les commandes et autres entreprises de type document ont un long flux d'état. Vous devez avoir une compréhension approfondie des machines d'état, ce qui contribuera grandement à améliorer les capacités de conception de votre système d'entreprise
10 Comment garantir l'idempotence des API qui fournissent. interfaces externes
Par exemple, l'interface de paiement fournie par UnionPay : lorsque vous devez accéder au commerçant pour soumettre une demande de paiement, elle est livrée avec : source source, numéro de série seq
source+seq crée un index unique dans la base de données pour éviter plusieurs paiements (en cas de simultanéité, une seule demande peut être traitée)
Point cléAfin de fournir une interface externe pour prendre en charge les appels idempotents, l'interface comporte deux champs qui doivent être transmis, l'un est la source et le other est le numéro de séquence source seq. Ces deux champs sont utilisés comme index unique commun dans le système du fournisseur
De cette façon, lorsqu'un tiers appelle, vérifiez d'abord dans votre propre système s'il a été traité et renvoyez le résultat du traitement correspondant ; s'il n'a pas été traité, effectuer le traitement correspondant et renvoyer le résultat.
Notez que pour être idempotent et convivial, vous devez d'abord vérifier si l'entreprise a été traitée. Si vous l'insérez directement dans le système d'entreprise sans interroger, une erreur sera signalée, mais elle a effectivement été traitée.
L'idempotence devrait être un gène d'un programmeur qualifié, lors de la conception d'un système, c'est la considération primordiale, en particulier dans les systèmes tels qu'Alipay, les banques, les sociétés financières Internet, etc. qui impliquent tous de l'argent. les données doivent également être exactes, afin que des problèmes tels que des déductions excessives et des paiements en trop ne puissent pas survenir. Cela sera difficile à gérer et l'expérience utilisateur ne sera pas bonne.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!