Python視頻學習(十四、Redis)

0. Redis基本介紹

  • NoSQL的世界中沒有一種通用的語言,每種nosql數據庫都有自己的api和語法,以及擅長的業務場景
  • NoSQL中的產品種類相當多:
    • Mongodb
    • Redis
    • Hbase hadoop
    • Cassandra hadoop

NoSQL和SQL數據庫的比較:

  • 適用場景不同:sql數據庫適合用於關係特別複雜的數據查詢場景,nosql反之
  • “事務”特性的支持:sql對事務的支持非常完善,而nosql基本不支持事務
    兩者在不斷地取長補短,呈現融合趨勢

Redis簡介

  • Redis是一個開源的使用ANSI C語言編寫、支持網絡、可基於內存亦可持久化的日誌型、Key-Value數據庫,並提供多種語言的API。從2010年3月15日起,Redis的開發工作由VMware主持。從2013年5月開始,Redis的開發由Pivotal贊助。
  • Redis是 NoSQL技術陣營中的一員,它通過多種鍵值數據類型來適應不同場景下的存儲需求,藉助一些高層級的接口使用其可以勝任,如緩存、隊列系統的不同角色

Redis特性:

Redis 與其他 key - value 緩存產品有以下三個特點:

  • Redis支持數據的持久化,可以將內存中的數據保存在磁盤中,重啓的時候可以再次加載進行使用。
  • Redis不僅僅支持簡單的key-value類型的數據,同時還提供list,set,zset,hash等數據結構的存儲。
  • Redis支持數據的備份,即master-slave模式的數據備份

Redis 優勢

  • 性能極高 – Redis能讀的速度是110000次/s,寫的速度是81000次/s 。
  • 豐富的數據類型 – Redis支持二進制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 數據類型操作。
  • 原子 – Redis的所有操作都是原子性的,同時Redis還支持對幾個操作全並後的原子性執行。
  • 豐富的特性 – Redis還支持 publish/subscribe, 通知, key 過期等等特性。

Redis應用場景

  • 用來做緩存(ehcache/memcached)——redis的所有數據是放在內存中的(內存數據庫)
  • 可以在某些特定應用場景下替代傳統數據庫——比如社交類的應用
  • 在一些大型系統中,巧妙地實現一些特定的功能:session共享、購物車
  • 只要你有豐富的想象力,redis可以用在可以給你無限的驚喜…….

1. 安裝和配置

1.1 下載安裝Redis

官網地址

$ wget http://download.redis.io/releases/redis-5.0.3.tar.gz
$ tar xzf redis-5.0.3.tar.gz
$ sudo mv  redis-5.0.3 /usr/local
$ cd /usr/local/redis-5.0.3
$ sudo make test
$ sudo make install

在這裏插入圖片描述

根據README.md中的說法,make install安裝之後,可以在src目錄下運行

./redis-server /path/to/redis.conf   # 運行server,並且制定配置文件
或者
% ./redis-server --port 9999 --replicaof 127.0.0.1 6379   # 不用配置文件,直接指定參數
% ./redis-server /etc/redis/6379.conf --loglevel debug

但是make install只會安裝二進制文件,並不會配置init 腳本或者配置文件到合適的位置。爲了創建一個開發環境,Redis提供了

% cd utils
% ./install_server.sh

這個腳本會詢問所有情況,並且配置各種deamon服務和配置文件目錄、log目錄等等

之後就會有一個服務,名稱叫做redis_端口號的,啓動即可

遇到的問題

  1. 沒有cc
sudo apt install gcc
  1. jemalloc錯誤
make[1]: Entering directory '/home/yyfyifan/Downloads/redis-5.0.3/src'
    CC Makefile.dep
    CC adlist.o
In file included from adlist.c:34:0:
zmalloc.h:50:10: fatal error: jemalloc/jemalloc.h: No such file or directory
 #include <jemalloc/jemalloc.h>
          ^~~~~~~~~~~~~~~~~~~~~
