Maison  >  Article  >  développement back-end  >  Introduction aux opérations atomiques et au verrouillage de fichiers en PHP (exemple de code)

Introduction aux opérations atomiques et au verrouillage de fichiers en PHP (exemple de code)

不言
不言avant
2019-01-28 10:00:482825parcourir

Cet article vous présente une introduction aux opérations atomiques et au verrouillage de fichiers en PHP (exemples de code). Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.

Opérations atomiques PHP, troupeau de verrouillage de fichiers, transactions de base de données

PHP n'hérite pas du verrou Unix supporté par le standard POSIX, mais encapsule uniquement un troupeau d'appel système Linux (le sémaphore peut également être utilisé comme une serrure). Il va de soi que le mécanisme de verrouillage peut également être utilisé, bien qu'il soit moins efficace.
Le script php s'exécute dans le conteneur fastcgi, et fastcgi est multi-processus, donc si le programme php accède à des ressources critiques, cela entraînera inévitablement des résultats de programme incorrects.
On estime que nous devrions également considérer la question des conteneurs fastcgi

Description du problème : les pirates ont utilisé des outils pour brosser notre backend
Il y aura des remboursements lors de l'annulation de commandes. Les pirates ont annulé des commandes simultanément, ce qui entraînera des remboursements. remboursements multiples
Si les demandes arrivent une par une, même si l'intervalle est de 100 millisecondes, il n'y aura aucun problème

Un processus de traitement PHP est le suivant : lire le drapeau de remboursement, constater qu'il n'y a pas de remboursement, remboursement, puis définissez l'indicateur de remboursement
Le problème est que plusieurs demandes arrivent en même temps et que les signes de remboursement lus ne sont pas tous remboursés, donc plusieurs demandes sont remboursées
Le même fichier php est demandé plusieurs fois à en même temps, en même temps

En utilisant PHP file lock flock, nous l'avons essayé mais cela n'a pas fonctionné, nous avons donc utilisé la file d'attente C++
Utilisé C++ pour écouter sur un port, recevoir directement les paquets HTTP, puis renvoyer les paquets au format HTTP, programme PHP j'utilise curl pour accéder à mon programme C.
Il équivaut à un appel à distance et peut être déployé sur d'autres serveurs pour la distribution

Souvent, nous ne considérons pas notre capacité parallèle du code PHP, surtout lorsque notre code PHP peut lire et écrire sur une certaine ressource. Mais cela ne signifie pas que toutes les opérations en PHP sont atomiques, transactionnelles et parallélisables. Étant donné que le script PHP s'exécute dans le conteneur fastcgi et que fastcgi est multi-processus, si le programme PHP accède à des ressources critiques, cela entraînera inévitablement des résultats de programme incorrects.

La solution au problème est d'utiliser un mécanisme de verrouillage. PHP n'hérite pas des verrous Unix supportés par le standard POSIX : comme les verrous d'enregistrement fcntl, les verrous de thread, etc., mais encapsule uniquement un appel système Linux flock (le sémaphore peut également être utilisé comme verrou), flock sous forme de flock ($fp,$type), Où $fp est le descripteur de fichier et $type est :
/* Lorsqu'un fichier est ouvert en lecture et en écriture, il est généralement nécessaire d'ajouter un mécanisme de verrouillage au fichier*/

1. Verrou partagé LOCK_SH :
Habituellement, un verrou partagé est requis lorsqu'un processus demande une opération de lecture à partir d'un fichier. Les verrous partagés peuvent prendre en charge les opérations de lecture entre n'importe quel processus. Si vous écrivez un fichier avec un verrou partagé, le processus se bloquera et entrera dans l'état SLEEP jusqu'à ce que le verrou partagé soit déverrouillé 

2. >généralement un processus Ajoutez un verrou exclusif à l'opération d'écriture du fichier Une fois le verrou ajouté au fichier, tout autre processus sera bloqué lors de l'accès au fichier jusqu'à ce qu'il soit déverrouillé.

3. Déverrouillage LOCK_UN :

Déverrouiller le descripteur de fichier verrouillé

Cette méthode de verrouillage peut certes garantir l'atomicité du bloc de programme verrouillé, mais elle sacrifie également l'atomicité du programme. Par conséquent, dans notre programme actuel, le moins de logique de programme possible (en particulier les verrous exclusifs) doit être intégré entre les codes de verrouillage et de déverrouillage du programme pour garantir que le programme est déverrouillé le plus rapidement possible.

Enfin, attachez le programme après avoir ajouté le mécanisme de verrouillage :

