1. 程式人生 > 實用技巧 >Django筆記:Redis鍵值對資料庫

Django筆記:Redis鍵值對資料庫

Redis是一種nosql資料庫(非關係型資料庫),它的資料是以鍵值對的形式儲存在記憶體中的,同時也可以定時將資料同步到磁碟檔案中,即實現資料的持久化,相比於Memcached快取系統,它支援更多的資料結構,如stringlist(佇列和棧)、set(集合)、sorted set(有序集合)、hash(hash表)等。本文只是簡單整理了下學習筆記,感興趣的話可以檢視中文官方文件

一、使用場景和特點

1. 常用的使用場景

  1. 登入會話儲存:儲存在Redis中,與Memcached相比,資料不會丟失。
  2. 排行榜或計數器:一些實時的排行或計數都可以採用Redis來實現。
  3. 訊息佇列:如celery就是使用Redis作為中間人。
  4. 當前線上人數:實時的資料,但是又不需要儲存到資料庫中,可以採用Redis來實現。
  5. 常用的資料快取:如論壇的首頁等不會經常變化的資料儲存到Redis中。
  6. 前100文章或評論進行快取:一般情況下,使用者瀏覽資料只會瀏覽前面的部分,可以把這些經常訪問的資料快取到Redis資料庫中。
  7. 好友關係:微博的好友關係就是使用Redis實現的。
  8. 釋出和訂閱功能:可以用來做聊天軟體。

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. 常用基礎操作

新增:使用setget命令進行資料的新增和獲取,新增資料時預設為字串型別,如果設定的值中含有空格則需要使用雙引號包裹起來。

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 timeoutsetex key timeout value,另一種是對已經存在的值進行設定:expire key timeouttimeout單位為秒。
檢視過期時間:通過命令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/valuehmset 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表(字典)中所有的fieldvalue
檢視是否存在某個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 messagechannel名稱和message內容都可以自定義。
訂閱某個頻道的訊息:subscribe channel1 channel2 ...。執行這個命令後,程式相當於進入了一個死迴圈,會一直等待發布者釋出訊息,一旦釋出者釋出了訊息,那麼此訂閱程式就能馬上收到訊息。

三、持久化機制

Redis提供了兩種持久化機制或者說備份方式,即RDB和AOF,它們的儲存方式都是儲存在磁碟的特定檔案中,這兩種方式的配置資訊都在配置檔案/etc/redis/redis.conf中,它們各自的特點可以參考如下表格。

比較項 RDB AOF
開啟和關閉 預設開啟。如果想要關閉,則註釋掉配置檔案中SNAPSHOTTING下相關save即可,如save 900 1表示如果900秒內發生了一次資料更新操作則進行一次同步,其他save也是同理,相當於每隔一定時間會檢查一次,如果資料更新次數達到配置的要求則會進行同步,這也是RDB預設的同步機制。 預設關閉。如果想要開啟,修改配置檔案中appendonly noappendonly 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]')
'''

注:本文為學習筆記,發現錯誤歡迎指出。