compilation terminated.
Makefile:248: recipe for target 'adlist.o' failed
make[1]: *** [adlist.o] Error 1
make[1]: Leaving directory '/home/yyfyifan/Downloads/redis-5.0.3/src'
Makefile:6: recipe for target 'test' failed
make: *** [test] Error 2

解決方式:

make MALLOC=libc
  1. tcl版本
You need tcl 8.5 or newer in order to run the Redis test

解決方式:

sudo apt install tcl

或者(下面這個我試了,失敗了)

wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz
sudo tar xzvf tcl8.6.1-src.tar.gz  -C /usr/local/
cd  /usr/local/tcl8.6.1/unix/
sudo ./configure
sudo make
sudo make install 
--------------------- 
原文:https://blog.csdn.net/luyee2010/article/details/18766911 

1.2 配置信息

sudo vi /etc/redis/redis.conf
  • 綁定ip:如果需要遠程訪問,可將此⾏註釋,或綁定⼀個真實ip
    bind 127.0.0.1

  • 端⼝,默認爲6379
    port 6379

  • 是否以守護進程運⾏
    daemonize yes

    • 如果以守護進程運⾏,則不會在命令⾏阻塞,類似於服務
    • 如果以⾮守護進程運⾏,則當前終端被阻塞
    • 設置爲yes表示守護進程,設置爲no表示⾮守護進程
  • 數據⽂件
    dbfilename dump.rdb

  • 數據⽂件存儲路徑
    dir /var/lib/redis

  • ⽇志⽂件
    logfile /var/log/redis/redis-server.log

  • 數據庫,默認有16個
    database 16

  • 主從複製,類似於雙機備份。
    slaveof

1.3 連接服務器

redis-cli  # 默認是連接到本地的6379端口,可以指定參數

運行測試命令:

PING
> PONG

數據庫沒有名稱,默認有16個,通過0-15來標識,連接redis默認選擇第一個數據庫,即0號數據庫

SELECT N # 切換到n號數據庫

2. 數據操作

官網API

2.1 數據類型

redis是key-value的數據結構,每條數據都是⼀個鍵值對。

鍵是字符串,而值有5種類型:

  • 字符串string
  • 哈希hash(相當於字典)
  • 列表list(每個元素都是字符串)
  • 集合set(每個元素都是字符串)
  • 有序集合zset(每個元素都是字符串)
    在這裏插入圖片描述

2.2 字符串類型

字符串類型是Redis中最爲基礎的數據存儲類型,它在Redis中是二進制安全的,這便意味着該類型可以接受任何格式的數據,如JPEG圖像數據或Json對象描述信息等。在Redis中字符串類型的Value最多可以容納的數據長度是512M

命令 說明 例子
set key value 設置鍵值對 set iname itcast
set key value EX 秒數 設置鍵值對的時候設置過期時間 set abc haha EX 5
setex key seconds value 設置鍵、值及過期時間,以秒爲單位 setex aa 3 aa
mset key1 value1 key2 value2 ... 設置多個鍵值 mset a1 python a2 java a3 c
append key value 往已有的鍵對應值中追加字符串 append 'a1' 'haha'
get key 根據鍵獲取值 get 'name'
mget key1 key2 ... 獲取多個值 mget a1 a2 a3

2.3 鍵命令

命令 說明 例子
keys pattern 查看所有符合pattern的鍵,支持通配符 keys *
exists 鍵 查看這個鍵存在不存在,返回1代表存在 exists a1
type 鍵 查看這個鍵對應值的類型 type a
del key1 key2.. 刪除對應的鍵和值 del a1 a2 a3
expire key seconds 設置鍵對應的過期時間,如果沒有設置,則一直存在 expire a1 3
ttl key 查看剩餘存活時間 ttl b2

2.4 hash類型

hash⽤於存儲對象,對象的結構爲屬性、值,值的類型爲string

添加修改命令 說明 例子
hset key field value 創建鍵值對,並且設置hash的單個屬性和值 hset user name itheima(設置鍵 user的屬性name爲itheima)
hmset key field1 value1 field2 value2 ... 創建鍵值對,並且設置多個屬性 hmset u2 name itcast age 11
獲取命令 說明 例子
hkeys key 獲取指定key對應的所有fields hkeys u2
hget key field 獲取指定鍵的指定field對應的value hget u2 name
hmget key field1 field2 ... 獲取指定鍵的多個指定field對應的value hget u2 name age
hvals key 直接獲取該key的hash中所有fields的value hvals u2
刪除命令 說明 例子
del key 刪除鍵
hdel key field1 field2 ... 刪除field和對應的value hdel u2 age

如果出現MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error.錯誤。
那麼運行config set stop-writes-on-bgsave-error no 命令後,關閉配置項stop-writes-on-bgsave-error解決該問題

2.5 list類型

列表的元素類型爲string
按照插⼊順序排序

插入命令 說明 例子
lpush key value1 value2 ... 從列表的左側插入數據 lpush a1 0 1
rpush key value1 value2 .. 從列表的右側插入數據 rpush a1 0 1
linsert key before或after 現有元素 新元素 在指定元素的前或後插⼊新元素 linsert a1 before b 3 在列表元素b的前面插入3
獲取命令 說明 例子
lrange key start stop 返回列表⾥指定範圍內的元素 lrange a1 0 -1
  • start、stop爲元素的下標索引
  • 索引從左側開始,第⼀個元素爲0
  • 索引可以是負數,表示從尾部開始計數,如-1表示最後⼀個元素
設置命令 說明 例子
lset key index value 設置 index索引位置的值,索引從0開始,可以爲負數 lset a 1 z
刪除命令 說明 例子
lrem key count value 從某個方向開始,刪除count個value
如果count=0, 則刪除所有出現的value
如果count>0,那麼從左開始數count個刪除;
如果count<0, 那麼從右開始數-count個刪除

2.6 set類型

元素爲string類型
元素具有唯⼀性,不重複
說明:對於集合沒有修改操作

添加命令 說明
sadd key member1 member2 .. 向key中添加集合值
獲取命令 說明
smembers key 返回所有的元素,無序,不保證和添加順序一致
刪除命令 說明
srem key member1 ... 刪除key集合中的指定元素

2.7 zset類型——有序集合

sorted set,有序集合
元素爲string類型
元素具有唯⼀性,不重複
每個元素都會關聯⼀個double類型的score,表示權重,通過權重將元素從⼩到⼤排序
說明:沒有修改操作

添加命令 說明 例子
zadd key score1 member1 score2 member2 .. 向key中添加權重和值 zadd a4 4 lisi 5 wangwu 6 zhaoliu 3 zhangsan
獲取命令 說明
zrange key start stop 返回索引範圍內的值
zrangebyscore key min max 返回score在min~max之間的值
zscore key member 獲取member的score
刪除命令 說明
zrem key member1 member2 .. 刪除key集合中的指定元素
zremrangebyscore key min max 刪除score在min~max之間的元素

3. Python交互redis

3.1 安裝

Python的redis庫

pip install redis

3.2 使用

from redis import StrictRedis
sr = StrictRedis(host='localhost', port=6379, db=0)  
# 可以簡寫爲  sr = StrictRedis(),相當於本地的
# 根據不同的類型,擁有不同的實例⽅法可以調⽤,與前⾯學的redis命令對應,⽅法需要的參數與命令的參數⼀致

例子:

from redis import *
if __name__=="__main__":
    try:
        #創建StrictRedis對象,與redis服務器建⽴連接
        sr=StrictRedis()
        #添加鍵name,值爲itheima,  成功返回True,否則False
        result=sr.set('name','itheima')
        print(result)
        #輸出鍵的值,如果鍵不存在則返回None
        result = sr.get('name')
        
		# 刪除鍵,返回刪除成功的個數
        result = sr.delete('name')
		print(result) # 1
		# 獲取所有的鍵,不傳參數代表 keys *
        result=sr.keys()

    except Exception as e:
        print(e)

