Les jeux sociaux ont tendance à être considérablement surchargés (principalement les samedis et dimanches) en raison de la concentration de l'accès des utilisateurs et de l'augmentation correspondante des données des utilisateurs.
Le code problématique peut ne pas être trouvé, même avec des tests de charge, selon le scénario que vous avez créé. Je pense que les revues de code sont également importantes pour dissiper ces angoisses invisibles.
[Point stupéfiant] ・ Libérez la bombe chronométrée d'exploser les samedis et dimanches en regardant la source ・ À mesure que les membres progressent en partageant leurs compétences, la probabilité d'installer des bombes chronométrées qui explosent les samedis et dimanches diminue
Eh bien pour résumer C'est tout (discours de fils de 4 ans)
Maintenant que nous avons un puissant outil de révision appelé git pull request, le seuil est beaucoup plus bas, donc je le recommande!
Lors d'une révision de code, j'entends souvent les gens dire * "Je ne sais pas quoi vérifier" *, j'ai donc résumé les points que je garde à l'esprit lors de la vérification.
Les 5 points suivants doivent être vérifiés en priorité.
Voici les détails à vérifier pour chaque catégorie. Cliquez ici pour l'environnement prérequis.
D'ailleurs, l'importance du contrôle est exprimée par des pictogrammes. : rage :: Absolument correct : scream :: Faites-le réparer sauf si vous avez une bonne raison : confondu :: Par s'il y a une bonne raison
La vérification principale est ** "L'index est-il correctement attaché au SQL d'exécution?" **. J'ai l'impression que beaucoup de gens l'ignorent, probablement parce que la diffusion de l'ORM a rendu difficile la lecture de SQL. Comme cela a un effet important sur la vitesse d'exécution, nous nous concentrerons sur la vérification.
Référence: Points importants lors de l'explication
*: rage: ** Un index est-il utilisé pour l'exécution SQL? ** ** La récupération de données sans index ralentit considérablement avec la quantité de données. *: rage: ** Si un index composite est utilisé, où sont toutes les colonnes utilisées? ** ** Si seules certaines colonnes sont indexées, cela ralentira avec la quantité de données. Pour le SQL complexe, expliquez et vérifiez si key_len est approprié. *: rage: ** Pour les tables où l'intégrité est importante, une clé unique est-elle apposée? ** ** Empêche les données de devenir incohérentes en raison de défauts de code. *: rage: ** Si vous utilisez la sélection pour la mise à jour, envisagez-vous de verrouiller les espaces? ** ** Si vous sélectionnez une mise à jour sur des données inexistantes, un blocage dû à un verrouillage d'espacement peut se produire. *: scream: ** L'ordre par colonne est-il également indexé? ** ** Si la colonne à trier n'est pas indexée, le tri des fichiers se produira et il sera lent. *: scream: ** Les colonnes inutilisées sont-elles indexées? (Y a-t-il des index inutiles?) ** S'il existe de nombreux index inutiles, la régénération de l'index prendra du temps au moment de l'insertion. *: confondu: ** Indexez-vous des colonnes à faible cardinalité? ** ** Les colonnes à faible cardinalité (de nombreuses données en double) sont lentes en raison d'une faible efficacité d'index. *: confondu: ** L'index de couverture est-il perdu parce que vous obtenez des colonnes inutiles? ** ** Comme MySQL est un index de cluster, ce sera plus rapide si la colonne de sélection est couverte par l'index. *: confondu: ** Le nombre prévu d'enregistrements dans la table est-il trop grand? ** ** Si le nombre de données est important, la vitesse d'acquisition et la vitesse d'exécution d'ALTER TABLE seront lentes. Des mesures telles que le partitionnement et le partitionnement sont-elles prises? confirmer.
La principale chose à vérifier est la ** «validité de la taille de la mémoire utilisée» **. Si la mémoire utilisée dépasse maxmemory, il y a un risque qu'une erreur se produise (en raison du paramètre maxmemory-policy) ou que le taux HIT baisse en raison des vibrations.
*: rage: ** L'expiration (TTL) est-elle définie? ** ** Si expire n'est pas défini, la mémoire augmentera jusqu'à ce qu'elle soit terminée. *: rage: ** Si vous exécutez plusieurs commandes, utilisez-vous un revêtement de tuyau? ** ** L'exécution de plusieurs commandes individuellement ralentira.
Mauvais exemple
#Bouclez et enregistrez-vous un par un
for key, value in data_dict.items():
redis_connect.set(key, value)
Utiliser un revêtement de tuyau
with redis_connect.pipeline() as pipe:
#Bouclez et enregistrez-vous dans le pipeline et enregistrez-vous en même temps
for key, value in data_dict.items():
pipe.set(key, value)
pipe.execute()
*: scream: ** La taille de mémoire supposée est-elle trop grande? ** ** Si l'utilisation de la mémoire est trop importante par rapport au serveur préparé, demandez-leur d'envisager d'utiliser le type Hash. *: confondu: ** L'utilisez-vous comme stockage (comme hypothèse de persistance), pas comme cache? ** ** Fondamentalement NG, mais si cela est inévitable, comme avoir besoin d'utiliser un type d'ensemble trié, etc., demandez un numéro de base de données dédié. En effet, s'il se trouve dans le même numéro de base de données que la clé utilisée comme cache, il sera difficile de le vider en cas d'urgence. Assurez-vous également que vous disposez des paramètres AOF (pas de révision de code), d'un lot de génération et d'un moyen de gérer la persistance et la récupération des données.
*: rage: ** Si les données principales acquises sont mises en boucle et traitées, y a-t-il un problème de vitesse même si les données principales acquises deviennent une grande quantité de données? ** ** Si vous exécutez SQL dans la partie traitement ou effectuez des calculs compliqués, il sera considérablement ralenti pendant le fonctionnement pour des raisons telles qu'une augmentation des données de base. Demandez-leur de se demander si les données utilisées dans le traitement peuvent être résumées à l'avance. *: rage: ** N'y a-t-il pas beaucoup d'exécutions SQL? ** ** Même si chaque SQL est rapide, la réponse sera lente si elle s'accumule, et ce sera également une charge sur le serveur de base de données. Est-il possible de mettre en place dans le cas de select? Est-il possible d'insérer en vrac dans le cas d'un insert? Je vais vous demander d'y réfléchir. *: rage: ** La partie importante est-elle enregistrée? ** ** Sans journaux, vous ne pourrez pas enquêter sur les demandes d'un utilisateur. *: rage: ** Est-ce que plusieurs utilisateurs peuvent accéder aux mêmes données en même temps? ** ** Par exemple, lorsque plusieurs utilisateurs peuvent mettre à jour le même enregistrement, comme le traitement d'approbation d'un ami, il existe une possibilité de blocage à moins qu'un traitement exclusif ou un ajustement de l'ordre de mise à jour ne soit effectué. *: scream: ** Avez-vous recréé les roues? ** ** Si un traitement similaire augmente, des problèmes se produiront en raison de l'augmentation de la main-d'œuvre et de l'omission de correction lorsque des modifications de spécifications se produisent. *: scream: ** Y a-t-il un nombre magique? ** ** S'il y a un nombre magique, le code ne peut être lu que par la personne qui mémorise les spécifications, et si la valeur change, des omissions de correction se produiront.
Mauvais exemple
if mission_type == 1331:
#Quel genre de mission est le processus? ??
Facile à comprendre avec enum etc.
if mission_type == MissionType.PlayerLevel:
#S'avère être une mission au niveau du joueur
*: confondu: ** Est-il remanié? ** ** L'une des refactorisations les plus importantes est la méthode d'extraction. Si une grande quantité de code est écrite dans une seule méthode, l'imbrication a tendance à être profonde et il devient difficile pour les membres de comprendre ce qui est fait, d'où et où lors de la lecture. *: confondu: ** Booléen négatif Y a-t-il une branche négative de la variable? ** ** Quel est l'intérieur de la phrase if après tout? Même la personne elle-même est confuse, de sorte que la possibilité d'introduire un défaut augmente.
Exemple extrême
if not_equip != False:
#Quand passez-vous ici? ??
*: rage: ** Y a-t-il des fautes d'orthographe? ** ** Il va sans dire. *: rage: ** Le nom de la méthode est-il approprié? ** ** Si vous mettez également à jour en disant get_xxx, les membres seront confus lors de la lecture du code. *: confondu: ** Suivez-vous les conventions du code? ** ** L'importance varie selon le site, mais si les règles sont respectées, la lisibilité s'améliorera. Dans le cas de Python, il existe une convention commune pep, donc c'est OK si elle est conforme. *: confondu: ** Les caractères pleine largeur sont-ils écrits en continu? ** ** Si des caractères pleine largeur visibles par l'utilisateur sont écrits solidement dans le code, il sera nécessaire de modifier le code lors de la prise en charge de plusieurs langues. Je pense que la plupart des frameworks prennent en charge i18n, alors j'aimerais que vous l'utilisiez. Référence: Django Internationalization Cependant, cela nécessitera du travail supplémentaire, donc s'il n'est pas nécessaire d'internationaliser à l'avenir, nous la transmettrons.
*: rage: ** La plage de transaction est-elle appropriée? Est-il lié dans la mesure où il devrait être engagé / annulé? ** ** Si la plage est incorrecte, les données ne seront pas cohérentes si une exception se produit. Si vous disposez de bases de données distinctes, sachez que vous utilisez également des transactions XA. *: rage: ** Si les mises à jour de MySQL et Redis sont mélangées dans la même requête, considérez-vous quand une exception se produit? ** ** Par exemple, si vous mettez d'abord à jour Redis et qu'une exception se produit lors de la mise à jour de la base de données, Redis ne sera pas restaurée, ce qui rompra la cohérence avec la base de données.
*: rage: ** Si le paramètre est un tableau, est-il acceptable d'augmenter le nombre illégalement? ** ** Par exemple, dans le cas de la réception par lots de cadeaux, si l'ID cible est reçu dans un tableau, si le nombre de tableaux n'est pas défini sur une limite supérieure, la charge du serveur peut augmenter en raison d'une attaque qui a été falsifiée avec une grande quantité de données par un utilisateur malveillant. Il y a du sexe. *: rage: ** Est-il acceptable pour le même utilisateur d'envoyer la même requête plusieurs fois de suite? ** ** Lorsqu'une demande qui aurait dû être faite une fois est envoyée deux fois de suite, la cohérence des données sera perdue si le contrôle exclusif n'est pas effectué. *: rage: ** Y a-t-il des mesures prises lorsqu'un paramètre impossible est envoyé? ** ** Si un utilisateur malveillant modifie un paramètre et exécute l'API, l'intégrité des données sera rompue à moins que la vérification de cohérence ne soit effectuée.
*: rage: ** Le commentaire est-il égal au traitement? ** **
Les membres peuvent mal lire le code si le commentaire est incorrect ou si vous oubliez de modifier le commentaire lorsque vous modifiez le processus.
*: rage: ** Les commentaires correspondants ont-ils plus tard les mots-clés TODO:
et FIXME:
? ** **
Il est souvent oublié et enterré, alors assurez-vous d'ajouter un mot clé pour pouvoir grep plus tard.
TODO:
... Si vous voulez le revoir plus tardFIXME:
... Si vous le corrigez toujours plus tard
*: scream: ** Le code passé est-il commenté et laissé? ** **
Cela fait du bruit lorsque les membres lisent le code, alors laissez-le à l'historique de git.
S'il y a un arrière-plan important et que vous souhaitez laisser le code, l'arrière-plan est le plus important, alors demandez-leur de le laisser avec une explication de l'arrière-plan.