<?php 
$usrinfo = isset($_GET["usrinfo"])?$_GET["usrinfo"]:exit(1); 
$stinfo = isset($_GET["stinfo"])?$_GET["stinfo"]:exit(1); 
echo $stinfo; 
$pid = posix_getpid(); 
$fp = fopen(“usrinfo.txt”,”a+”); 
$num = rand(0,100000); 
flock($fp,LOCK_EX); 
fwrite($fp,”user:”.$usrinfo.” stinfo:”.$stinfo.”–”.$pid.”–”.$num.”\n”); 
fwrite($fp,”talking 1 — pid:$pid and num:$num\n”); 
flock($fp,LOCK_UN); 
fclose($fp);
L'exécution de ce programme dans des circonstances normales produira des résultats corrects.

Quelle méthode peut-on utiliser pour garantir l'atomicité lors des opérations par lots ?

Par exemple : supprimez plusieurs articles, mais l'un d'entre eux a été supprimé. Si une erreur se produit ici, comment annuler toute l'opération et localiser le message d'erreur ?
Les transactions de base de données garantissent l'atomicité mais ne peuvent pas localiser les messages d'erreur. Mais que devons-nous faire si nous rencontrons un scénario dans lequel les transactions ne peuvent pas être utilisées ?

Il est plus raisonnable d'utiliser des transactions de base de données. Les informations d'erreur peuvent être enregistrées si une opération échoue, une erreur sera générée.

Appliquez une logique pour garantir que chaque opération est enregistrée, que le succès ou l'échec soit enregistré. Si quelque chose ne va pas au milieu, vous pouvez annuler le succès. Généralement, notre suppression est une fausse suppression, c'est donc très simple. S'il est supprimé, les informations complètes doivent être enregistrées lors de l'enregistrement.

PHP utilise le verrouillage de fichier pour simuler le verrouillage de processus et réaliser une opération atomique

Utilisez PHP pour réaliser une opération atomique, mais PHP lui-même ne fournit pas de mécanisme de verrouillage de processus. Utilisez le mécanisme de verrouillage de fichier PHP pour simuler le verrouillage de processus via un fichier. Verrouiller pour réaliser le fonctionnement atomique.

Avant le code de l'opération atomique, utilisez un verrou exclusif pour ouvrir un fichier. Le code est le suivant :

$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
 echo "Failed to open the lock file!"; 
 exit(1);//异常处理
 }
flock ( $fp, LOCK_EX );
Après le code de l'opération atomique, déverrouillez le fichier et. fermez le fichier. Le code est le suivant :


flock ( $fp, LOCK_UN );
fclose ( $fp );
Le pseudo-code global est :


define("LOCK_FILE_PATH", "/tmp/lock");
if( !file_exists(LOCK_FILE_PATH) ){ 
$fp = fopen( LOCK_FILE_PATH, "w" );
fclose ( $fp );
}
$fp = fopen( LOCK_FILE_PATH, "r" );
if (!$fp) {
echo "Failed to open the lock file!";
exit(1);//异常处理
}
flock ( $fp, LOCK_EX );
//此处添加原子操作代码
flock ( $fp, LOCK_UN );
fclose ( $fp );
Ce qui précède peut implémenter des opérations atomiques PHP et éviter les conflits. .

Opérations atomiques php et opérations atomiques mysql

La méthode courante pour les opérations atomiques consiste à implémenter la restauration des données. Il est assez simple d'utiliser PHP pour implémenter l'opération de restauration de la base de données :
1, établir une connexion à la base de données
2, mysql_query('BEGIN');
3, $SQL = "...";
mysql_query($SQL); Effectuer les opérations de base de données correspondantes
4, déterminer les conditions de restauration :
if(mysql_errno)
{
print mysql_error();
mysql_query('ROLLBACK'); Revenir en arrière si une erreur se produit
exit();
5, vous pouvez répéter les étapes 3 et 4 ci-dessus pour démarrer le processus. (D'autres opérations peuvent être ajoutées au milieu, ne se limitant pas aux mises à jour de la base de données, mais attention à ne pas laisser une transaction prendre trop de temps, car cela verrouillerait toutes les tables que vous utilisez, ce qui affecterait l'utilisation d'autres programmes)
Vous pouvez également le faire en plusieurs fois. Après une instruction de mise à jour SQL correcte, écrivez délibérément une instruction incorrecte pour voir si elle est annulée.
6, terminez l'opération de restauration
mysql_query('COMMIT'); Pouvoir arriver ici signifie que les opérations de base de données ci-dessus sont toutes correctes et sont officiellement soumises pour exécution

C'est l'ensemble du processus d'utiliser PHP pour implémenter des opérations atomiques. , une attention particulière doit être accordée à l'établissement d'une structure de table qui prend en charge les opérations de restauration des données

De plus, il existe d'autres moyens de mettre fin à l'opération de restauration en plus de la validation.


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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer