我的网站搭建(第52天) 使用Redis缓存提速

我的网站搭建(第52天) 使用Redis缓存提速


转载:http://yshblog.com/blog/156


昨天在服务器和本地都安装了Redis数据库,具体可看Redis在CentOS和Windows安装过程

安装该数据库是为了做服务器缓存。以下两种情况都适合使用服务器缓存:

1)数据非经常更新。若每次都从硬盘读取一次,浪费服务器资源、拖慢响应速度。

2)数据更新频率较高,服务器负担比较大。


我网站就有这么一些数据:阅读排行榜和7日阅读变化。

这些数据只需每天更新一次。而我每次都从数据库获取相应的数据,计算统计排行情况和阅读数。很明显浪费服务器资源,浪费时间。解决方法是定时统计一次数据,保存到数据库或文件中。每次读取数据从中获取。

若保存到数据库,还需要额外建立一张对应的表存储数据。在Django中建立表通常做法是建立一个模型。看似简单,问题调试麻烦、开发时长久。所以我一直拖着没处理该问题。毕竟一开始访问量不是很多。后来不少网友访客打开慢(当然服务器在国外也是个原因),查了资料发现Redis内存数据库。可以将数据写入到内存,再进行读写。减少计算量,可以有效提高服务器响应速度。

这么一来,我就不用创建新表创建模型。直接将数据写入缓存,定时更新。获取数据从服务器缓存获取即可。


啰嗦了这么多,看看如何实现Redis数据库作服务器缓存。


1、安装redis

具体安装过程,见Redis在CentOS和Windows安装过程

我安装的版本是3.2.8。读写数据之前,记得开启redis服务。否则会显示No connect未连接错误。


2、安装django-redis和settings配置

执行命令,即可安装:

 
 
  1. pip install django-redis

目前django-redis已更新到4.7.0版本。安装完毕之后,给Django项目的settings.py文件添加如下配置。

 
 
  1. CACHES = {
  2.     'default': {
  3.         'BACKEND': 'django_redis.cache.RedisCache',
  4.         'LOCATION': '127.0.0.1:6379',
  5.         "OPTIONS": {
  6.             "CLIENT_CLASS": "django_redis.client.DefaultClient",
  7.         },
  8.     },
  9. }

网上大部分文章该部分配置有误(可能是旧版的redis库对应配置),都是写成如下:

 
 
  1. CACHES = {
  2.     'default': {
  3.         'BACKEND': 'redis_cache.cache.RedisCache',
  4.         'LOCATION': '127.0.0.1:6379',
  5.         "OPTIONS": {
  6.             "CLIENT_CLASS": "redis_cache.client.DefaultClient",
  7.         },
  8.     },
  9. }

都是抄来抄去的文章,错得一模一样。这么写会报错:InvalidCacheBackendError: Could not find backend redis_cache.cache.RedisCache': No module named redis_cache.cache。找不到对应的模块。

另外,LOCATION参数和你的redis.conf文件中IP地址和端口要一致。redis服务才能监听到你的读写操作。


3、测试redis缓存

该步骤非必须,只是为了测试看可否正常使用redis。

进入django的后台命令模式:

 
 
  1. python manage.py shell

逐条输入如下命令测试:

 
 
  1. from django.core.cache import cache #引入缓存模块
  2. cache.set('k', '12314', 30*60)      #写入key为k,值为12314的缓存,有效期30分钟
  3. cache.has_key('k') #判断key为k是否存在
  4. cache.get('k')     #获取key为k的缓存

测试没问题,则说明可正常使用。

若出现错误:ConnectionError: Error 10061 connecting to None:6379。说明没开启redis。


4、redis缓存功能开发

这里需要考虑两个问题:

1)写入redis的数据是什么形式?

2)缓存时效多长?


redis支持字符串、列表、集合、字典等数据结构。经测试,可将Python的字典和列表直接存储。你也可以用json模块对字典和列表转化成字符串再存储。

