Redis是徹底開源免費的,遵照BSD協議,是一個高性能的key-value數據庫(非關係型數據庫)。html
本質:將數據保存在內存中。python
用途:緩存、消息隊列。redis
Redis支持五種數據類型:字符串、列表、哈希散列表、集合、有序集合。和Memcached相似,但它支持存儲的values類型相對更多。這些數據類型都支持push/pop、add/remove及取交集並集和差集及更豐富的操做,並且這些操做都是原子性的。在此基礎上,redis支持各類不一樣方式的排序。數據庫
Redis支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓時能夠再次加載進行使用。與memcached同樣,爲了保證效率,數據都是緩存在內存中。區別的是redis會週期性的把更新的數據寫入磁盤或者把修改操做寫入追加的記錄文件,而且在此基礎上實現了master-slave(主從)同步。vim
Redis支持數據庫備份。緩存
Redis性能極高,讀的速度是110000次/s,寫的速度是8100次/s。安全
Redis豐富的數據類型(String、Lists、Hashes、Sets、Ordered Sets)。服務器
Redis的全部操做都是原子性的,要麼成功執行、要麼徹底失敗不執行,多個操做支持事務,即MULTI和EXEC指令包起來。併發
Redis有豐富的特性,支持publish/subscribe(發佈/訂閱者模式),通知,key過時等特性。socket
相同點:都是NoSQl數據庫,數據存到內存,讀取速度快 好處以下: 1.減小數據庫壓力,提高訪問速度 2.在數據掛掉的狀況下,仍能保證業務正常運行一段時間,提高安全性 不一樣點: (1)類型 memcached:類型單一,只能存字符串"key爲字符串"="value也爲字符串" redis:支持五大類型:string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)、hash(哈希類型) (2)持久化 memcached:斷電數據丟失 redis:支持持久化,單獨開一個進程完成持久化,要保持性能就須要關閉持久化,不少公司並不使用持久化功能
String字符串:能夠包含任何數據,包括圖片以及序列化對象,一個鍵最大能存儲512MB。
List列表:簡單的字符串列表,按照插入順序排序,能夠從兩段進行添加,相似於雙向鏈表,列表還能夠進行阻塞。
Hash散列表:一個String類型的key和value的映射表,hash特別適合存儲對象,類比python字典。
Set集合:字符串類型的無序且不重複集合。集合是經過哈希表實現,因此添加、刪除、查找的時間複雜度都是O(1)。
Zset有序集合:zset和set同樣,不一樣的是每一個元素會關聯一個double類型的分數,redis正是經過對分數的排序對集合進行有序存儲。
(1)Redis安裝
$ wget http://download.redis.io/releases/redis-5.0.2.tar.gz $ tar xzf redis-5.0.2.tar.gz $ cd redis-5.0.2 $ make # 編譯redis程序
(2)Redis啓動
通常啓動reids-server都須要結合配置文件來啓動。這樣在配置文件中的配置就會生效在啓動的redis服務中。
$ pwd /Users/hqs/redis-5.0.2 $ src/redis-server redis.conf # 啓動redis服務 # 啓動新終端,使用內置的客戶端與redis進行交互 $ pwd /Users/hqs/redis-5.0.2 $ src/redis-cli 127.0.0.1:6379> set name 'bobo' OK 127.0.0.1:6379> get name "bobo"
能夠經過redis-cli進入交互模式,使用config命令查看或設置配置項。也能夠進入配置文件用vim編輯器進行修改。
# 獲取全部配置項 reids 127.0.0.1:6379> config get * # 獲取單個配置項 redis 127.0.0.1:6379> config get loglevel # 編輯配置 redis 127.0.0.1:6379> config set loglevel "notice"
首先須要下載安裝redis模塊:pip3 install redis
Redis提供兩個類Redis和StrictRedis用於實現Redis的命令,StrictRedis用於實現大部分官方的命令,並使用官方的語法和命令。
Redis是StrictRedis的子類,用於向後兼容舊版本的redis-py。
Redis鏈接實例是線程安全的,能夠直接將redis鏈接實例設置爲一個全局變量,直接使用。
若是須要另外一個Redis實例(or Redis數據庫)時,就須要從新建立redis鏈接實例來獲取一個新的鏈接。
鏈接redis,加上decode_response=True,寫入的鍵值對中的value爲str類型,不加這個參數寫入的則爲字節類型。
class Redis(object): def __init__(self, host='localhost', port=6379, db=0, password=None, socket_timeout=None, socket_connect_timeout=None, socket_keepalive=None, socket_keepalive_options=None, connection_pool=None, unix_socket_path=None, encoding='utf-8', encoding_errors='strict', charset=None, errors=None, decode_responses=False, retry_on_timeout=False, ssl=False, ssl_keyfile=None, ssl_certfile=None, ssl_cert_reqs='required', ssl_ca_certs=None, max_connections=None, single_connection_client=False, health_check_interval=0):
默認host是'localhost',默認端口是6379。db以數字呈現,默認值是0,配置了16個db,能夠經過配置db來切換到對應的數據庫,至關於對內存中的大redis進行分塊。
password是數據庫密碼,socket_timeout是超時時間,socket_connect_timeout是鏈接超時數。
connection_pool是鏈接池,max_connection是最大鏈接數。
decode_responses很重要,默認值是False,若改成True,則從redis取出的值都是字符串。
import redis """ conn = redis.Redis(host='127.0.0.1', port=6379) # 設置值 conn.set("n1", "v1") conn.hset("n2", "k2", "v2") ret1 = conn.get('n1') ret2 = conn.hget('n2', 'k2') print(ret1, ret2) # 輸出:b'v1' b'v2' """ conn = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True) # 設置值 conn.set("n1", "v1") conn.hset("n2", "k2", "v2") ret1 = conn.get('n1') ret2 = conn.hget('n2', 'k2') print(ret1, ret2) # 輸出:v1 v2
Redis set命令用於在redis中設置值,不存在則建立,存在則修改。
Redis hset命令用於在哈希表中字段賦值。不存在則建立新的哈希表,已存在於哈希表中舊值被覆蓋。
Redis get 命令用於獲取指定 key 的值。返回key的值。若是 key 不存在,返回 nil 。若是key 儲存的值不是字符串類型,返回一個錯誤。
Redis hget 命令用於返回哈希表中指定字段的值。返回給定字段的值。若是給定字段或key不存在,返回nil。
Redis Hmset 命令用於同時將多個 field-value (字段-值)對設置到哈希表中。此命令會覆蓋哈希表中已存在的字段。若是哈希表不存在,會建立一個空哈希表,並執行 HMSET 操做。
import redis conn = redis.Redis(host='127.0.0.1', port=6379, decode_responses=True) conn.hmset("n3", {"k3": "v3", "k4": "v4"}) # 單條單條取 ret3 = conn.hget("n3", "k3") ret4 = conn.hget("n3", "k4") print(ret3, ret4) # v3 v4 # 全取 ret5 = conn.hgetall("n3") print(ret5) # {'k3': 'v3', 'k4': 'v4'}
redis-py使用connection pool來管理對一個redis server的全部鏈接,避免每次創建、釋放鏈接的開銷。
默認,每一個Redis實例都會維護一個本身的鏈接池。能夠直接創建一個鏈接池,而後做爲參數Redis,這樣就能夠實現多個Redis實例共享一個鏈接池
import redis pool = redis.ConnectionPool(host='127.0.0.1', port=6379, decode_responses=True, max_connections=10) # 最大鏈接數 conn = redis.Redis(connection_pool=pool) ret = conn.get("n1") print(ret) # 輸出:v1
若是想要併發操做,就須要寫成單列,以模塊導入就是一個單例,把他作成單例,寫在一個文件裏面,import它就是一個單例。
Redis提供了發佈訂閱功能,能夠用於消息的傳輸,Redis的發佈訂閱機制包括三個部分:發佈者、訂閱者和Channel。
發佈者和訂閱者都是Redis客戶端,Channel則爲Redis服務器端,發佈者將消息發送到某個的頻道,訂閱了這個頻道的訂閱者就能接收到這條消息。
Redis的這種發佈訂閱機制與基於主題的發佈訂閱相似,Channel至關於主題。
redis採用publish命令發送消息,其返回值是接收到該消息的訂閱者的數量。
import redis # 建立鏈接 conn = redis.Redis(host="127.0.0.1", port=6379, decode_responses=True) # 建立發佈者 conn.publish('hqs', 'Hello world!!')
redis採用subscribe命令訂閱某頻道,返回值包含客戶端訂閱的頻道、目前已訂閱的頻道數量、接收到的消息(subscribe表示已經成功訂閱某頻道)。
import redis # 建立鏈接 conn = redis.Redis(host="127.0.0.1", port=6379, decode_responses=True) # 第一步:生成一個訂閱者對象 pubsub = conn.pubsub() # 第二步:訂閱一個消息(實質就是監聽這個鍵) pubsub.subscribe('hqs') # 第三步:死循環一直等待監聽結果 while True: print("working~~~~") msg = pubsub.parse_response() print(msg)
先執行生成三個訂閱者:
再用發佈者發佈消息,訂閱者輸出以下: