10 fois plus efficace avec cache dans le développement de Django

Petit poussin. 2021-10-29 09:14:13
fois efficace avec cache dans

Moteur de tâches personnaliséProbiusAprès avoir été en ligne pendant un certain temps,Le petit ami m'a dit qu'il y avait des tâches qui prenaient trop de temps,Les fleurs d'attente ont disparu,Par exemple, la tâche suivante a dépassé24Minutes

Voir le temps d'exécution de chaque sous - tâche,Il s'est avéré qu'il n'était consommé que dans“YARNInstaller le module”Cette sous - tâche prendra plus de temps que20Minutes,L'examen de la logique d'exécution de cette sous - tâche n'a révélé aucun problème,AbandonProbius,L'exécution de cette sous - tâche directement sur le serveur a été surprise de constater que le temps d'exécution n'était que2Minutes,Il est donc certain queProbiusC'est le problème.

Encore une fois, j'ai regardé cette sous - tâche,Le journal de sortie de la tâche trouvée dépasse1wArticle (s),J'ai compris le problème en un instant,Testé à nouveau avec des modifications simples,Exécution initiale24Le temps d'exécution des tâches en minutes est réduit à3Dans les minutes,L'amélioration de l'efficacité est assez évidente

Qu'est - ce qui a changé pour avoir une telle magie?Regardez d'abord le code ci - dessous

class Logger:
def __init__(self, tid, state=None):
self.tid = tid
self.state = state
self.datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
def add(self, details):
subtasklog = SubTaskLog.objects.get(id=self.tid)
if details:
details = details.replace('\n', ' ').replace('\r', ' ')
newlog = self.datetime + ' ' + details + ';'
if subtasklog.details:
subtasklog.details += newlog
else:
subtasklog.details = newlog
if self.state is not None:
subtasklog.state = self.state
subtasklog.save()

.L'exécution des tâches produira continuellement des journaux , Ces journaux passent par Logger La classe écrit dans la base de données , Afin que le Front End puisse lire l'affichage en temps réel , Ça n'a pas l'air mal au début , Mais lorsque la production de journaux est très importante en peu de temps, la base de données est souvent lue et écrite , La pression de la base de données est trop forte pour affecter l'efficacité de l'exécution de l'ensemble du programme . Un moyen efficace de soulager la pression de la base de données est d'ajouter un cache

En fait, j'ai pensé à utiliser le cache quand j'ai écrit ce code , C'est surtout parce que : Au cours de la conception du projet, j'ai préconisé de réduire au minimum la dépendance ,Pas de conception excessive, Viser à répondre aux besoins , Essayez de rendre le projet aussi simple que possible , Ce petit partenaire collaboratif n'a pas l'air d'avoir du mal à lire le Code , Il est facile de trouver la cause d'un problème . Dans des circonstances normales, la qualité quotidienne de la tâche n'est pas grande , La base de données n'est pas difficile à traiter , Capable de répondre aux besoins , L'introduction d'un potentiel de cache nécessite une dépendance accrue , Rendre le projet plus complexe , Donc il n'y a pas de . Mais à en juger par la question ci - dessus , La base de données ne répond plus aux exigences , Il est nécessaire d'ajouter un cache

Django Cache

Django Avec un système de cache puissant , Fournir différents niveaux de granularité du cache : Vous pouvez mettre en cache des vues spécifiques , Vous pouvez également mettre en cache seulement quelques fragments de modèle , Il est également possible de mettre en cache tout le site . Mais aucune de ces catégories n'est ce que je veux , Cet article ne décrit pas l'utilisation des types de cache ci - dessus , Veuillez consulter le site officiel pour plus de détails

Django Le cache sous - jacent est également disponible API,Vous pouvez utiliser ceciAPI Stocker des objets dans le cache à n'importe quel niveau de granularité . C'est exactement ce dont j'ai besoin , Chaque fois qu'un nouveau journal est généré, il n'est plus écrit directement dans la base de données , Au lieu de cela, écrivez d'abord dans le cache , Écrire une fois la tâche terminée dans la base de données , Cela réduira considérablement la consommation de la base de données , Et la plupart des caches utilisent la mémoire pour stocker , Lire et écrire très efficacement

Configuration du cache

Django Cache sous - jacent pour APITrès simple à utiliser, Vous devez d'abord configurer activer la mise en cache dans le fichier de configuration ,settings.pyAjouter le code suivant au fichier

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
'LOCATION': '127.0.0.1:11211',
}
}

Utilisé iciMemcachedEn tant que service de cache,Memcached Est un serveur de cache entièrement basé sur la mémoire ,- Oui.Django Le support natif le plus rapide 、 Le type de cache le plus efficace , Les autres types de cache pris en charge sont

  • Cache de base de données:django.core.cache.backends.db.DatabaseCache,LOCATIONNom du tableau
  • Cache système de fichiers:django.core.cache.backends.filebased.FileBasedCache,LOCATIONPour le chemin du fichier
  • Cache de mémoire locale :django.core.cache.backends.locmem.LocMemCache,LOCATION Utilisé pour identifier les différents magasins de mémoire
  • Cache virtuel :django.core.cache.backends.dummy.DummyCache, Uniquement pour les modèles de développement , Implémenter simplement l'interface cache , Ne faites rien d'autre
  • Arrière - plan de cache personnalisé ,Par exempleredisAttendez.

J'avais l'intention d'utiliser directement le cache mémoire local , De cette façon, il n'est plus nécessaire d'installer MemcachedService rendu, Mais le cache de mémoire local est Processus privé, Non accessible entre les processus , Ce qui pose un problème, c'est que Logger Une fois le processus écrit dans le cache mémoire , Le processus que j'ai montré à l'avant ne pouvait pas lire , Je ne peux pas sortir les journaux en temps réel , Le cache de mémoire est abandonné ,Utilisez plutôtDjango Soutenir les meilleurs Memcached

UtiliserMemcachedIl faut d'abord installermemcachedServices,EtpythonConnexionmemcachedLe sac de

# debianInstallation du systèmememcachedServices
apt-get install memcached
# InstallationpythonConnexionmemcachedLe sac depython-memcached
pip install python-memcached

Chaque arrière - plan de cache supporte la configuration de paramètres supplémentaires , Pour contrôler le comportement du cache , Les paramètres valides sont les suivants :

TIMEOUT: Temps d'arrêt par défaut pour la mise en cache ,En secondes,Par défaut300Secondes,Lorsque défini àNone Quand signifie ne jamais être dépassé ,Set to0 Indique l'expiration immédiate sans mise en cache

KEY_PREFIX: Préfixe de la clé de cache ,S'il y a des paramètres, La valeur de ce paramètre est automatiquement ajoutée à Django Avant toutes les clés de cache utilisées par le serveur

VERSION: AdoptionDjango Numéro de version par défaut de la clé de cache générée par le serveur , Un peu comme RedisDedb, Les exemples suivants montrent clairement VERSIONLe rôle de

>>> from django.core.cache import cache
>>>
>>> cache.set('site', 'ops-coffee.cn', version=37)
>>>
>>> cache.get('site')
>>>
>>> cache.get('site', version=37)
'ops-coffee.cn'
>>>

OPTIONS: Paramètres passés au service d'arrière - plan du cache , Par exemple, je vais passer username、password Attendre les paramètres à l'arrière - plan memcachedServices,Alors, ça pourrait être écrit comme ça.

CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',
'LOCATION': '127.0.0.1:11211',
'OPTIONS': {
'binary': True,
'username': 'user',
'password': 'pass',
'behaviors': {
'ketama': True,
}
}
}
}

Accès au cache

OuvertDjango CacheAprès configuration, Vous pouvez utiliser le Service de mise en cache ,L'utilisation de base est la suivante:

>>> from django.core.cache import cache

cache.set(key, value, timeout=DEFAULT_TIMEOUT, version=None)

Parmi euxkeyC'est une chaîne,value C'est une reconnaissance picklableLa formepythonObjet,timeoutEtversion Les paramètres sont optionnels ,timeoutPar défautCACHES Pour l'arrière - plan correspondant dans la configuration timeoutParamètres,version Pour la version correspondante , Voir ci - dessus pour VERSIONExplication

>>> cache.set('site', 'ops-coffee.cn')
>>>
>>> cache.get('site')
'ops-coffee.cn'
>>>

cache.get(key, default=None, version=None)

Nouveaux paramètresdefaultÇa veut dire..., Quand la demande keyLorsqu'il n'existe pas,Renvoiedefault Cette valeur est définie , Au lieu de cela, il n'y a pas de retour par défaut `None

>>> cache.get('name')
>>>
>>> cache.get('name', 'has expired')
'has expired'

cache.add(key, value, timeout=DEFAULT_TIMEOUT, version=None)

Aveccache.setSimilaire,Juste quandaddDekeyLorsqu'il n'existe pas,Nouveaukey, Il n'y a rien à faire s'il existe

>>> cache.add('site', 'https://blog.ops-coffee.cn')
False
>>> cache.get('site')
'https://ops-coffee.cn'
>>>
>>> cache.get('name')
>>> cache.add('name', ' Café o & M Blogs')
True
>>> cache.get('name')
' Café o & M Blogs'

Un nouveau succès renverra True,Sinon, retournez àFalse

cache.get_or_set(key, default, timeout=DEFAULT_TIMEOUT, version=None)

Besoin2Paramètres,Le premier estkey,Le deuxième estkey Valeur définie lorsqu'elle n'existe pas .get_or_setÇa veut dire que sikeyExiste,RenvoiekeyValeur de, Si ce n'est pas le cas, donnez keyDéfinir une valeur

>>> cache.get('name')
' Café o & M Blogs'
>>> cache.get_or_set('name', ' Café bar blog ')
' Café o & M Blogs'
>>>
>>> cache.get('path')
>>> cache.get_or_set('path', '/devops')
'/devops'
>>> cache.get('path')
'/devops'

cache.get_many(keys, version=None)

En passant dans unkeysListe, Retour à ces listes en format dictionnaire key La valeur cache existe

>>> cache.add('name', ' Café o & M Blogs')
True
>>> cache.set('site', 'https://ops-coffee.cn')
>>> cache.get_many(['site','name','path'])
{'site': 'https://ops-coffee.cn', 'name': ' Café o & M Blogs'}

cache.set_many(dict, timeout)

En passant dans le Dictionnaire , Mise en cache des paramètres de lot

>>> cache.set_many({'site':'ops-coffee.cn','name':' Café o & M '})

cache.delete(key, version=None)

Supprimer unkey

>>> cache.delete('site')

cache.delete_many(keys, version=None)

Suppression par lotskey

>>> cache.delete_many(['site','name'])

cache.clear()

Vider le cache, Notez que cela supprimera tout dans le cache key, Peut - être que ça contient quelque chose que tu n'as pas mis en place key

>>> cache.clear()

cache.touch(key, timeout=DEFAULT_TIMEOUT, version=None)

Mise à jourkeyLe délai d'expiration est detimeoutValeur définie,timeoutEst optionnel, Sinon, la valeur par défaut est CACHESSetTIMEOUTValeur

>>> cache.touch('site', 3)
True

La mise à jour réussie renvoie True,Sinon, retournez àFalse

cache.incr(key, delta=1, version=None)

incr Incrémenter un existant intTypekeyValeur de, Par défaut, l'échelle est 1,Par désignationdelta Vous pouvez définir l'amplitude de l'incrément

>>> cache.set('num', 1)
>>> cache.incr('num')
2
>>> cache.incr('num', 10)
12

cache.decr(key, delta=1, version=None)

Avecincr Incréments similaires ,decrPour diminuer

>>> cache.decr('num')
11
>>> cache.decr('num', 5)
6

cache.close()

Si l'arrière - plan du cache est déjà implémenté close()Méthodes,Peut passercache.close() Fermer la connexion au cache

Optimisation du Code

J'ai compris le problème avec le Code ,J'ai aussi comprisDjangoComment faireCache, Alors vous pouvez commencer à optimiser le Code en haut , Le Code optimisé est le suivant :

class Logger:
def __init__(self, tid, state=None):
self.tid = tid
self.state = state
self.datetime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time.time()))
self.key = 'engine_subtasklog_%d' % self.tid
def add(self, details, sync=False):
subtasklog = SubTaskLog.objects.get(id=self.tid)
if details:
details = details.replace('\n', ' ').replace('\r', ' ')
newlog = self.datetime + ' ' + details + ';'
# Mettre à jour les détails dans le cache
old_log = cache.get(self.key, '')
cache.set(self.key, old_log + newlog) if old_log else cache.set(self.key, newlog)
if self.state is not None:
subtasklog.state = self.state
# Écrire le cache dans la base de données et enregistrer
subtasklog.details = cache.get(self.key)
subtasklog.save()
# Supprimer le cache
cache.delete(self.key)

Selon le mandatIDCréer un cachekey, Tous les Log Est écrit dans le cache en premier , Une fois la tâche terminée, écrivez un journal dans le cache dans la base de données , Pour réduire la pression de la base de données , L'efficacité de l'exécution a été grandement améliorée

Cet article est partagé par Wechat public Number - étranger et poussière (grq100296)

La source originale et les informations reproduites sont détaillées dans le texte,En cas d'infraction,Veuillez contacter: [email protected] Supprimer.

Date de publication originale: 2021-10-26

Participation à cet articleTencent Cloud Self - media Sharing Plan,Bienvenue à la lecture,Partager ensemble.

