Maison  >  Article  >  Quelques réflexions sur les solutions à haute concurrence en PHP

Quelques réflexions sur les solutions à haute concurrence en PHP

无忌哥哥
无忌哥哥original
2018-06-27 14:37:592211parcourir

En ce qui concerne les ventes urgentes, les ventes flash, les tirages de loterie, la saisie de billets et d'autres activités, afin d'éviter la survente, la quantité de l'inventaire est limitée. Cependant, si le nombre de personnes passant des commandes en même temps dépasse l'inventaire. quantité, cela entraînera des problèmes de survente. Alors, comment résoudre ce problème ? Mon idée est la suivante (pseudocode) : sql1 : interroger l'inventaire des produits si (quantité d'inventaire> 0) { //Générer la commande...
sql2 : inventaire simultané-1}

En l'absence de concurrence, le processus ci-dessus semble normal. Supposons que deux personnes passent des commandes en même temps et qu'il n'y a qu'un seul inventaire à l'étape sql1, l'inventaire interrogé par les deux personnes est > ; 0, donc sql2 a finalement été exécuté et l'inventaire est finalement devenu -1, ce qui est survendu. Ce n'est pas le résultat que nous souhaitons.

J'ai résumé les idées les plus populaires pour résoudre ce problème :

1 Utilisez un processus unique supplémentaire pour traiter une file d'attente, mettez les demandes de commande dans la file d'attente et traitez-les une par une. . Il existe des problèmes de concurrence, mais des processus d'arrière-plan supplémentaires et des problèmes de retard doivent être ouverts, ce qui ne sera pas pris en compte ici pour l'instant. Ici, je peux utiliser la file d'attente des messages, nous utilisons souvent Memcacheq et Radis. Par exemple : s'il y a 100 tickets à récupérer par les utilisateurs, ils peuvent alors mettre ces 100 tickets dans le cache et ne pas les verrouiller lors de la lecture et de l'écriture. Lorsque le niveau de simultanéité est important, environ 500 personnes peuvent réussir à récupérer des billets, de sorte que les demandes après 500 puissent être directement transférées vers la page statique à la fin de l'événement. Il est impossible pour 400 des 500 personnes qui entrent de se procurer le produit. Par conséquent, seules les 100 premières personnes peuvent acheter avec succès selon l'ordre dans lequel elles entrent dans la file d'attente. Les 400 prochaines personnes accéderont directement à la page de fin de l'événement. Bien entendu, la saisie de 500 personnes n’est qu’un exemple. Vous pouvez ajuster le nombre vous-même. La page de fin d'activité doit utiliser une page statique, pas une base de données. Cela réduit la pression sur la base de données.

2. Le verrouillage optimiste MySQL signifie que par exemple, si l'inventaire total est de 2, lorsque l'événement d'achat urgent est soumis, l'inventaire sera immédiatement de +1, puis l'inventaire sera de 3 à ce moment-là, et puis une fois la commande générée, interrogez à nouveau avant de mettre à jour l'inventaire (car la commande est générée, l'inventaire est -1, mais ne vous inquiétez pas, vérifiez à nouveau l'inventaire et le résultat est 3), voyez s'il est cohérent. avec la quantité d'inventaire attendue (l'inventaire attendu ici est de 3), s'il est incohérent, revenez en arrière, invitez l'utilisateur à avoir un inventaire insuffisant. Ici, nous parlons de verrous pessimistes. Certains amis peuvent demander, alors il doit y avoir des verrous optimistes, non ?? Ici, je vais parler brièvement des verrous pessimistes et optimistes que je connais

Les verrous pessimistes et les verrous optimistes sont deux. les plus courants. L’idée de conception de verrouillage de concurrence de ressources est également un concept très basique en programmation concurrente. Cet article fournira une introduction comparative et systématique à la mise en œuvre de ces deux mécanismes de verrouillage courants sur les données de bases de données.

Verrouillage pessimiste

La caractéristique du verrouillage pessimiste est d'acquérir d'abord le verrou, puis d'effectuer des opérations commerciales. Autrement dit, le « pessimiste » croit que l'acquisition du verrou est très susceptible d'échouer, donc il le fait. est nécessaire d'abord Assurez-vous d'obtenir le verrou avec succès avant d'effectuer des opérations commerciales. L'expression communément appelée « un verrou, deux vérifications et trois mises à jour » fait référence à l'utilisation de verrous pessimistes. De manière générale, le verrouillage pessimiste sur la base de données nécessite la prise en charge de la base de données elle-même, c'est-à-dire que le verrouillage pessimiste est implémenté via l'opération de sélection... pour la mise à jour couramment utilisée. Lorsque la base de données exécute la sélection pour la mise à jour, elle acquiert le verrou de ligne de la ligne de données dans la sélection. Par conséquent, si une autre sélection pour la mise à jour exécutée simultanément tente de sélectionner la même ligne, une exclusion se produira (il faudra attendre que le verrouillage de la ligne soit activé). être libéré), de sorte que l'effet de verrouillage est obtenu. Le verrou de ligne acquis par select for update sera automatiquement libéré à la fin de la transaction en cours, il doit donc être utilisé dans la transaction.

Une chose à noter ici est que différentes bases de données ont une implémentation et une prise en charge différentes pour la sélection pour la mise à jour. Par exemple, Oracle prend en charge la sélection pour la mise à jour sans attente, ce qui signifie que si le verrou ne peut pas être obtenu, une erreur sera générée. signalé immédiatement, au lieu d'attendre, mysql n'a pas l'option sans attente. Un autre problème avec MySQL est que toutes les lignes analysées seront verrouillées lors de l'exécution de l'instruction select for update, ce qui peut facilement causer des problèmes. Par conséquent, si vous utilisez le verrouillage pessimiste dans MySQL, veillez à utiliser l'index au lieu d'une analyse complète de la table.

Verrouillage optimiste

Les caractéristiques du verrouillage optimiste sont d'effectuer d'abord des opérations commerciales et de ne prendre le verrou que lorsque cela est absolument nécessaire. C'est-à-dire que les « optimistes » pensent que la plupart du temps, le verrouillage réussira, il suffit donc de prendre le verrouillage après la dernière étape de mise à jour réelle des données après avoir terminé l'opération commerciale.

La mise en œuvre du verrouillage optimiste sur la base de données est tout à fait logique et ne nécessite pas de support particulier de la base de données. L'approche générale consiste à ajouter un numéro de version ou un horodatage aux données qui doivent être verrouillées, puis à l'implémenter comme suit :

1 SELECT data AS old_data, version AS old_version FROM … ; les données obtenues Effectuez des opérations commerciales et obtenez new_data et new_version3. data = new_data, version = new_version WHERE version = old_versionif (ligne mise à jour > 0) { // L'acquisition du verrou optimiste est réussie, opération terminée} else { // Verrouillage optimiste l'acquisition échoue, retournez Roll et réessayez🎜>

En fait, peu importe qu'il y ait un verrouillage optimiste dans une transaction. Le mécanisme sous-jacent est le suivant : la concurrence n'est pas autorisée lors de la mise à jour de la même ligne dans la base de données, c'est-à-dire que la base de données obtiendra la ligne mise à jour à chaque fois. exécute une instruction de mise à jour. Le verrou en écriture n'est pas libéré tant que la ligne n'est pas mise à jour avec succès. Par conséquent, avant d'effectuer l'opération commerciale, obtenez le numéro de version actuel des données qui doivent être verrouillées, puis comparez à nouveau le numéro de version pour confirmer qu'il est le même que celui obtenu auparavant lorsque les données sont réellement mises à jour, et mettez à jour le numéro de version pour confirmer qu’aucune modification simultanée n’a eu lieu. Si la mise à jour échoue, on peut considérer que l'ancienne version des données a été modifiée simultanément et n'existe plus. À ce stade, on considère que l'acquisition du verrou a échoué et que l'ensemble de l'opération commerciale doit être annulée. l’ensemble du processus peut être réessayé si nécessaire.

Voici un résumé tenace de ces deux verrous :

1. Le coût du verrouillage optimiste est inférieur à celui du verrouillage pessimiste lorsqu'aucune défaillance de verrouillage ne se produit, mais une fois qu'une défaillance se produit, le coût La restauration est relativement importante, elle convient donc à une utilisation dans des scénarios où la probabilité d'échec du verrouillage est relativement faible, ce qui peut améliorer les performances de concurrence du système.

2. Le verrouillage optimiste convient également à certains scénarios particuliers, par exemple lorsque la connexion avec la base de données ne peut pas être maintenue pendant les opérations commerciales et à d'autres endroits où le verrouillage pessimiste ne peut pas être appliqué.

3. En jugeant sur la base du résultat de la mise à jour, nous pouvons ajouter une table de mise à jour des conditions de jugement définie inventaire=xxx où inventaire>0 dans sql2 Si false est renvoyé, cela signifie que l'inventaire est insuffisant et que la transaction est insuffisante. reculé.

4. À l'aide du verrouillage exclusif de fichier, lors du traitement d'une demande de commande, utilisez flock pour verrouiller un fichier. Si le verrouillage échoue, cela signifie que d'autres commandes sont en cours de traitement. soit attendez, soit demandez directement "serveur occupé". Le code approximatif est le suivant :

Mode bloquant (en attente)

$fp = fopen("lock.txt", "w+");if(flock($fp,LOCK_EX)) { // 锁定当前指针,,,
    //..处理订单
    flock($fp,LOCK_UN);
}fclose($fp);

Mode non bloquant

$fp = fopen("lock.txt", "w+");if(flock($fp,LOCK_EX | LOCK_NB)) {    //..处理订单
    flock($fp,LOCK_UN);
} else {  echo "系统繁忙,请稍后再试";
}fclose($fp);

5. un ou plusieurs Les achats précipités du serveur de file d'attente Xiaomi et Taobao sont encore légèrement différents. Xiaomi se concentre sur le moment de pointe. Une fois que vous avez récupéré le quota, il vous appartient et vous pouvez passer une commande et régler le paiement. Taobao, quant à lui, se concentre sur le filtrage lors du paiement. Il a mis en œuvre plusieurs niveaux de filtrage. Par exemple, s'il souhaite vendre 10 articles, il permettra à plus de 10 utilisateurs de les récupérer. Il effectuera ensuite un filtrage simultané lors du paiement. , réduisant le nombre d'éléments couche par couche en un instant.

6. Utilisez redis lock product_lock_key comme clé de verrouillage du ticket Lorsque product_key existe dans Redis, tous les utilisateurs peuvent accéder au processus de commande. Lorsque vous entrez dans le processus de paiement, stockez d'abord sadd(product_lock_key, « 1″) dans redis. Si le retour réussit, entrez dans le processus de paiement. S'il échoue, cela signifie que quelqu'un est déjà entré dans le processus de paiement, et le thread attend N secondes et effectue l'opération sadd de manière récursive.


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn