在服務器配置不算高的狀況下,頻繁地訪問數據庫會增長許多開銷,當查詢的內容較多或較複雜時,會佔用不少的查詢時間,容易使得訪問卡,慢,出錯等狀況。因爲以前在部署網站的時候,我沒有采用那些經常使用的緩存技術,隨着個人發表文章愈來愈多,我也感覺到了卡,慢的現象,用戶體驗不好。以前我也學習過redis基本使用,並且將所學習內容總結在Redis使用教程 (全)這篇文章裏,此次是將Redis應用在Django項目中,一塊兒來學習下吧!
首先,有必要對redis做一個簡單介紹,一個開源的高性能的key-value存儲系統。前端
1) redis支持數據的持久化,能夠將內存中的數據保持在磁盤中,重啓的時候能夠再次加載進行使用。python
2) redis不只僅支持簡單的key-value類型的數據,同時還提供list,set,sorted set,hash等數據結構的存儲。redis
3) redis支持數據的備份,即master-slave模式的數據備份。shell
1) 性能極高 – redis能讀的速度是110000次/s,寫的速度是81000次/s 。數據庫
2) 豐富的數據類型 – Redis支持二進制案例的 String, List, Hash, Set 及 Sorted Set 數據類型操做。django
3) 原子 – redis的全部操做都是原子性的,同時Redis還支持對幾個操做全並後的原子性執行。json
4) 豐富的特性 – redis還支持 publish/subscribe, 通知, key 過時等等特性。緩存
具體安裝,見Redis使用教程 (全)。安裝好後,可將redis服務以守護進程運行。bash
執行命令,便可安裝:服務器
pip install django-redis
目前django-redis已更新到4.9.0版本。安裝完畢以後,給Django項目的settings.py文件添加以下配置。
CACHES = { 'default': { 'BACKEND': 'django_redis.cache.RedisCache', 'LOCATION': '127.0.0.1:6379', "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", }, }, }
網上大部分文章該部分配置有誤(多是舊版的redis庫對應配置),都是寫成以下:
CACHES = { 'default': { 'BACKEND': 'redis_cache.cache.RedisCache', 'LOCATION': '127.0.0.1:6379', "OPTIONS": { "CLIENT_CLASS": "redis_cache.client.DefaultClient", }, }, }
這麼寫會報錯:InvalidCacheBackendError: Could not find backend redis_cache.cache.RedisCache': No module named redis_cache.cache。找不到對應的模塊。另外,LOCATION參數和你的redis.conf文件中IP地址和端口要一致。redis服務才能監聽到你的讀寫操做。
該步驟非必須,只是爲了測試看能否正常使用redis。進入django的後臺命令模式:
python manage.py shell
逐條輸入以下命令測試。
from django.core.cache import cache #引入緩存模塊 cache.set('k', '12314', 30*60) #寫入key爲k,值爲12314的緩存,有效期30分鐘 cache.has_key('k') #判斷key爲k是否存在 cache.get('k') #獲取key爲k的緩存
測試沒問題,則說明可正常使用。若出現錯誤:ConnectionError: Error 10061 connecting to None:6379。說明沒開啓redis。
redis支持字符串、列表、集合、字典等數據結構。經測試,可將Python的字典和列表直接存儲。也能夠用json模塊對字典和列表轉化成字符串再存儲。
至於緩存時效看具體狀況,建議30分鐘或者1小時更新一次。本來我考慮1天更新1次數據,但全球有不少個時區。不是每一個時區都和我同樣在0點的時候看到更新結果。因此,每1小時更新一次的頻率較爲合適,你能夠直接設置60*60秒。而我須要整點的時候更新,須要再多一步計算到下一個整點還有多少秒。
我將一些複雜的查詢作了改動,主要是一些文章排行的統計,下面是獲取最新發表與最新推薦的排行緩存內容,註釋的部分代碼是以前沒有使用緩存,直接操做的數據庫。其中隨機發表不適合使用緩存,不然查詢出來的就是固定文章,從而不具備隨機性了。
# 最新發表的15篇博客 # new_publish = Post.objects.filter(Q(display=0) | Q(display__isnull=True))[:15] new_publish = cache.get('new_publish') if new_publish is None: new_publish = Post.objects.filter(Q(display=0) | Q(display__isnull=True))[:15] # 60*60表示60秒*60,也就是1小時 cache.set('new_publish', new_publish, 60 * 60) # 獲取Post模型類或模型的實例,並返回ContentType表示該模型的實例 post_content_type = ContentType.objects.get_for_model(Post) # 最新推薦的15篇博客 # new_recommend = get_new_recommend_post(post_content_type) new_recommend = cache.get('new_recommend') if new_recommend is None: new_recommend = get_new_recommend_post(post_content_type) # 60*60表示60秒*60,也就是1小時 cache.set('new_recommend', new_recommend, 60 * 60
還有周榜,月榜,總榜
# 閱讀量周榜博客榜單 # last_7_days_hot_data = get_7_days_read_posts() last_7_days_hot_data = cache.get('last_7_days_hot_data') if last_7_days_hot_data is None: last_7_days_hot_data = get_7_days_read_posts() # 60*60表示60秒*60,也就是1小時 cache.set('last_7_days_hot_data', last_7_days_hot_data, 60 * 60) # 閱讀量月榜博客榜單 # last_30_days_hot_data = get_30_days_read_posts() last_30_days_hot_data = cache.get('last_30_days_hot_data') if last_30_days_hot_data is None: last_30_days_hot_data = get_30_days_read_posts() # 60*60表示60秒*60,也就是1小時 cache.set('last_30_days_hot_data', last_30_days_hot_data, 60 * 60) # 閱讀量總榜博客榜單 # all_hot_posts = get_all_read_posts() all_hot_posts = cache.get('all_hot_posts') if all_hot_posts is None: all_hot_posts = get_all_read_posts() # 60*60表示60秒*60,也就是1小時 cache.set('all_hot_posts', all_hot_posts, 60 * 60)
這裏只是簡單地表示一下緩存的應用,因此直接將定義的函數寫入了代碼中,若是不清楚排行的統計功能,能夠看看以前寫的博客統計排行。運行以後可使用redis-cli和keys *的命令檢查當前redis庫中是否存在上述鍵,若是沒有看到,能夠嘗試從新啓動Web服務。
此處寫入redis緩存是被動寫入。須要打開前端頁面觸發該行爲,一小時後緩存內容自動消失,仍須要從新加載。因此打開頁面正好須要寫入緩存時,該頁面打開速度相對慢一點。有了緩存以後,後面打開速度仍是有很多改善。爲了解決緩存自動消失的bug,還須要加入celery定時調度任務,我會在下篇內容進行更新。
原文出處:https://jzfblog.com/detail/114,文章的更新編輯以此連接爲準。歡迎關注源站文章!