前言:本來想寫redis與rabbitMQ的,但寫完redis后感覺有點多,rabbitMQ還是留在下篇博客吧~~
關於redis與rabbitMQ的下載與安裝,可參考redis&rabbitMQ安裝
一、redis基本操作-1
1 import redis 2 #建立連接 3 r=redis.Redis(host="127.0.0.1",port=6379) 4 5 all_keys=r.keys()#輸出所有key,列表[b'age',b'name',b'occupation'] 6 for k in all_keys: 7 print(k,r.get(k)) 8 9 print(r.keys()) 10 11 r.set("sister","yongli",ex=5) #存入緩存,5秒后清除 12 13 print(r.get("sister")) 14 15 r.set("father","jingxian",nx=True) #只有father不存在時,當前set操作才執行 16 print(r.get("father")) 17 18 r.set("AA","BB",xx=True) #只有AA存在時,當前set操作才執行 19 print(r.get("AA")) 20 21 22 r.mset(k1="v1",k2="v2") #批量設置值 23 print(r.mget("k1","k2")) #批量獲取值 24 25 26 r.set("id","3114007487") 27 print(r.getrange("id",3,6)) #獲取子序列(切片,0開始) 28 29 r.setrange("id",3,"AAA") #修改字符串內容,從指定字符串索引開始向后替換 30 print(r.getrange("id",0,-1)) #輸出:b'311AAA7487' 31 32 #"3" 對應ASCII碼為51, 二進制為 0011 0011 33 print(r.getbit("id",7)) 34 r.setbit("id",7,0) #將第7位改為0,第0位開始算 0011 0010 : 50 對應為2 35 print(r.getbit("id",7)) 36 print(r.getbit("id",1000)) #讀取位數超過,不爆錯 37 print(r.get("id"))
運行結果:

1 b'age' b'22' 2 b'id' b'211AAA7487' 3 b'k2' b'v2' 4 b'k1' b'v1' 5 b'name' b'abc' 6 b'occupation' b'student' 7 b'father' b'BB' 8 [b'age', b'id', b'k2', b'k1', b'name', b'occupation', b'father'] 9 b'yongli' 10 b'BB' 11 None 12 [b'v1', b'v2'] 13 b'4007' 14 b'311AAA7487' 15 1 16 0 17 0 18 b'211AAA7487'
redis基本操作-2(供拓展)

getbit(name, offset) 1 # 獲取name對應的值的二進制表示中的某位的值 (0或1) bitcount(key, start=None, end=None) 1 # 獲取name對應的值的二進制表示中 1 的個數 2 # 參數: 3 # key,Redis的name 4 # start,位起始位置 5 # end,位結束位置 strlen(name) 1 # 返回name對應值的字節長度(一個漢字3個字節) incr(self, name, amount=1) 可用於計算PV 1 # 自增 name對應的值,當name不存在時,則創建name=amount,否則,則自增。 2 3 # 參數: 4 # name,Redis的name 5 # amount,自增數(必須是整數) 6 strlen(name) 1 # 返回name對應值的字節長度(一個漢字3個字節) decr(self, name, amount=1) 1 # 自減 name對應的值,當name不存在時,則創建name=amount,否則,則自減。 2 3 # 參數: 4 # name,Redis的name 5 # amount,自減數(整數) append(key, value) 返回字符的長度 1 # 在redis name對應的值后面追加內容 2 3 # 參數: 4 key, redis的name 5 value, 要追加的字符串
上面是redis的基本操作,建議一句句實驗下。
redis是一種no-sql緩存數據庫。數據是存在緩存中的。所以你如果重啟redis-server,會發現之前存的數據都消失了! 為了解決這個問題,可在存數據后加上save命令, 數據便會存到磁盤,重啟后數據不會消失。
二、連接池與計算網站UV實例
1. 連接池
使用connection pool來管理對一個redis server的所有連接,避免每次建立、釋放連接的開銷。
1 import redis 2 3 pool = redis.ConnectionPool(host='10.211.55.4', port=6379) 4 r = redis.Redis(connection_pool=pool)
2.計算網站UV實例
關於PV,UV,IP可以看看我下面的總結,具體也可以參考博客:http://playkid.blog.163.com/blog/static/56287260201361951919690/