3.3 Djangon中用Redis保存Session

之前django的session默認是存在的數據庫裏面一張session表中,我們也可以把session存儲在redis裏面,訪問速度更快。

  1. 安裝包:
pip install django-redis-sessions

  1. 配置使用Redis來放置Session信息

settings.py中,最下面添加這些

SESSION_ENGINE = 'redis_sessions.session'  # 固定的
SESSION_REDIS_HOST = 'localhost'   # Redis數據庫 ip
SESSION_REDIS_PORT = 6379  # Redis端口
SESSION_REDIS_DB = 2    # 第幾個數據庫
SESSION_REDIS_PASSWORD = ''   # 沒有就空
SESSION_REDIS_PREFIX = 'session'      # 保存在Redis中的key的前綴
  1. 測試
  def session_set(request):
      request.session['name']='itheima'
      return HttpResponse('ok')


  def session_get(request):
      name=request.session['name']
      return HttpResponse(name)

4. Redis配置主從

  • ⼀個master可以擁有多個slave⼀個slave⼜可以擁有多個slave,如此下去,形成了強⼤的多級服務器集羣架構
  • master用來寫數據,slave用來讀數據,經統計:網站的讀寫比率是10:1
  • 通過主從配置可以實現讀寫分離

新版本的Redis, slave這個詞改成了 replica

在這裏插入圖片描述

配置主從

步驟:

  1. 配置主的ip和port
  2. 啓動主,並且指定配置文件
  3. 配置從的ip和port
  4. 配置從的replicaof用來指定主實例的位置
  5. 啓動從,並且指定從的配置文件

主實例配置:

  1. bind和port
bind 192.168.26.128
port 6379
  1. 不要配置 replicaof

  2. 啓動服務

redis-server /path/to/config

從實例配置

  1. 設置port——不要和主的相同
bind 192.168.26.128
port 6380
  1. 配置replicaof指向主實例
replicaof 192.168.26.128 6379
  1. 啓動實例並且指定這個配置文件
redis-server /path/to/slaveconfig

測試主從

redis-cli -h IP  info  # 查看所有該redis信息(包括主從關係)
redis-cli -h IP  info  REPLICATION    # 查看主從關係

在主實例上連接,創建新的內容,在從服務器上查看

不能寫入從,從只能用來讀取

5. Redis集羣

  • 如果同時的訪問量過大(1000w),主服務肯定就會掛掉,數據服務就掛掉了或者發生自然災難。
  • 集羣相當於是網絡中的多臺節點互相連接,並以單一系統的模式加以管理。一個客戶與集羣相互作用時,集羣像是一個獨立的服務器。集羣配置是用於提高可用性和可縮放性。

在這裏插入圖片描述

  • Redis集羣有2類:軟件層面和硬件層面
    • 軟件層面:只有一臺電腦,在這一臺電腦上啓動了多個redis服務。
      在這裏插入圖片描述
    • 硬件層面:存在多臺實體的電腦,每臺電腦上都啓動了一個redis或者多個redis服務。
      在這裏插入圖片描述

5.1 搭建Redis集羣

參考資料:
redis集羣搭建
Python

在2臺機器上啓動6個服務

現在使用2個機器,每個機器上面運行3個redis服務來搭建集羣。

  • 第一臺機器IP爲172.16.179.130, 分別創建3個配置文件:
# 7000.conf
port 7000
bind 172.16.179.130
daemonize yes
pidfile 7000.pid
cluster-enabled yes
cluster-config-file 7000_node.conf
cluster-node-timeout 15000
appendonly yes
# 7001.conf
port 7001
bind 172.16.179.130
daemonize yes
pidfile 7001.pid
cluster-enabled yes
cluster-config-file 7001_node.conf
cluster-node-timeout 15000
appendonly yes
# 7002.conf
port 7002
bind 172.16.179.130
daemonize yes
pidfile 7002.pid
cluster-enabled yes
cluster-config-file 7002_node.conf
cluster-node-timeout 15000
appendonly yes