至于缓存时效看具体情况,建议30分钟或者1小时更新一次。原本我考虑1天更新1次数据,但全球有很多个时区。不是每个时区都和我一样在0点的时候看到更新结果。我们是东八区,我们0点的时候,东九区是1点。所以,每1小时更新一次的频率较为合适,你可以直接设置60*60秒。而我需要整点的时候更新,需要再多一步计算到下一个整点还有多少秒。


获取多少天之前的阅读排行榜代码如下(该部分可以不看):

 
 
  1. #coding:utf-8
  2. import datetime
  3. from blog.models import Blog
  4.  
  5. #获取阅读排行榜
  6. def readed_list(date_end, days, item_num):
  7.     date_start = date_end - datetime.timedelta(days)
  8.  
  9.     qs = Blog.objects.values('id', 'caption')
  10.     qs = qs.filter(view_recorder__view_time__range=[date_start, date_end])
  11.     qs = qs.annotate(read_num=models.Count('view_recorder'))
  12.     qs = qs.order_by('-read_num')[:item_num]
  13.     return qs

这是我自己项目的具体代码,主要获取博客id,博客标题,和博客在这段时间内的阅读数。每一项数据都是字典,再添加到一个列表中。


读写redis缓存代码(敲黑板,这是重点):

 
 
  1. #coding:utf-8
  2. from django.core.cache import cache
  3. import time
  4.  
  5. def get_readed_cache():
  6.     #判断键是否存在
  7.     key = 'readed'
  8.     if cache.has_key(key):
  9.         data = cache.get(key)
  10.     else:
  11.         #不存在,则获取数据,并写入缓存
  12.         data = get_readed_data()
  13.  
  14.         #写入缓存
  15.         cache.set(key, data, 3600-int(time.time() % 3600))
  16.     return data
  17.     
  18. def get_readed_data():
  19.     #日期处理
  20.     now = datetime.datetime.now()
  21.     date_end = datetime.datetime(now.year, now.month, now.day, 0, 0) 
  22.     item_num = 14
  23.  
  24.     #阅读排行
  25.     readed_1 = readed_list(date_end, 1, item_num)
  26.     readed_7 = readed_list(date_end, 7, item_num)
  27.     readed_30 = readed_list(date_end, 30, item_num)
  28.     data = [readed_1, readed_7, readed_30]
  29.     
  30.     return data

使用has_key方法判断键是否存在;get方法获取数据;set方法设置缓存。

写入缓存中的时间是以秒为单位。time.time()得到当前时间,取1小时(3600秒)的余数得到当前小时跑了多少秒。3600减去该值得到距离下个整点还剩多少秒。

得到该数据,再返回给前端页面:

 
 
  1. #coding:utf-8
  2. from django.shortcuts import render_to_response
  3.  
  4. def test(request):
  5.     data = {}
  6.     data["read_lists"] = get_readed_cache()
  7.     return render_to_response('index.html', data)

该方法是示例代码,还需要设置url路由,令其可在前端打开。

前端页面可以用for循环遍历列表,可用键名当作属性获取字典的值。例如:

 
 
  1. {%for read_list in read_lists%}
  2.     {%for blog in read_list%}
  3.         <p>{{blog.caption}}</p>
  4.     {%endfor%}
  5. {%endfor%}

其中,blog变量是一个字典,键有id、caption、read_num。上面代码有写。在模版中,可用属性的方法获取键值。


若你想看看redis保存该数据的样子,可进入redis客户端查看。输入命令redis-cli进入客户端。

再分别输入keys * 查看有那些键,再输入get命令获取数据。结果如下:

20170420/20170420113023183.png


当然,这里我写入redis缓存是被动写入。需要打开前端页面触发该行为。

所以打开页面正好需要写入缓存时,该页面打开速度相对慢一点。有了缓存之后,后面打开速度飞快。经测试,这一点改动,打开首页足足加快了0.5-1秒。

后面,我将采用celery定时任务主动更新缓存。


猜你喜欢

转载自blog.csdn.net/feng98ren/article/details/80232880