版权声明
本文为[Petit poussin.]所创,转载请带上原文链接,感谢
https://pythonmana.com/2021/10/20211028160926596K.html

  1. Python,前缀后缀相同时合并
  2. 关于#python#的问题:python
  3. 關於#python#的問題:python
  4. Python,前綴後綴相同時合並
  5. Questions sur # # Python #: Python
  6. Python, préfixe et suffixe combinés en même temps
  7. python manage.py shell无法运行,
  8. python manage.py shell無法運行,
  9. Le shell Python manage.py ne fonctionne pas,
  10. python中使用vscode Import 'matplotlib.pyplot' could not be resolved from source 问题
  11. [Chapter 11 of the full version] Python advanced crawler practice - system master Po anti climbing skills challenge high salary
  12. L'utilisation de vscode Import 'matplotlib.pyplot' en python ne peut pas être résolue à partir du problème source
  13. Python fusionne les deux listes et supprime les éléments dupliqués lors de la fusion
  14. [JS Reverse AES Reverse Encryption] python crawler combat, les jours sont de plus en plus décisifs
  15. 30 jeux Python. Je peux jouer à la pêche au travail pendant une journée.
  16. J'a i collecté un nouveau hit de liste en python, donc c'est un secret que quelqu'un d'autre peut devenir un magnat des médias!
  17. J'a i utilisé Python pour ramper à travers 5000 belles photos de papier peint, un jour oublié Premier amour!
  18. [Python planting system] the best green plant for your girlfriend. Girls love it when they see it! Attachment: should be able to feed - right??!
  19. [Python love guide] two small programs for sweetness burst table are released! Afraid you can't find someone?
  20. J'ai utilisé Python pour ramper 1000 lettres d'amour pour aider mon colocataire à exprimer les fleurs de classe, mais les inverser et les inverser... C'est le secret ultime des fleurs de classe!
  21. J'ai utilisé Python pour me connecter à la plus grande plate - forme de jeu au monde, et à quel point le cryptage steam est intelligent [code source inclus]
  22. python中列表转为矩阵后无法进行矩阵的乘法运算
  23. Python crawler Development and Learning full tutoriel 2nd Edition, banggan 100000 words [recommended Collection]
  24. Python crawler haut de gamme: microstore confus anti - décryptage
  25. La multiplication de la matrice ne peut pas être effectuée lorsque la liste est convertie en matrice en python
  26. Introduction to operators in python (Part 1)
  27. Are the dictionaries in Python ordered
  28. Introduction to dictionaries in Python
  29. List introduction in Python
  30. pandas比较两个dataframe特定数据列的数值是否相同并给出差值:使用np.where函数
  31. Python使用matplotlib绘制透明背景的可视化图像并保存透明背景的可视化结果(transparent background)
  32. Python self study notes -- basic grammar
  33. Python utilise matplotlib pour dessiner une image visuelle de l'arrière - plan transparent et enregistrer les résultats visuels de l'arrière - plan transparent
  34. Pandas compare les valeurs de deux colonnes de données spécifiques à dataframe et donne des valeurs de voyage: en utilisant la fonction np.where
  35. Comment configurer une application ASGI Django avec Postgres, nginx et uvicorn sur Ubuntu 20.04
  36. What are the advantages of Python and how to get started quickly
  37. Python self study notes -- basic data types
  38. Python code reading (Chapter 14): List Union
  39. Analyse statistique de la fonction de données des essais aléatoires Python
  40. Alien invasion project in Python application -- Aliens (Part 2)
  41. Python code reading (Chapter 14): List Union
  42. Lecture du Code Python (article 25): diviser les chaînes multilignes en listes
  43. Python self study notes -- operators
  44. Formation python - différences entre http et HTTPS
  45. Implementation of automatic timing comment function on Python CSDN platform
  46. python+tkinter+treeview子控件快捷键
  47. Raccourcis clavier pour les sous - contrôles Python + tkinter + treeview
  48. Analyse des données Python
  49. python+tkinter+treeview子控件快捷鍵
  50. Devine si je peux attraper Maotai avec la programmation python? Tout est ouvert à github
  51. À propos de pygame.display.set in Python Un petit problème avec mode ()
  52. Implementation of automatic timing comment function on Python CSDN platform
  53. python:dataframe进行iteritem遍历时如何将输出结果按照列分别输出为该列最后一行
  54. python:dataframe進行iteritem遍曆時如何將輸出結果按照列分別輸出為該列最後一行
  55. Python: comment le dataframe affiche les résultats de sortie par colonne à la dernière ligne de la colonne lors de la traversée de l'itemitem
  56. Écrivez un gadget de bureau pour votre fille préférée en python et elle dit que c'est génial!
  57. Introduction to closures in Python 3
  58. Global / nonlocal usage in Python 3
  59. Introduction to context manager in Python 3
  60. Common standard library random, python introductory tutorial 5 or 6 questions a day | Python skill tree