Rosmontis&迷迭香的博客&鹤望兰分部

Rosmontis&迷迭香的博客
僅用於Bing訪客使用,若需要最新的文章,建議訪問rosmontis.com
  1. 首页
  2. 正文

Django—使用Django Cache缓存提升网站访问速度

2022年5月7日 9点热度 0人点赞 0条评论

什么是缓存Cache

缓存是一类可以更快的读取数据的介质统称,也指其它可以加快数据读取的存储方式。一般用来存储临时数据,常用介质的是读取速度很快的内存。一般来说从数据库多次把所需要的数据提取出来,要比从内存或者硬盘等一次读出来付出的成本大很多。对于中大型网站而言,使用缓存减少对数据库的访问次数是提升网站性能的关键之一。

为什么要使用缓存Cache

在Django中,当用户请求到达视图后,视图会先从数据库提取数据放到模板中进行动态渲染,渲染后的结果就是用户看到的网页。如果用户每次请求都从数据库提取数据并渲染,将极大降低性能,不仅服务器压力大,而且客户端也无法即时获得响应。如果能将渲染后的结果放到速度更快的缓存中,每次有请求过来,先检查缓存中是否有对应的资源,如果有,直接从缓存中取出来返回响应,节省取数据和渲染的时间,不仅能大大提高系统性能,还能提高用户体验。

来看下下边这段代码

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()

任务执行会不断的输出日志,这些日志就通过上边的Logger类写入数据库,以便前端可以及时读取实时展示,乍看上去并无不妥,但当短时间内日志产生量非常大时便会频繁读写数据库,数据库压力过大从而影响整个程序的执行效率。缓解数据库压力的有效方法就是加缓存

Django Cache

Django本身就带有一个强大的缓存系统,提供不同级别的缓存粒度:可以缓存特定的视图,也可以只缓存部分模板片段,还可以缓存整个网站。但这几类都不是我想要的,本篇文章不会介绍以上几类缓存的使用,需要的话可以参考官网写的很详细

Django同时还提供了底层缓存API,可以使用这个API以任意级别粒度在缓存中存储对象。这正是我所需要的,每次产生的新日志都不再直接写入数据库,而是先写入缓存中,待任务执行完成后一次写入数据库,这样将大大降低对数据库的消耗,且缓存大都使用内存来存储,读写效率极高

缓存配置

Django的底层缓存API使用非常简单,首先需要在配置文件中配置启用缓存,settings.py文件中添加如下代码

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

这里使用了Memcached作为缓存服务,Memcached是一个完全基于内存的缓存服务器,是Django原生支持的最快、最高效的缓存类型,其他还支持的缓存类型有

  • 数据库缓存:django.core.cache.backends.db.DatabaseCache,LOCATION为表名
  • 文件系统缓存:django.core.cache.backends.filebased.FileBasedCache,LOCATION为文件路径
  • 本地内存缓存:django.core.cache.backends.locmem.LocMemCache,LOCATION被用于标识各个内存存储
  • 虚拟缓存:django.core.cache.backends.dummy.DummyCache,仅用于开发模式,只是实现缓存接口,并不做其他操作
  • 自定义的缓存后台,例如redis等

我原本是想直接使用本地内存缓存的,这样就无需再安装Memcached服务了,但是本地内存缓存为进程私有,不可跨进程访问,这就产生了一个问题就是Logger进程写入内存缓存后,我前端展示的进程读不到,就无法实时输出日志了,遂放弃内存缓存,改用Django支持最好的Memcached

使用Memcached前需要先安装memcached服务,以及python连接memcached的包

# debian系统安装memcached服务
apt-get install memcached

# 安装python连接memcached的包python-memcached
pip install python-memcached

每个缓存后端都支持配置额外的参数,从而来控制缓存的行为,有效的参数如下:

TIMEOUT: 用于缓存的默认超时时间,以秒为单位,默认为300秒,当设置为None时表示永不过时,设置为0表示立刻过期不缓存

