Apprentissage recommandé : Tutoriel vidéo Redis
Avant-propos : La question de l'idempotence de l'interface
est une question publique qui n'a rien à voir avec le langage pour les développeurs. Pour certaines requêtes utilisateur, elles peuvent être envoyées à plusieurs reprises dans certains cas. S'il s'agit d'une opération de requête, ce n'est pas grave. Cependant, certaines d'entre elles impliquent des opérations d'écriture. Une fois répétées, cela peut entraîner de graves conséquences, comme des transactions. . Si l'interface est demandée à plusieurs reprises, des commandes répétées peuvent être passées. L'idempotence de l'interface signifie que les résultats d'une ou de plusieurs requêtes initiées par l'utilisateur pour la même opération sont cohérents et qu'il n'y aura aucun effet secondaire causé par plusieurs clics. 接口幂等性
问题,对于开发人员来说,是一个跟语言无关的公共问题。对于一些用户请求,在某些情况下是可能重复发送的,如果是查询类操作并无大碍,但其中有些是涉及写入操作的,一旦重复了,可能会导致很严重的后果,例如交易的接口如果重复请求可能会重复下单。接口幂等性是指用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
在HTTP/1.1中,对幂等性进行了定义。它描述了一次和多次请求某一个资源对于资源本身应该具有同样的结果,即第一次请求的时候对资源产生了副作用,但是以后的多次请求都不会再对资源产生副作用。这里的副作用是不会对结果产生破坏或者产生不可预料的结果。也就是说,其任意多次执行对资源本身所产生的影响均与一次执行的影响相同。
这类问题多发于接口的:
insert
操作,这种情况下多次请求,可能会产生重复数据。update
操作,如果只是单纯的更新数据,比如:update user set status=1 where id=1
,是没有问题的。如果还有计算,比如:update user set status=status+1 where id=1
,这种情况下多次请求,可能会导致数据错误。在接口调用时一般情况下都能正常返回信息不会重复提交,不过在遇见以下情况时可以就会出现问题,如:
本文讨论的是如何在服务端优雅地统一处理这种接口幂等性情况,如何禁止用户重复点击等客户端操作不在此次讨论范围。
幂等性是为了简化客户端逻辑处理,能放置重复提交等操作,但却增加了服务端的逻辑复杂性和成本,其主要是:
所以在使用时候需要考虑是否引入幂等性的必要性,根据实际业务场景具体分析,除了业务上的特殊要求外,一般情况下不需要引入的接口幂等性。
幂等意味着一条请求的唯一性。不管是你哪个方案去设计幂等,都需要一个全局唯一的ID ,去标记这个请求是独一无二的。
全局唯一性ID,我们怎么去生成呢?你可以回想下,数据库主键Id怎么生成的呢?
是的,我们可以使用UUID
insert
Dans ce cas, plusieurs requêtes peuvent produire des données en double. Opération update
, si vous mettez simplement à jour les données, par exemple : update user set status=1 which id=1
, il n'y a pas de problème. S'il existe des calculs, tels que : update user set status=status+1 which id=1
, plusieurs requêtes dans ce cas peuvent provoquer des erreurs de données. UUID
, mais les inconvénients de l'UUID sont évidents. Sa chaîne prend beaucoup de place, l'ID généré est trop aléatoire, a une mauvaise lisibilité et n'est pas incrémenté. 🎜Nous pouvons également utiliser l'Algorithme Snowflake (Snowflake)
pour générer des identifiants uniques. 雪花算法(Snowflake)
生成唯一性ID。
雪花算法是一种生成分布式全局唯一ID的算法,生成的ID称为Snowflake IDs
。这种算法由Twitter创建,并用于推文的ID。
一个Snowflake ID有64位。
当然,全局唯一性的ID,还可以使用百度的Uidgenerator
,或者美团的Leaf
。
幂等处理的过程,说到底其实就是过滤一下已经收到的请求,当然,请求一定要有一个全局唯一的ID标记
Identifiants Snowflake
. Cet algorithme a été créé par Twitter et est utilisé pour les identifiants des tweets. Un identifiant Snowflake a 64 bits. Bit 1 : Le bit le plus élevé de long en Java est le bit de signe, qui représente le positif et le négatif. Le nombre positif est 0 et le nombre négatif est 1. Généralement, l'ID généré est un nombre positif, donc la valeur par défaut est. 0. Les 41 bits suivants sont l'horodatage, représentant le nombre de millisecondes depuis l'époque sélectionnée. Bien sûr, l'identifiant unique au monde, Vous pouvez également utiliser le Uidgenerator
de Baidu ou le Leaf
de Meituan.
balise d'identification unique globale Ha. Alors, comment déterminer si la demande a déjà été reçue ? Stockez la demande. Lors de la réception de la demande, vérifiez d'abord l'enregistrement de stockage. Si l'enregistrement existe, le dernier résultat sera renvoyé. Si l'enregistrement n'existe pas, la demande sera traitée. <li>Le traitement général de l'idempotence est le suivant :
S'il existe, cela signifie que la demande en aval du numéro de série a été traitée. A ce moment, vous pouvez répondre directement au message d'erreur de la demande répétée.
Si elle n'existe pas, utilisez la clé comme clé de Redis, utilisez les informations de clé en aval comme valeur stockée (telles que certaines informations de logique métier transmises par le fournisseur en aval), stockez la paire clé-valeur dans Redis et puis exécutez la correspondance normalement selon la logique métier.
Opérations applicables :
Restrictions d'utilisation :
Processus principal :
🎜🎜🎜🎜 Étapes principales : 🎜🎜🎜 Le service en aval génère un identifiant distribué sous forme de numéro de série, puis exécute la demande d'appel de l'interface en amont, ainsi que le "unique numéro de série" et "l'identifiant d'authentification" demandé. 🎜🎜 Le service en amont effectue une vérification de sécurité et détecte si le « numéro de série » et « l'identifiant d'identification » existent dans les paramètres transmis en aval. 🎜🎜 Le service en amont détecte s'il existe une clé composée du "numéro de série" et de "l'ID d'authentification" correspondants dans Redis. Si elle existe, il lancera un message d'exception d'exécution répété, puis répondra au message d'erreur correspondant du serveur. en aval. S'il n'existe pas, la combinaison du « numéro de série » et de « l'ID d'authentification » sera utilisée comme clé, et les informations de clé en aval seront utilisées comme valeur, puis stockées dans Redis, puis la logique métier suivante sera être exécuté normalement. 🎜🎜🎜Dans les étapes ci-dessus, lors de l'insertion de données dans Redis, vous devez définir le délai d'expiration. Cela garantit que dans cet intervalle de temps, si l'interface est appelée à plusieurs reprises, un jugement et une identification peuvent être effectués. Si le délai d'expiration n'est pas défini, il est probable qu'une quantité illimitée de données sera stockée dans Redis, ce qui empêchera Redis de fonctionner correctement. 🎜🎜🎜3.2. Jeton anti-duplication 🎜🎜🎜Description du projet : 🎜🎜Compte tenu des clics continus du client ou des tentatives d'expiration du délai de l'appelant, comme la soumission d'une commande, cette opération peut utiliser le mécanisme du jeton pour empêcher les soumissions répétées. Pour faire simple, l'appelant demande d'abord un identifiant global (jeton) au backend lors de l'appel de l'interface, et transporte cet identifiant global avec la demande (il est préférable de mettre le jeton dans les en-têtes. Le backend doit utiliser ce jeton). . En tant que clé, les informations utilisateur sont envoyées à Redis en tant que valeur pour la vérification du contenu de la valeur de la clé. Si la clé existe et que la valeur correspond, la commande de suppression est exécutée, puis la logique métier suivante est exécutée normalement. S'il n'y a pas de clé correspondante ou si la valeur ne correspond pas, un message d'erreur répété sera renvoyé pour garantir des opérations idempotentes. 🎜Restrictions d'utilisation :
Processus principal :
Le serveur fournit une interface pour obtenir le jeton, qui peut être un numéro de séquence, qui peut également être un ID distribué ou une chaîne UUID.
Le client appelle l'interface pour obtenir le Token. A ce moment, le serveur générera une chaîne de Token.
Stockez ensuite la chaîne dans la base de données Redis, en utilisant le Token comme clé Redis (notez le délai d'expiration).
Retournez le jeton au client. Une fois que le client l'a reçu, il doit être stocké dans le champ caché du formulaire.
Lorsque le client exécute et soumet le formulaire, il stocke le jeton dans les en-têtes et transporte les en-têtes lors de l'exécution de la demande commerciale.
Après avoir reçu la demande, le serveur récupère le jeton des en-têtes, puis vérifie si la clé existe dans Redis en fonction du jeton.
Le serveur détermine si la clé existe dans Redis. Si elle existe, supprimez la clé puis exécutez la logique métier normalement. S'il n'existe pas, une exception sera levée et un message d'erreur pour les soumissions répétées sera renvoyé.
Notez que dans des conditions concurrentes, l'exécution de la recherche et de la suppression de données Redis doit garantir l'atomicité, sinon l'idempotence peut ne pas être garantie en cas de concurrence. Son implémentation peut utiliser des verrous distribués ou utiliser des expressions Lua pour se déconnecter des opérations de requête et de suppression.
Apprentissage recommandé : Tutoriel vidéo Redis
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!