總結:三個⽂件的配置區別在port、pidfile、cluster-config-file三項

然後啓動三個服務:

redis-server 7000.conf
redis-server 7001.conf
redis-server 7002.conf
  • 第二臺機器IP爲172.16.179.131,也分別創建3個配置文件並且啓動服務:
# 7003.conf
port 7003
bind 172.16.179.131
daemonize yes
pidfile 7003.pid
cluster-enabled yes
cluster-config-file 7003_node.conf
cluster-node-timeout 15000
appendonly yes
# 7004.conf
port 7004
bind 172.16.179.131
daemonize yes
pidfile 7004.pid
cluster-enabled yes
cluster-config-file 7004_node.conf
cluster-node-timeout 15000
appendonly yes
# 7005.conf
port 7005 
bind 172.16.179.131
daemonize yes
pidfile 7005.pid
cluster-enabled yes
cluster-config-file 7005_node.conf
cluster-node-timeout 15000
appendonly yes
redis-server 7003.conf
redis-server 7004.conf
redis-server 7005.conf

創建集羣

redis的安裝包中包含了redis-trib.rb,⽤於創建集羣

6個服務最後會成爲3個節點,每個節點都是一個主一個從。 每個主/從節點會分配到一個 槽的區間, redis集羣存儲內容是存儲在16384 個slot中,所以會把這些槽分配給各個節點,每個節點保存一部分。

具體步驟省略,因爲我嘗試的安裝redis之後找不到這個命令

5.2 數據驗證

連接上任何一個地址,然後寫入數據,它會根據寫入的key來自動跳轉到對應的主node上,然後寫入。

在哪個服務器上寫數據:CRC16

  • redis cluster在設計的時候,就考慮到了去中⼼化,去中間件,也就是說,集羣中 的每個節點都是平等的關係,都是對等的,每個節點都保存各⾃的數據和整個集 羣的狀態。每個節點都和其他所有節點連接,⽽且這些連接保持活躍,這樣就保 證了我們只需要連接集羣中的任意⼀個節點,就可以獲取到其他節點的數據
  • Redis集羣沒有並使⽤傳統的⼀致性哈希來分配數據,⽽是採⽤另外⼀種叫做**哈希 槽 (hash slot)**的⽅式來分配的。redis cluster 默認分配了 16384 個slot,當我們 set⼀個key 時,會⽤CRC16算法來取模得到所屬的slot,然後將這個key 分到哈 希槽區間的節點上,具體算法就是:CRC16(key) % 16384。所以我們在測試的 時候看到set 和 get 的時候,直接跳轉到了7000端⼝的節點
  • Redis 集羣會把數據存在⼀個 master 節點,然後在這個 master 和其對應的salve 之間進⾏數據同步。當讀取數據時,也根據⼀致性哈希算法到對應的 master 節 點獲取數據。只有當⼀個master 掛掉之後,纔會啓動⼀個對應的 salve 節點,充 當 master
  • 需要注意的是:必須要3個或以上的主節點,否則在創建集羣時會失敗,並且當存 活的主節點數⼩於總節點數的⼀半時,整個集羣就⽆法提供服務了

5.3 Python和Redis集羣的交互

安裝包

pip install redis-py-cluster

示例代碼:

from rediscluster import StrictRedisCluster
if __name__ == '__main__':
  try:
      # 構建所有的節點,Redis會使⽤CRC16算法,將鍵和值寫到某個節點上
      startup_nodes = [
          {'host': '192.168.26.128', 'port': '7000'},
          {'host': '192.168.26.130', 'port': '7003'},
          {'host': '192.168.26.128', 'port': '7001'},
      ]
      # 構建StrictRedisCluster對象
      src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
      # 設置鍵爲name、值爲itheima的數據
      result=src.set('name','itheima')
      print(result)
      # 獲取鍵爲name
      name = src.get('name')
      print(name)
  except Exception as e:
      print(e)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章