KEY_PREFIX: 缓存键前缀,如果有设置,则这个设置的值将自动添加到Django服务器使用的所有缓存键之前

VERSION: 通过Django服务器生成的缓存键的默认版本号,有点类似与Redis的db,以下例子能清晰展示VERSION的作用

>>> 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: 传递到缓存后端服务的参数,例如我要传递username、password等参数到后端的memcached服务,那么可以这样写

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,
            }
        }
    }
}

缓存访问

开启Django Cache配置后,就可以使用缓存服务了,基本用法如下

>>> from django.core.cache import cache

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

其中key是一个字符串,value是一个认可picklable形式的python对象,timeout和version参数都是可选的,timeout默认为CACHES配置中相应后端的timeout参数,version为对应的版本,参考上边关于VERSION的解释

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

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

新的参数default的意思是,当请求的key不存在时,则返回default设置的这个值,而不是默认不存在返回的`None

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

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

与cache.set类似,只是当add的key不存在时,则新建key,存在则不做任何操作

>>> cache.add('site', 'https://blog.ops-coffee.cn')
False
>>> cache.get('site')
'https://ops-coffee.cn'
>>>
>>> cache.get('name')
>>> cache.add('name', '运维咖啡吧 博客')
True
>>> cache.get('name')
'运维咖啡吧 博客'

新建成功则会返回True,否则返回False

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

需要2个参数,第一个为key,第二个为key不存在时设置的值。get_or_set意思是如果key存在,则返回key的值,如果不存在则给key设置一个值

>>> cache.get('name')
'运维咖啡吧 博客'
>>> cache.get_or_set('name', '咖啡吧博客')
'运维咖啡吧 博客'
>>>
>>> cache.get('path')
>>> cache.get_or_set('path', '/devops')
'/devops'
>>> cache.get('path')
'/devops'

cache.get_many(keys, version=None)

通过传入一个keys列表,以字典格式返回这些列表中key存在的缓存值

>>> cache.add('name', '运维咖啡吧 博客')
True
>>> cache.set('site', 'https://ops-coffee.cn')
>>> cache.get_many(['site','name','path'])
{'site': 'https://ops-coffee.cn', 'name': '运维咖啡吧 博客'}

cache.set_many(dict, timeout)

通过传入字典,批量设置缓存

>>> cache.set_many({'site':'ops-coffee.cn','name':'运维咖啡吧'})

cache.delete(key, version=None)

删除一个key

>>> cache.delete('site')

cache.delete_many(keys, version=None)

批量删除key

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

cache.clear()

清空缓存,需要注意的是这会删除缓存里的所有key,可能包含一些并不是你设置的key

>>> cache.clear()

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

更新key的过期时间为timeout设置的值,timeout是可选的,如果不写则默认为CACHES设置的TIMEOUT值

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

更新成功则返回True,否则返回False

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

incr递增一个已存在的int类型的key的值,默认情况下递增幅度为1,通过指定delta可以设置递增的幅度

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

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

与incr递增类似,decr为递减

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

cache.close()

如果缓存后端已经实现了close()方法,可以通过cache.close()关闭和缓存的连接

代码优化

知道了代码存在的问题,也了解了Django中如何操作Cache,那么就可以着手优化上边的代码了,优化后的代码如下:

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 + ';'

            # 将详情更新到缓存中
            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

            # 将缓存写入数据库并保存
            subtasklog.details = cache.get(self.key)
            subtasklog.save()

            # 删除缓存
            cache.delete(self.key)

根据任务ID创建缓存key,这条任务下的所有Log都会先写入缓存中,当任务结束时再将缓存中的日志一把写入数据库,从而减轻数据库压力,执行效率得到了极大的提升

标签: 暂无
最后更新:2022年6月7日

Rosmontis

这个人很懒,什么都没留下

点赞

文章评论

取消回复

Rosmontis

这个人很懒,什么都没留下

本站文章约1个月与rosmontis.com同步一次

链接可将rosmontis.net改为com查看更多内容

最新 热点 随机
最新 热点 随机
【拉环社】【Onedrive】仰望夜空的星辰Fine Days/抬头看看吧,看那天上的繁星Fine Days(FD)完整汉化+全CG(4.9GB) 【拉环社】【Onedrive】仰望夜空的星辰IF/抬头看看吧,看那天上的繁星IF -Interstellar Focus-(FD)完整汉化+全CG(2.8GB) 【漩涡社】鲸神的提亚斯提拉/鲸神的Tearstilla 鯨神のティアスティラ 完整汉化+全CG(3.2GB) 【拉环社】【Onedrive】仰望夜空的星辰/抬头看看吧,看那天上的繁星(本作) 见上げてごらん、夜空の星を 完整汉化+全CG(6.5GB) 【SAGA PLANETS】【Onedrive】FD:金色loveriche-金色时光- 金色ラブリッチェ -Golden Time- 完整汉化+全CG(5.5GB) 【SAGA PLANETS】【Onedrive】金辉恋曲四重奏/金色Loveriche 金色ラブリッチェ 完整汉化+全CG(5.6GB) 【Onedrive】娇蛮任性HIGHSPEC ワガママハイスペック 完整汉化(7.2GB) 【Alcot】【Onedrive】FD:将军大人芳华正茂 Fandisc 将軍様はお年頃 ふぁんでぃすく -御三家だヨ!全員集合- 完整汉化+全CG(3.0GB) 【Alcot】【Onedrive】将军大人芳华正茂/将军大人风华正茂 将军様はお年顷 完整汉化+全CG(4.20GB) 国产动画《京剧猫》,被运营耽搁的好动画,哀其不幸怒其不争! 【Onedrive】架向星空之桥AA 架向星空之桥FAN DISC 星空へ架かる桥AA 完整汉化(3.6GB) 【Onedrive】架向星空之桥 星空へ架かる桥 完整汉化(4.3GB) 【颜艺社】【Onedrive】寄宿之恋 かりぐらし恋爱 完整汉化+全CG(2.7GB) 【八月社】【Onedrive】秽翼的尤斯蒂娅 秽翼のユースティア 完整汉化(4.7GB) 【橘子社妈妈累】【Onedrive】回家之前的棉花糖 お家に帰るまでがましまろです 完整汉化+全CG(5.8GB) 【SAGA PLANETS】【Onedrive】花之天使的夏日恋歌 フローラル・フローラブ 完整汉化+全CG(3.7GB) 【音符社】【Onedrive】花与乙女的祝福+花与乙女的祝福 皇家花束 完整汉化(共3.9GB) 【2022.06更新】【Onedrive】最全!花吻在上/亲吻那片花瓣 その花びらにくちづけを 1~20本作+3番外共23作 完整汉化(约10.5GB) 【Onedrive】花色温泉乡/花色七芒星 花色ヘプタグラム 完整汉化(3.6GB) 【CRYSTALIA】红月摇曳的恋之星火SS 与旭同往~来自盛夏的某日~ 旭とワンルーム ~とある夏の一日~ 完整汉化+全CG (550MB) 【CRYSTALIA】红月摇曳的恋之星火SS 与红叶同住 ~来自盛夏的某日~ 紅葉とワンルーム ~とある夏の一日~ 完整汉化+全CG (580MB) 【CRYSTALIA】红月摇曳的恋之星火 紅月ゆれる恋あかり 完整汉化+全CG (2.5GB) 【Onedrive】FD:景之海的艾佩莉亚 ~卡萨布兰卡的骑士~ 景の海のアペイリア ~カサブランカの騎士~ 完整汉化+全CG(2.3GB) 【Onedrive】景之海的艾佩莉娅/海景的艾佩利雅 景の海のアペイリア 完整汉化+全CG(3.0GB) 【柚子社】【Onedrive】管乐恋曲!~The bonds of melody~ ぶらばん! ~The bonds of melody~ 完整汉化(3.0GB) 【Onedrive】【妹抱FD】哥哥,早上起床之前都要抱紧我哦!晚上睡觉之前学更多Java吧!完整汉化+全CG(4.4GB) 【Onedrive】哥哥,早上起床之前都要抱紧我哦!(妹抱)お兄ちゃん、朝までずっとギュってして!完整汉化+全CG(7.0GB) 【SLG】夏日狂想曲:乡间的难忘回忆 【拉环社】【Onedrive】在这苍穹展翅/在这苍穹之中展开双翼 この大空に、翼をひろげてIf My Heart Had Wings 完整汉化(4.3GB) 【拉环社】【Onedrive】在这苍穹展翅-飞行日志- If My Heart Had Wings -Flight Diary- この大空に、翼をひろげて FLIGHT DIARY 完整汉化(3.0GB)
【SLG】夏日狂想曲:乡间的难忘回忆【海豹社】【Onedrive】爱之钥系列 爱之钥田园夏日 アイカギ~アフターデイズ~ 完整汉化+全CG(1.4GB)【SAGA PLANETS】【Onedrive】FD:金色loveriche-金色时光- 金色ラブリッチェ -Golden Time- 完整汉化+全CG(5.5GB)【Onedrive】娇蛮任性HIGHSPEC ワガママハイスペック 完整汉化(7.2GB)【Onedrive】骑士系列 恋骑士Purely☆Kiss 完整汉化+全CG(3.6GB)【CRYSTALIA】红月摇曳的恋之星火 紅月ゆれる恋あかり 完整汉化+全CG (2.5GB)【SAGA PLANETS】【Onedrive】金辉恋曲四重奏/金色Loveriche 金色ラブリッチェ 完整汉化+全CG(5.6GB)【拉环社】【Onedrive】仰望夜空的星辰Fine Days/抬头看看吧,看那天上的繁星Fine Days(FD)完整汉化+全CG(4.9GB)【Onedrive】FD:景之海的艾佩莉亚 ~卡萨布兰卡的骑士~ 景の海のアペイリア ~カサブランカの騎士~ 完整汉化+全CG(2.3GB)【Onedrive】景之海的艾佩莉娅/海景的艾佩利雅 景の海のアペイリア 完整汉化+全CG(3.0GB)【Onedrive】哥哥,早上起床之前都要抱紧我哦!(妹抱)お兄ちゃん、朝までずっとギュってして!完整汉化+全CG(7.0GB)【CRYSTALIA】红月摇曳的恋之星火SS 与红叶同住 ~来自盛夏的某日~ 紅葉とワンルーム ~とある夏の一日~ 完整汉化+全CG (580MB)【CRYSTALIA】红月摇曳的恋之星火SS 与旭同往~来自盛夏的某日~ 旭とワンルーム ~とある夏の一日~ 完整汉化+全CG (550MB)【Onedrive】花色温泉乡/花色七芒星 花色ヘプタグラム 完整汉化(3.6GB)【2022.06更新】【Onedrive】最全!花吻在上/亲吻那片花瓣 その花びらにくちづけを 1~20本作+3番外共23作 完整汉化(约10.5GB)【音符社】【Onedrive】花与乙女的祝福+花与乙女的祝福 皇家花束 完整汉化(共3.9GB)【SAGA PLANETS】【Onedrive】花之天使的夏日恋歌 フローラル・フローラブ 完整汉化+全CG(3.7GB)【橘子社妈妈累】【Onedrive】回家之前的棉花糖 お家に帰るまでがましまろです 完整汉化+全CG(5.8GB)【八月社】【Onedrive】秽翼的尤斯蒂娅 秽翼のユースティア 完整汉化(4.7GB)【颜艺社】【Onedrive】寄宿之恋 かりぐらし恋爱 完整汉化+全CG(2.7GB)【Onedrive】架向星空之桥 星空へ架かる桥 完整汉化(4.3GB)【Onedrive】架向星空之桥AA 架向星空之桥FAN DISC 星空へ架かる桥AA 完整汉化(3.6GB)国产动画《京剧猫》,被运营耽搁的好动画,哀其不幸怒其不争!【Alcot】【Onedrive】将军大人芳华正茂/将军大人风华正茂 将军様はお年顷 完整汉化+全CG(4.20GB)【Alcot】【Onedrive】FD:将军大人芳华正茂 Fandisc 将軍様はお年頃 ふぁんでぃすく -御三家だヨ!全員集合- 完整汉化+全CG(3.0GB)【拉环社】【Onedrive】仰望夜空的星辰/抬头看看吧,看那天上的繁星(本作) 见上げてごらん、夜空の星を 完整汉化+全CG(6.5GB)【漩涡社】鲸神的提亚斯提拉/鲸神的Tearstilla 鯨神のティアスティラ 完整汉化+全CG(3.2GB)【拉环社】【Onedrive】仰望夜空的星辰IF/抬头看看吧,看那天上的繁星IF -Interstellar Focus-(FD)完整汉化+全CG(2.8GB)【雪碧社Sprite】【Onedrive】苍之彼方的四重奏EXTRA2 DL Edition 蒼の彼方のフォーリズム EXTRA2 生肉+全CG(3.5GB)【Onedrive】爱因斯坦携爱敬上APOLLOCRISIS アインシュタインより愛を込めて APOLLOCRISIS 汉化本体+全CG(2.3GB)
详解XHTML中的标题标签与段落标签的使用 【明日方舟】【YOUTUBE转载】轮到早露给你洗脑了 Zabbix被监控端日志报错:cannot send list of active checks to “xxx.xxx.xxx.xxx“: host [zabbix-server] not found 腾讯云TDSQL-C MYSQL版云数据库参数设置详解 【明日方舟解包】【spine】卡涅利安 贴图立绘+动态骨架文件 国产动画《京剧猫》,被运营耽搁的好动画,哀其不幸怒其不争! 【Onedrive】骑士系列 圣骑士Melty☆Lovers 完整汉化+全CG(3.3GB) 【Onedrive】爱因斯坦携爱敬上 アインシュタインより愛を込めて 汉化本体+全CG(3.9GB) 【鬼畜病毒评测】JJY病毒 Linux查看CPU,内存信息命令集合(查看CPU和内存频率,CPU核数,内存大小等) AI自动写网文—一秒生成十字的超级网文生成器 HTML实现移动端固定悬浮半透明搜索框 【Onedrive】骑士系列 铳骑士Cutie☆Bullet 完整汉化+全CG(2.4GB) 【音符社】【Onedrive】有少女献鸣的爱之奏章 想いを捧げる乙女のメロディー (2.9 GB) 【八月社】【Onedrive】秽翼的尤斯蒂娅 秽翼のユースティア 完整汉化(4.7GB) 用按钮触发事件的方式实现背景色的闪烁效果 【ADV/Onedrive】传颂之物 第一部うたわれるもの(2.0G) 用VB实现一个小星星屏保 【2022.05更新】【Lose】爱上火车まいてつ(PURESTATION+LASTRUN) + 最新补丁合集 (13.0 GB+7.9GB=21.9GB) 重装服务器后SSH无法连接服务器 使用阿里云邮件推送服务创建自己的域名邮箱(SMTP支持80端口发件) 如何让VB程序自动默认以管理员权限运行 【Onedrive】哥哥,早上起床之前都要抱紧我哦!(妹抱)お兄ちゃん、朝までずっとギュってして!完整汉化+全CG(7.0GB) Wordpress迁站后,发布文章后及修改固定链接后打开文章出现404的问题 ocx stock 最实用的54个OCX(ActiveX)控件! 【漩涡社】【Onedrive】NEKO-NIN exHeart 1+PLUS Nachi 猫忍之心1奈知篇 汉化+全CG(0.8G) html 弹出div实现移动居中非常好用 html+css实现充电水滴融合特效代码 【Onedrive】献给神明般的你 神様のような君へ 完整汉化+全CG存档(2.9G) Mysql索引优化与性能调优

COPYRIGHT © 2022 Rosmontis&迷迭香的博客&鹤望兰分部. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang