Django1.9開發博客(13)- redis緩存


Redis 是一個高性能的key-value數據庫。redis的出現, 很大程度補償了memcached這類keyvalue存儲的不足,在部分場合可以對關系數據庫起到很好的補充作用。 它提供了Python,Ruby,Erlang,PHP客戶端,使用很方便。

目前Redis已經發布了3.0版本,正式支持分布式,這個特性太強大,以至於你再不用就對不住自己了。

性能測試

服務器配置:Linux 2.6, Xeon X3320 2.5Ghz

SET操作每秒鍾110000次,GET操作每秒鍾81000次

stackoverflow網站使用Redis做為緩存服務器。

安裝redis

服務器安裝篇我寫了專門文章, 請參閱redis入門與安裝

django中的配置

我們希望在本博客系統中,對於文章點擊數、閱覽數等數據實現緩存,提高效率。

requirements.txt

添加如下內容,方便以后安裝軟件依賴,由於在pythonanywhere上面並不能安裝redis服務,所以本章只能在本地測試。

redis==2.10.5
django-redis==4.4.2
APScheduler==3.1.0

 

settings.py配置

新增內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from urllib.parse import urlparse
import dj_database_url

redis_url = urlparse(os.environ.get('REDISTOGO_URL', 'redis://localhost:6959'))
CACHES = {
'default': {
'BACKEND': 'redis_cache.cache.RedisCache',
'LOCATION': '{0}:{1}'.format(redis_url.hostname, redis_url.port),
'OPTIONS': {
'DB': 0,
'PASSWORD': redis_url.password,
'CLIENT_CLASS': 'redis_cache.client.DefaultClient',
'PICKLE_VERSION': -1, # Use the latest protocol version
'SOCKET_TIMEOUT': 60, # in seconds
'IGNORE_EXCEPTIONS': True,
}
}
}

SESSION_ENGINE = 'django.contrib.sessions.backends.cache'
SESSION_CACHE_ALIAS = 'default'

# 本地開發配置放在local_settings.py中
try:
from .local_settings import *
except ImportError:
pass

 

local_settings.py配置

這個是本地開發時候使用到的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
DEBUG = True

CACHES = {
'default': {
'BACKEND': 'redis_cache.cache.RedisCache',
'LOCATION': '192.168.203.95:6379:1',
'OPTIONS': {
'CLIENT_CLASS': 'redis_cache.client.DefaultClient',
# 'PASSWORD': 'secretpassword',
'PICKLE_VERSION': -1, # Use the latest protocol version
'SOCKET_TIMEOUT': 60, # in seconds
'IGNORE_EXCEPTIONS': True,
}
}
}

 

使用方法

cache_manager.py緩存管理器

我們新建一個緩存管理器cache_manager.py,內容如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""
Topic: redis緩存管理器
"""
from ..models import Post
from redis_cache import get_redis_connection
from apscheduler.schedulers.background import BackgroundScheduler

RUNNING_TIMER = False
REDIS_DB = get_redis_connection('default')


def update_click(post):
""" 更新點擊數 """
if REDIS_DB.hexists("CLICKS", post.id):
print('REDIS_DB.hexists...' + str(post.id))
REDIS_DB.hincrby('CLICKS', post.id)
else:
print('REDIS_DB.not_hexists...' + str(post.id))
REDIS_DB.hset('CLICKS', post.id, post.click + 1)
run_timer()


def get_click(post):
""" 獲取點擊數 """
if REDIS_DB.hexists("CLICKS", post.id):
return REDIS_DB.hget('CLICKS', post.id)
else:
REDIS_DB.hset('CLICKS', post.id, post.click)
return post.click

def sync_click():
"""同步文章點擊數"""
print('同步文章點擊數start....')
for k in REDIS_DB.hkeys('CLICKS'):
try:
p = Post.objects.get(k)
print('db_click={0}'.format(p.click))
cache_click = get_click(p.id)
print('cache_click={0}'.format(cache_click))
if cache_click != p.click:
p.click = get_click(p.id)
p.save()
except:
pass

 

views.py修改

然后我們修改view.py,在相應的action里使用這個cache_manager:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from .commons import cache_manager

def post_list(request):
"""所有已發布文章"""
posts = Post.objects.annotate(num_comment=Count('comment')).filter(
published_date__isnull=False).prefetch_related(
'category').prefetch_related('tags').order_by('-published_date')
for p in posts:
p.click = cache_manager.get_click(p)
return render(request, 'blog/post_list.html', {'posts': posts})

def post_detail(request, pk):
try:
pass
except:
raise Http404()
if post.published_date:
cache_manager.update_click(post)
post.click = cache_manager.get_click(post)

 

其他的我就不多演示了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM