天天看點

Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理

基于python+mysql淺談redis緩存設計與資料庫關聯資料處理

by:授客  QQ:1033553122

測試環境

redis-3.0.7

CentOS 6.5-x86_64

python 3.3.2

基于Python操作Redis

1、建立示例資料庫表
      
CREATE TABLE tb_signin_rank(
      
id INT,
      
user_name VARCHAR(10) COMMENT '使用者名',
      
signin_num INT COMMENT '簽到次數',
      
signin_time DATETIME COMMENT '簽到時間',
      
gold_coin INT COMMENT '金币' 
      
);
      
初始化資料
      
INSERT INTO tb_signin_rank 
      
VALUES(1, 'shouke', 0, NULL, 0),
      
(2, 'chuangke', 0, NULL, 0),
      
(3, 'ishouke', 0, NULL, 0),
      
(4, 'keshou', 0, NULL, 0),
      
(5, 'shouke', 0, NULL, 0);
      
2、redis緩存鍵值設計
      
key               value
      
表名:主鍵值:列名   列值
      
或者如下,通過為不同列之間建立較為緊密的關聯
      
key                        value
      
表名:主鍵值:列值1:列名2   列值2
      
示例:把id為1的人的簽到次數(假設為5)存儲到redis中則可如下操作:
      
set('tb_signin_rank:1:signin_num', 5)
      
這樣做的好處是,類似資料庫一樣,通過主鍵便可擷取其它值。
      
示例:把id和使用者名關聯
      
set('tb_signin_rank:shouke:id', 1)
      
這樣,通過使用者名就可以查詢出關聯的id了:uid = r.get("tb_signin_rank:%s:id" % username)
      
3、redis關聯資料庫的資料處理
      
不要求強一緻實時性的讀請求,都由redis處理
      
要求強一緻實時性的讀請求,由資料庫處理
      
通常包含以下兩種處理模式:
      
模式1:
      
如圖,先判斷是否存在緩存(通常是根據key),如果存在則從緩存讀取,否則從資料庫讀取并更新緩存。
      
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
适用場景:對資料實時性要求不高,更新比較不頻繁,比如簽到排行榜
      
模式2:
      
如下圖,先寫入redis然後,利用守護程序等方式,定時寫入到資料庫
      
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
模式3:
      
如下圖,先寫入資料庫,然後再更新到緩存
      
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
适用場景:資料量較大,更新較為頻繁
      
說明:
      
模式2和模式3的差別在于,前者把redis當作資料庫用,通過寫入redis後馬上傳回程式,然後定時把資料寫入資料庫,這也大大提高了通路速度。這種方式不足的是,這種對redis的可靠性依賴性太強
      
4、案例
      
./dbconfig.conf配置
      
[TESTDB]
      
host = 192.168.1.103
      
port = 3306
      
user = testacc
      
passwd = test1234
      
db = testdb
      
charset = utf8
      
#!/usr/bin/env python
      
# -*- coding:utf-8 -*-
      
__author__ = 'shouke'
      
import configparser
      
import sys
      
import mysql.connector
      
import redis
      
if __name__ == '__main__':
      
    pool = redis.ConnectionPool(host='192.168.1.103', port=6379, db=0)
      
    r = redis.Redis(connection_pool=pool)
      
    # r.expire('tb_signin_rank:id:signin_num', 20)
      
    config = configparser.ConfigParser()
      
    # 從配置檔案中讀取資料庫伺服器IP、域名,端口
      
    config.read('./dbconfig.conf')
      
    host = config['TESTDB']['host']
      
    port = config['TESTDB']['port']
      
    user = config['TESTDB']['user']
      
    passwd = config['TESTDB']['passwd']
      
    db_name = config['TESTDB']['db']
      
    charset = config['TESTDB']['charset']
      
    try:
      
        dbconn = mysql.connector.connect(host=host, port=port, user=user, password=passwd, database=db_name, charset=charset)
      
    except Exception as e:
      
        print('初始化資料連接配接失敗:%s' % e)
      
        sys.exit()
      
    # 執行簽到
      
    try:
      
        db_cursor = dbconn.cursor()
      
        for id in range(1, 6):
      
            db_cursor.execute('UPDATE tb_signin_rank SET signin_num = signin_num + 1, signin_time = NOW(), gold_coin = gold_coin + (1 + RAND()*9) WHERE id = %s',(id,))
      
            db_cursor.execute('commit')
      
        # 更新緩存
      
        r.zincrby("tb_signin_rank:id:signin_num", id, 1)
      
    except Exception as e:
      
        print('執行資料庫更新操作失敗:%s' % e)
      
        db_cursor.execute('rollback')
      
        db_cursor.close()
      
        exit()
      
    # 展示使用者簽到次數
      
    for id in range(1, 6):
      
        result = r.zscore('tb_signin_rank:id:signin_num', id)
      
        if not result: # 不存在緩存,從資料庫讀取
      
            print('----從資料庫讀取使用者簽到次數----')
      
            try:
      
                db_cursor = dbconn.cursor()
      
                db_cursor.execute('SELECT signin_num FROM tb_signin_rank WHERE id = %s', (id,))
      
                result = db_cursor.fetchone()[0]
      
                # 更新到緩存
      
                r.zadd('tb_signin_rank:id:signin_num', id, result)
      
            except Exception as e:
      
                print('執行資料庫查詢操作失敗:%s' % e)
      
                db_cursor.close()
      
        else: # 存在緩存,從緩存讀取
      
            print('----從緩存讀取使用者簽到次數----')
      
            result = int(result)
      
        print('sigin_num of user[id=%s]: %s' % (id, result))
      
    # 展示簽到排行榜
      
    result = r.zrevrange('tb_signin_rank:id:signin_num', 0, 10)
      
    print('簽到排行榜:', result)



      
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
參考連接配接:
      
http://www.cnblogs.com/qq78292959/archive/2013/02/05/2892735.html
      

作者:授客

QQ:1033553122

全國軟體測試QQ交流群:7156436

Git位址:https://gitee.com/ishouke

友情提示:限于時間倉促,文中可能存在錯誤,歡迎指正、評論!

作者五行缺錢,如果覺得文章對您有幫助,請掃描下邊的二維碼打賞作者,金額随意,您的支援将是我繼續創作的源動力,打賞後如有任何疑問,請聯系我!!!

           微信打賞                       

支付寶打賞                  全國軟體測試交流QQ群  

Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理
Python 基于python+mysql淺談redis緩存設計與資料庫關聯資料處理