在动态网站中,用户所有的请求,服务器都会去数据库中进行相应的增,删,查,改,渲染模板,执行业务逻辑,最后生成用户看到的页面。
为了减轻压力,基本上网站都会做一些措施,比如图片防盗链,它是通过请求头的refer来确定客户端是从哪里来访问的,从而对一些非法访问的客户端进行封禁。
当一个网站的用户访问量很大的时候,每一次的的后台操作,都会消耗很多的服务端资源,所以必须使用缓存来减轻后端服务器的压力。
缓存是将一些常用的数据保存到内存或者memcache/redis中,在一定的时间内有人来访问这些数据时,不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户。
一、衡量一个网站并发量的两个指标:
- QPS:Queries Per Second意思是“每秒查询率”,是一台服务器每秒能够响应的查询次数,是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准。
- TPS:是TransactionsPerSecond的缩写,也就是事务数/秒。它是软件测试结果的测量单位。一个事务是指一个客户机向服务器发送请求然后服务器做出反应的过程。客户机在发送请求时开始计时,收到服务器响应后结束计时,以此来计算使用的时间和完成的事务个数
如何提高并发量:
- 使用cdn
- 精灵图(一次加载,然后通过定位实现显示相应的图片)
- 页面本地缓存
- nginx做负载均衡,后台服务做集群化的部署
- 后台缓存(django中的缓存)
- 数据库的主从同步
- 读写分离
- 异步处理(celery:分布式的异步任务框架)
二、Django中的几种缓存方式:
- 开发调试缓存(没有缓存)
- 缓存到内存中
- 缓存到文件
- 缓存到数据库
- 缓存到redis中
- Memcache缓存(使用python-memcached模块)
- Memcache缓存(使用pylibmc模块)
经常使用的有文件缓存和redis缓存
三、缓存的配置如下:
1、开发调试的配置
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', # 缓存后台使用的引擎 'TIMEOUT': 300, # 缓存超时时间(默认300秒,None表示永不过期,0表示立即过期) 'OPTIONS':{ 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) }, } }
2、缓存到内存中
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', # 指定缓存使用的引擎 'LOCATION': 'unique-snowflake', # 写在内存中的变量的唯一值 'TIMEOUT': 300, # 缓存超时时间(默认为300秒,None表示永不过期) 'OPTIONS': { 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) } } }
3、缓存到文件中
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache', # 指定缓存使用的引擎 'LOCATION': '/var/tmp/django_cache', # 指定缓存的路径 'TIMEOUT': 300, # 缓存超时时间(默认为300秒,None表示永不过期) 'OPTIONS': { 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) } } }
4、缓存到数据库中
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.db.DatabaseCache', # 指定缓存使用的引擎 'LOCATION': 'cache_table', # 数据库表 'OPTIONS': { 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) } } }
注意:创建缓存的数据库表的语句:python manage.py createcachetable
5、Memcache缓存(使用python-memcached模块)
Memcached是Django原生支持的缓存系统.要使用Memcached,需要下载Memcached的支持库python-memcached或pylibmc.
settings.py
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache', # 指定缓存使用的引擎 'LOCATION': '192.168.10.100:11211', # 指定Memcache缓存服务器的IP地址和端口 'OPTIONS': { 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) } } }
LOCATION也可以配置成如下:
'LOCATION': 'unix:/tmp/memcached.sock', # 指定局域网内的主机名加socket套接字为Memcache缓存服务器 'LOCATION': [ # 指定一台或多台其他主机ip地址加端口为Memcache缓存服务器 '192.168.10.100:11211', '192.168.10.101:11211', '192.168.10.102:11211', ]
6、Memcache缓存(使用pylibmc模块连接memcache)
CACHES = { 'default': { 'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache', # 指定缓存使用的引擎 'LOCATION': '192.168.10.100:11211', # 指定本机的11211端口为Memcache缓存服务器 'OPTIONS': { 'MAX_ENTRIES': 300, # 最大缓存记录的数量(默认300) 'CULL_FREQUENCY': 3, # 缓存到达最大个数之后,剔除缓存个数的比例,即:1/CULL_FREQUENCY(默认3) }, } }
LOCATION配置
'LOCATION': '/tmp/memcached.sock', # 指定某个路径为缓存目录 'LOCATION': [ # 分布式缓存,在多台服务器上运行Memcached进程,程序会把多台服务器当作一个单独的缓存,而不会在每台服务器上复制缓存值 '192.168.10.100:11211', '192.168.10.101:11211', '192.168.10.102:11211', ]
Memcached是基于内存的缓存,数据存储在内存中.所以如果服务器死机的话,数据就会丢失,所以Memcached一般与其他缓存配合使用
四、缓存使用
缓存粒度:
- 全站缓存
- 单页面缓存
- 局部缓存
缓存使用:
1、配置settings.py文件,把cache配置进去
2、单页面缓存,在视图函数上加一个装饰器
FBV
from django.shortcuts import render from django.views.decorators.cache import cache_page import time @cache_page(5) # 过期时间5s def index(request): ctime = time.strftime('%Y-%m-%d %H:%M:%S') return render(request, 'index.html', {'time': ctime})
利用模板语法,展示时间:
通过刷新页面,发现查询到的时间会保存5s,这个是保存在内存中的,如果想保存到文件中,需要在settings.py中进行配置。
CBV
from django.shortcuts import render from django.views.decorators.cache import cache_page from rest_framework.views import APIView from django.utils.decorators import method_decorator import time @method_decorator(cache_page(5), name='dispatch') class ShowTime(APIView): def get(self, request, *args, **kwargs): ctime = time.strftime('%Y-%m-%d %H:%M:%S') return render(request, 'index.html', {'time': ctime})
3、局部视图缓存
视图函数
from django.shortcuts import render import time def index(request): ctime = time.strftime('%Y-%m-%d %H:%M:%S') return render(request, 'index.html', {'time': ctime})
html:
{% cache 参数1 参数2 %}:第一个参数表示缓存时间,第二个参数是key值(取缓存的时候,需要根据key值取)
刷新网页看见,缓存的部分会拿缓存的数据,未缓存的则实时刷新
4、全站使用缓存
全站的缓存通过中间件来实现。
用户的请求通过中间件,经过一系列的认证等操作,如果请求的内容在缓存中存在,则使用FetchFromCacheMiddleware获取内容并返回给用户
当返回给用户之前,判断缓存中是否已经存在,如果不存在,则UpdateCacheMiddleware会将缓存保存至Django的缓存之中,以实现全站缓存
修改settings.py文件,中间件配置:
MIDDLEWARE_CLASSES = ( 'django.middleware.cache.UpdateCacheMiddleware', #响应HttpResponse中设置几个headers 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.middleware.cache.FetchFromCacheMiddleware', #用来缓存通过GET和HEAD方法获取的状态码为200的响应 ) CACHE_MIDDLEWARE_SECONDS=10
注意:
“update” 必须配置在第一个 “fetch” 必须配置在最后一个
5、高级用法
前后端分离项目,缓存的设置值与取值
- cache.set('test_data',{'name':'lqz','age':18},5)
- cache.get('test_data')
from django.core.cache import cache # 设置:cache.set(键,值,有效时间) cache.set('my_key', 'hello, world!', 30) cache.add('add_key', 'New value') cache.set_many({'a': 1, 'b': 2, 'c': 3}) # 获取:cache.get(键) cache.has_key('v') #判断key为v是否存在 cache.get('my_key') cache.get('my_key', 'has expired') cache.get_many(['a', 'b', 'c']) # 删除:cache.delete(键) cache.delete('key') cache.delete_many(['a', 'b', 'c']) # 清空:cache.clear() cache.clear() # 增加时间 cache.set('num', 1) cache.incr('num') # 每次默认增加1秒 cache.incr('num', 10) # 在原来的时间上增加10秒 # 减少时间 cache.decr('num') # 每次默认减少一秒 cache.decr('num', 5) # 在原来的时间上减去5秒 # 禁用客户端缓 # 如果你不在视图中使用缓存,服务器端是肯定不会缓存的,然而用户的客户端如浏览器还是会缓存一些数据,这时你可以使用never_cache禁用掉客户端的缓存。 from django.views.decorators.cache import never_cache @never_cache def index(request): pass # views.py from django.views.decorators.cache import never_cache class MyTime(View): @never_cache def get(self, request): timer = time.time() return HttpResponse(timer) @never_cache def myFun(request): timer = time.time() return HttpResponse(timer)