PV(page view)即頁面瀏覽量或點擊量,是衡量一個網站或網頁用戶訪問量。具體的說,PV值就是所有訪問者在24小時(0點到24點)內看了某個網站多少個頁面或某個網頁多少次。PV是指頁面刷新的次數,每一次頁面刷新,就算做一次PV流量。
UV(unique visitor)即獨立訪客數,指訪問某個站點或點擊某個網頁的不同IP地址的人數。在同一天內,UV只記錄第一次進入網站的具有獨立IP的訪問者,在同一天內再次訪問該網站則不計數。
IP可以理解為獨立IP的訪問用戶,指1天內使用不同IP地址的用戶訪問網站的數量,同一IP無論訪問了幾個頁面,獨立IP數均為1。
setbit巨流弊的應用場景,想想什么情況下會用到這個功能呢?超大型的應用平台,比如新浪微博,我想查看當前正在登陸的用戶,如何實現?當然你會想到,用戶登陸后在數據庫上的用戶信息上做個標記,然后count去統計做標記的用戶一共有多少,so,當前用戶查看迎刃而解;OK,好好,首先每個用戶登錄都要設置標記,如果當前用戶幾個億,那么得存幾個億的標記位,超級占用庫的開銷;現在就有一個無敵高效的辦法,利用二進制位統計當前在線用戶,什么意思呢?看下面的代碼就能明白了:

1 import redis 2 #建立連接 3 pool = redis.ConnectionPool(host='127.0.0.1', port=6379) 4 r = redis.Redis(connection_pool=pool) 5 6 r.setbit("uv_count1", 5,1) #每來一個連接,則讓字節位設為1 7 r.setbit("uv_count1", 8,1) 8 r.setbit("uv_count1", 3,1) 9 r.setbit("uv_count1", 3,1) #重復的不計算 10 print("uv_count:", r.bitcount("uv_count1")) 11 12 輸出:uv_count: 3
比如:當前第500位用戶在線,則將第500個bit置為1(默認為0)。bitcount統計二級制位中1的個數,setbit和bitcount配合使用,輕松解決當前在線用戶數的問題。1字節=8位,那么10m=8000萬位,即一個億的在線用戶也就10m多的內存就可搞定,這優化不得了!!
三、redis基本hash,list,set基本操作
我會直接用運行的截圖來講hash,list,set基本操作,不然有點無聊~~
Hash操作,redis中Hash在內存中的存儲格式如下圖:
1. hash基本操作
List操作,redis中的List在在內存中按照一個name對應一個List來存儲。如圖:
2. list基本操作
列表的某一個值前或后插入一個新值
r.lpush() 從左邊開始放數據
r.rpush() 從右邊開始放數據
3. set基本操作
四、redis的16個數據庫與有序集合
1. 16個數據庫
Redis有默認16個數據庫,默認在0庫,可以切換(eg:切換到15號數據庫: select 15);但在python中,出於安全考慮,在python的API沒有切換數據庫的概念,可以在連接調用時指定調用的數據庫,但一連接上了就不能切換了。
move(name, db)) # 將redis的某個值移動到指定的db下
2. 有序集合
有序集合: 在集合的基礎上,為每個元素排序;元素的排序需要根據另外一個值來進行比較,所以,對於有序集合,每一個元素有兩個值,即:值和分數,分數專門用來做排序。
有序集合的基本操作
五、redis發布與訂閱
應用場景:一登陸QQ右上角會有廣告。
發布者:服務器
訂閱者:個人用戶
發布與訂閱必須在同一個頻道上(類似於收音機),不然發布方發布后,訂閱方接收不到!
redis_helper.py文件(公共類)
1 import redis 2 3 4 class RedisHelper(object): 5 6 def __init__(self): 7 self.__conn=redis.Redis(host='127.0.0.1') 8 self.chan_sub='fm88.7' #設置兩個頻道,訂閱頻道 9 self.chan_pub='fm88.7' #發布頻道 10 11 def public(self,msg): 12 self.__conn.publish(self.chan_pub,msg) #發布消息 13 returnTrue 14 15 def subscribe(self): 16 pub=self.__conn.pubsub() #生成實例 打開收音機 17 pub.subscribe(self.chan_sub) #擰到那個台 18 m=pub.parse_response() #准備聽,未阻塞,再調用一次就阻塞 19 print(m) #[b'subscribe', b'fm88.7', 1] 20 return pub #返回實例
redis_sub.py
1 from redis_helper import RedisHelper 2 3 obj=RedisHelper() 4 redis_sub=obj.subscribe() #返回實例 5 6 while True:7 msg=redis_sub.parse_response() #聽 8 print(msg) #有消息則打印,無消息則阻塞
redis_pub.py
from redis_helper importRedisHelper obj=RedisHelper() return1=obj.public('love') print(return1)
運行結果(客戶端): 可並發處理多個客戶端。
[b'subscribe', b'fm88.7', 1] [b'message', b'fm88.7', b'love'] [b'message', b'fm88.7', b'love']