Django筆記:Redis鍵值對資料庫
Redis是一種nosql
資料庫(非關係型資料庫),它的資料是以鍵值對的形式儲存在記憶體中的,同時也可以定時將資料同步到磁碟檔案中,即實現資料的持久化,相比於Memcached快取系統,它支援更多的資料結構,如string
、list
(佇列和棧)、set
(集合)、sorted set
(有序集合)、hash
(hash表)等。本文只是簡單整理了下學習筆記,感興趣的話可以檢視中文官方文件。
一、使用場景和特點
1. 常用的使用場景
- 登入會話儲存:儲存在Redis中,與Memcached相比,資料不會丟失。
- 排行榜或計數器:一些實時的排行或計數都可以採用Redis來實現。
- 訊息佇列:如celery就是使用Redis作為中間人。
- 當前線上人數:實時的資料,但是又不需要儲存到資料庫中,可以採用Redis來實現。
- 常用的資料快取:如論壇的首頁等不會經常變化的資料儲存到Redis中。
- 前100文章或評論進行快取:一般情況下,使用者瀏覽資料只會瀏覽前面的部分,可以把這些經常訪問的資料快取到Redis資料庫中。
- 好友關係:微博的好友關係就是使用Redis實現的。
- 釋出和訂閱功能:可以用來做聊天軟體。
2. 和Memcached的比較
比較項 | Memcached | Redis |
---|---|---|
型別 | 純記憶體快取系統 | 記憶體到磁碟同步資料庫 |
資料型別 | 在定義value時就需要指定資料型別 | 不需要 |
虛擬記憶體 | 不支援 | 支援 |
過期策略 | 支援 | 支援 |
儲存資料安全 | 不支援 | 可以將資料同步到磁碟檔案中 |
災難恢復 | 不支援 | 可以將磁碟中的資料恢復到記憶體中 |
分散式 | 支援 | 支援,主從同步方式 |
訂閱與釋出 | 不支援 | 支援 |
二、安裝和使用
1. 安裝與連線
Redis是不支援Windows系統的,只能在Linux上進行操作。以下示例的命令以ubuntu系統為例。
安裝:sudo apt-get install redis-server
。
解除安裝:sudo apt-get purge --auto-remove redis-server
。
啟動:安裝後預設自動啟動,可以通過命令檢視程序資訊ps aux|grep redis
sudo service redis-server start
(重啟就是restart
)。停止:
sudo service redis-server stop
。連線redis-server:可以使用命令
redis-cli
進行連線,相當於Redis的客戶端,命令格式為redis-cli -h [ip] -p [port]
,如redis-cli -h 127.0.0.1 -p 6379
,Redis預設的啟動埠為6379。設定密碼:在配置檔案
/etc/redis/redis.conf
中放開requirepass password
項,並將password
替換為對應的密碼即可。設定密碼後還是可以正常連線,但是連線之後需要先執行auth [password]
後才能進行正常的資料更新等操作,不然無法進行正常的操作。當然也可以在連線時是用-a
引數指定密碼,如redis-cli -h 127.0.0.1 -p 6379 -a 123456
。其他機器連線本機Redis:預設只能本機連線,如果想要其他機器也能連線到本機的Redis,則需要在配置檔案
/etc/redis/redis.conf
中給bind 127.0.0.1
之後新增具體的本機ip,如bind 127.0.0.1 xxx.xxx.xxx.xxx
,其他機器就能通過後面這個ip來進行連線了。
2. 常用基礎操作
新增:使用set
和get
命令進行資料的新增和獲取,新增資料時預設為字串型別,如果設定的值中含有空格則需要使用雙引號包裹起來。
127.0.0.1:6379> set username zhangsan
OK
127.0.0.1:6379> get username
"zhangsan"
127.0.0.1:6379> set username "zhang san"
OK
127.0.0.1:6379> get username
"zhang san"
刪除:使用del
命令進行刪除。
127.0.0.1:6379> del username
(nil)
設定過期時間:新增資料時如果沒有設定過期時間,則預設為永久不過期。可以採用兩種方式設定過期時間,一種是在新增值時進行設定:set key value EX timeout
或setex key timeout value
,另一種是對已經存在的值進行設定:expire key timeout
。timeout
單位為秒。
檢視過期時間:通過命令ttl key
進行檢視。
檢視所有的key:通過命令keys *
進行檢視。
刪除全部資料:flushall
刪除全部鍵值對,實際工作中慎用。
3. 常用列表操作
Redis中列表操作是有專門的命令來執行的,而不是先建立一個列表,再對列表進行操作。
在列表頭/尾新增資料:lpush/rpush key value
。將value
插入到key
對應的列表的表頭/尾,如果key
不存在,則建立一個空列表並執行lpush/rpush
操作,如果key
對應的值不是列表,則會返回一個錯誤。
檢視列表元素:lrange key start stop
。返回列表內指定區間的元素,如果要檢視全部元素,則可以使用命令lrange key 0 -1
。
移除列表頭/尾元素:lpop/rpop key
。移除(彈出)列表頭/尾的一個元素並返回。
移除列表多個元素:lrem key count value
。刪除列表中指定count
個數的value
元素。count
大於0時,表示從表頭開始搜尋並刪除指定個數值為value
的元素;count
小於0時,表示從表尾開始搜尋並刪除指定個數(絕對值)值為value
的元素;count
等於0時,表示刪除全部值為value
的元素。
根據索引檢視列表元素:lindex key index
。檢視指定索引的元素。
檢視列表元素個數:llen key
。檢視列表中的元素個數。
4. 常用集合操作
同列表一樣,不需要先建立集合,再進行集合操作,在往key
中新增集合資料時,如果沒有則會自動建立該集合。
新增集合元素:sadd key value1 value2 ...
。往集合中新增資料,可以一次新增多個值。
檢視集合元素:smembers key
。檢視集合中的元素。
移除集合元素:srem key value1 value2
。移除集合中的元素,可以一次移除多個元素。
檢視集合中的元素個數:scard key
。檢視集合中的元素個數。
檢視多個集合的交集:sinter key1 key2
。檢視多個集合的交集。
檢視多個集合的並集:sunion key1 key2
。檢視多個集合的並集。
檢視多個集合的差集:sdiff key1 key2
。檢視多個集合的差集。
5. 常用hash操作
雜湊操作指的是value
的資料型別為字典,同樣的,不需要先建立hash表(字典)再進行操作,在新增資料時,如果hash表不存在則會自動建立。
新增資料:hset key field value
。在key
對應的hash表(字典)中新增一個新的鍵值對field/value
。hmset key field1 value1 field2 value2 ...
:一次新增多個鍵值對。
檢視資料:hget key field
。檢視key
對應的hash表(字典)中field
對應的值。
刪除資料:hdel key field
。刪除key
對應的hash表(字典)中field
對應的值。
檢視所有的子鍵值對:hgetall key
。檢視key
對應的hash表(字典)中所有的field/value
。
檢視所有的key:hkeys/hvals key
。檢視key
對應的hash表(字典)中所有的field
或value
。
檢視是否存在某個key:hexists key field
。檢視key
對應的hash表(字典)中是否存在指定的field
。
檢視子鍵值對個數:hlen key
。檢視檢視key
對應的hash表(字典)中的鍵值對個數。
6. 常用事務操作
Redis事務可以一次執行多個命令,具有以下兩個基本特徵:
- 隔離操作:事務中的所有命令都會序列化、按順序執行,不會被打斷。
- 原子操作:事務中的命令要麼全部執行,要麼全部不執行。
開啟一個事務:multi
。執行這個命令後就開啟了一個事務,之後的所有命令都不會被真正的執行,而是在執行該事務的時候一起執行事務中的所有命令。
執行事務:exec
。執行事務中的所有命令,如果事務中的命令有報錯,則該事務也會執行失敗。
取消事務:discard
。在使用multi
命令後,執行exec
命令之前,可以使用discard
命令取消並退出事務。
監視:watch key1 key2 ..
。監視一個或多個key
,在指定監視後,在定義事務過程中,如果該key
的值發生了變化,那麼執行事務時,對該key
的值的修改將不會生效。
取消監視:unwatch
。取消監視所有的key
。
7. 釋出訂閱操作
給某個頻道釋出訊息:publish channel message
。channel
名稱和message
內容都可以自定義。
訂閱某個頻道的訊息:subscribe channel1 channel2 ...
。執行這個命令後,程式相當於進入了一個死迴圈,會一直等待發布者釋出訊息,一旦釋出者釋出了訊息,那麼此訂閱程式就能馬上收到訊息。
三、持久化機制
Redis提供了兩種持久化機制或者說備份方式,即RDB和AOF,它們的儲存方式都是儲存在磁碟的特定檔案中,這兩種方式的配置資訊都在配置檔案/etc/redis/redis.conf
中,它們各自的特點可以參考如下表格。
比較項 | RDB | AOF |
---|---|---|
開啟和關閉 | 預設開啟。如果想要關閉,則註釋掉配置檔案中SNAPSHOTTING 下相關save 即可,如save 900 1 表示如果900秒內發生了一次資料更新操作則進行一次同步,其他save 也是同理,相當於每隔一定時間會檢查一次,如果資料更新次數達到配置的要求則會進行同步,這也是RDB預設的同步機制。 |
預設關閉。如果想要開啟,修改配置檔案中appendonly no 為appendonly yes 即可。 |
同步機制 | 根據配置檔案中save 項配置值,每隔一定時間會檢查一次,如果資料更新次數達到配置的要求則會進行同步。 |
配置檔案中提供了三種同步方式,可以根據需要開啟對應的同步方式即可:appendfsync always (每發生一次更新操作則同步一次),appendfsync everysec (預設,每秒同步一次),appendfsync no (採用作業系統的更新方式,每30秒同步一次)。 |
儲存內容 | 儲存的是具體的鍵值對,如username: zhangsan ,並且資料是經過壓縮的。 |
儲存的是對應的操作命令,如set username zhangsan ,且資料沒有經過壓縮。 |
儲存檔案的路徑 | 根據配置檔案中dir (預設/var/lib/redis )和dbfilename (預設dump.rdb )兩個引數來指定。 |
根據配置檔案中dir (預設/var/lib/redis )和appendfilename (預設appendonly.aof )兩個引數來指定。 |
優點 | 1)因為儲存的資料經過壓縮,所以檔案體積比AOF小。2)因為儲存的是具體的鍵值對,所以恢復速度比AOF塊。3)適用於備份操作。 | 1)因為預設是每秒同步一次,所以即使發生了故障,丟失的資料也不會太多。2)因為儲存的時候是在檔案末尾追加命令,所以備份速度會比較快。3)如果檔案過大時,AOF會對檔案中的命令進行重寫,只保留最小的命令集。 |
缺點 | 1)因為每次同步都會將整個檔案重新壓縮一次,所以一般會將同步的時間間隔設定的較長,而在這個時間內如果發生故障,則會丟失對應的資料。2)每次同步Redis都會fork出一個子程序來進同步操作,當資料量比較大的時候可能會非常耗時。 | 1)因為檔案沒有經過壓縮,所以檔案體積會比RDB大。2)因為每秒就會進行一次同步,所以併發量較大時,效率可能會較低。3)因為儲存的是命令,所以在災難恢復的時候會比RDB慢。 |
四、Python操作Redis
安裝:pip install redis
。
Python中對應操作的方法名大多和客戶端操作時的命令是一致的,可以參考命令來使用,下面只展示部分的操作方法,更多方法可以檢視原始碼。
from redis import Redis
# 連線Redis
cache = Redis(host='192.168.1.17', port=6379, password='123456')
# 1. 普通鍵值對,即value為字串型別
# 新增資料,可以使用ex引數指定過期時間
cache.set('username', 'zhangsan')
# 獲取資料
print(cache.get('username'))
# 刪除資料
cache.delete('username')
# 2. 列表操作
# 新增資料
cache.lpush('languages', 'python')
cache.lpush('languages', 'java')
# 獲取資料
print(cache.lrange('languages', 0, -1))
# 3. 集合操作
# 新增資料
cache.sadd('person', 'zhangsan')
cache.sadd('person', 'lisi')
# 獲取資料
print(cache.smembers('person'))
# 4. hash操作
# 新增資料
cache.hset('person', 'name', 'zhangsan')
cache.hset('person', 'age', '18')
# 獲取資料
print(cache.hgetall('person'))
# 5. 事務操作
# 建立管道(事務)
pl = cache.pipeline()
# 新增命令
pl.set('username', 'lisi')
pl.set('age', '20')
# 執行事務
pl.execute()
# 6. 釋出與訂閱操作
# 監聽操作
ps = cache.pubsub()
# 訂閱頻道
ps.subscribe('mychannel')
while True:
# 監聽訊息
for message in ps.listen():
print(message)
'''
# 釋出訊息(在另一個程式中執行)
from redis import Redis
# 連線Redis
cache = Redis(host='192.168.1.17', port=6379, password='123456')
# 釋出訊息
for i in range(5):
cache.publish('mychannel', '[email protected]')
'''
注:本文為學習筆記,發現錯誤歡迎指出。