1. 程式人生 > >Python全棧開發之Redis

Python全棧開發之Redis

lists lin tran res 不支持 管理 rom 地址 參考

No.1 NoSQL
  • 不支持SQL語句
  • 存儲結構和關系數據庫不同,而是采用key-value模式
  • NoSQL類型的數據沒有一種通用的語言,每種數據庫都有自己的api和適用場景
    • Mongodb
    • Redis
    • Hbase hadoop
    • Cassandra hadoop

      No.2 NoSQL和SQL數據的區別

  • 使用場景不同,SQL數據庫適用於關系特別復雜的數據查詢場景,NoSQL反之
  • SQL支持事務,NoSQL基本不支持事務

No.3 Redis

簡介

  • Redis是一個采用C語言編寫的開源的、支持網絡、可持久化日誌型、key-value數據庫,並支持多種編程語言的api
  • Redis是NoSQL的一種,它支持多種key-value數據類型,借助一些高層級的接口使其可以勝任,如緩存、隊列

特性

  • Redis支持數據的持久化,可以將內存的數據存儲在磁盤中,重啟時可以再次加載進行使用
  • Redis不僅僅支持簡單的key-value類型的數據,還支持list、set、zset、hash等數據類型的數據
  • Redis支持數據的備份,即master-salve模式數據備份

優勢

  • 性能極高,讀110000次/s,寫81000次/s
  • 豐富的數據類型,支持二進制的Strings、Lists、Hashes、Sets及Ordered Sets數據類型操作
  • 原子性操作,並且還支持幾個操作合並後的原子性執行
  • 豐富的特性,支持publish/subscribe,通知,key過期等特性

應用場景

  • 用來做緩存
  • 可以在某些場景替代傳統數據庫(社交類應用)
  • 在大型系統中實現session共享、購物車等

參考資料

  • redis官方網站
  • redis中文官網

No.4 安裝與配置

安裝

# 下載
wget http://download.redis.io/releases/redis-3.2.8.tar.gz 
# 解壓
tar -zxvf redis-3.2.8.tar.gz
# 將解壓出來的文件放到/usr/local/redis目錄
sudo mv ./redis-3.2.8 /usr/local/redis/ 
# 切換到/usr/local/redis目錄
cd /usr/local/redis/ 
# 生成
sudo make 
# 生成測試
sudo make test 
會發現報錯
You need tcl 8.5 or newer in order to run the Redis test 
Makefile:225: recipe for target ‘test’ failed 
make: * [test] Error 1
所以,我們要安裝依賴
wget http://downloads.sourceforge.net/tcl/tcl8.6.1-src.tar.gz  
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
再次執行測試
sudo make test
# 將redis的命令安裝到/usr/local/bin/?錄
sudo make install
# 進入/usr/local/bin目錄查看
cd /usr/local/bin
ls -all
- redis-server redis服務器
- redis-cli redis命令行客戶端
- redis-benchmark redis性能測試工具
- redis-check-aof AOF文件修復工具
- redis-check-rdb RDB文件檢索工具
將配置文件拷貝到/etc/redis目錄下
sudo cp /usr/local/redis/redis.conf /etc/redis/

配置

# 綁定ip:指定redis只接受此IP的請求,如果不設置,則默認接收所有請求
bind 127.0.0.1
# 端口,默認為6379
port 6379
# TCP連接中已完成隊列(完成三次握手之後)的長度
tcp-backlog 511
# 是否以守護進程運行
daemonize yes
# 數據文件
dbfilename dump.rdb
# 數據?件存儲路徑
dir /var/lib/redis
# ?誌?件
logfile /var/log/redis/redis-server.log
# 數據庫,默認有16個
database 16
# 主從復制,類似於雙機備份。
slaveof

命令

服務器

# 使用help查看把幫助文檔
redis-server --help
# 啟動
sudo service redis start
# 停止
sudo service redis stop
# 重啟
sudo service redis restart
# 查看服務器進程
ps -ef|grep redis
# 殺掉redis服務器
sudo kill -9 pid
# 以指定配置文件運行redis服務器
sudo redis-server /etc/redis/redis.conf

客戶端

# 使用help查看幫助
redis-cli --help
# 連接redis
redis-cli -h host -p port -a password
# 切換數據庫
select 2

No.5 數據交互

String

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

保存

# 設置鍵值
set key value
# 設置鍵值及過期時間,以秒為單位
setex key seconds value
# 一次設置多個值
mset key1 value1 key2 value2
# 追加值
append key value

獲取

# 根據鍵獲取值,鍵不存在返回nil
get key
# 根據鍵獲取多個值
mget key1 key2

鍵命令(支持所有數據類型)

# 查找鍵,參數支持正則表達式
keys pattern
# 判斷鍵是否存在,存在返回1,否則返回0
exists key
# 查看鍵對應的值的類型
type key
# 刪除鍵及對應的值
del key

栗子

set name kernel 設置鍵為name,value為kernel
setex name 5 kernel 設置鍵為name,value為kernel,過期時間為5秒
mset name1 kernel name2 kernel 設置鍵為name1,值為kernel1,鍵為name2,值為kernel2
append name kernel 為鍵name追加kernel,結果為kernelkernel
get name 獲取鍵name對應的值,結果為kernel
mget name1,name2 獲取鍵name1,name2,返回結果為kernel1,kernel2
keys * 查看所有鍵
keys a* 查看a開頭的所有鍵
exists name 查看鍵name是否存在,返回1
type name 查看鍵name對應的值的類型,返回string
del name1 name2 刪除name1,name2及它們對應的值

hash

  • hash?於存儲對象,對象的結構為屬性、值
  • 值的類型為string

保存

# 設置單個屬性
hset key field value
# 設置多個屬性
hmset key field1 value1 field2 value2

獲取

# 獲取鍵所有的屬性
hkeys key
# 獲取一個屬性的值
hget key field
# 獲取多個屬性的值
hmget key field field
# 獲取所有的值
hvals key

刪除

# 刪除整個hash鍵和值,可以使用上文中的del命令
# 刪除屬性,屬性對應的值也會響應刪除
hdel key field1 field2

栗子

hset user name kernel 設置user的name屬性為kernel
hmset user name kernel password 123 設置user的name屬性為kernel,密碼屬性為123
hkeys user 獲取user的所有鍵
hget user name 獲取user的name屬性值
hmget key name password 獲取user的name,password屬性值
hvals user 獲取user的所有屬性值
hdel user name 刪除user的name屬性

list

  • 列表的元素類型為string
  • 按照插?順序排序

增加

# 在左側添加數據
lpush key value1 value2
# 在右側添加數據
rpush key value1 value2
# 在指定元素的前後添加數據
linsert key before或after 指定元素 欲添加數據
# 設置指定索引位置的值
lset key index value

獲取

# 返回列表裏指定範圍內的元素
lrange key start stop 

刪除

# 刪除指定元素,將列表前count次出現的值為value的元素全部刪除,如果count>0,就從頭到尾移除,直到移除夠count個,如果count<0,就從後向前移除,同樣移除count的絕對值個,如果count=0,就移除所有
lrem key count value

栗子

lpush num 1 2 3 在左側添加數據
rpush num 4 5 6 在右側添加數據
linsert num before 2 8 在2的前面添加8
lset num 1 10 將索引為1的值修改為10
lrange num 1 5 返回num索引從1到5的值
lrem num 1 2 從左到右刪除2個1

set

  • ?序集合
  • 元素為string類型
  • 元素具有唯?性,不重復
  • 集合沒有修改操作

增加

# 添加元素
sadd key member1 member2

獲取

# 返回所有的元素
smembers key

刪除

# 刪除指定元素
srem key member

栗子

sadd names zhangsan lisi wangwu 向鍵為names的集合中添加zhangsan、lisi、wangwu
smembers names 獲取鍵為names的集合中的所有元素
srem names wangwu 刪除鍵為name是集合中的元素wangwu

zset

  • 有序集合
  • 元素為string類型
  • 元素具有唯?性,不重復
  • 每個元素都會關聯?個double類型的score,表示權重,通過權重將元素從?到?排序

增加

# 向鍵的集合中添加權重為score1,score2的元素
zadd key score1 member1 score2 member2

獲取

# 返回指定範圍的元素
zrange key start stop
# 返回權重值在min和max之間的元素
zrangebyscore key min max
# 返回成員member的score值

刪除

# 刪除指定元素
zrem key member member2
# 刪除權重在指定範圍的元素
zremrangebyscore key min max

栗子

zadd names 4 lisi 5 wangwu 6 zhangsan 向鍵為names添加元素lisi、wangwu、zhangsan,權重分別是4 5 6
zrange names 0 -1 獲取鍵為names的集合中的所有元素
zrangebyscore names 4 5 獲取鍵為names的集合中權重在4到5之間的成員
zscore names lisi 獲取鍵為names的集合中元素lisi的權重
zrem names zhangsan 刪除鍵為names的集合中元素張三
zremrangebyscore names 4 5 刪除鍵為names的集合中權重在4到5之間的元素

No.6 與Python交互

方法

StrictRedis對象?法

# 通過init創建對象,指定參數host、port與指定的服務器和端?連接,host默認為localhost,port默認為6379,db默認為0
sr = StrictRedis(host=‘localhost‘, port=6379, db=0)

string

  • set
  • setex
  • mset
  • append
  • get
  • mget
  • key

keys

  • exists
  • type
  • delete
  • expire
  • getrange
  • ttl

hash

  • hset
  • hmset
  • hkeys
  • hget
  • hmget
  • hvals
  • hdel

list

  • lpush
  • rpush
  • linsert
  • lrange
  • lset
  • lrem

set

  • sadd
  • smembers
  • srem

zset

  • zadd
  • zrange
  • zrangebyscore
  • zscore
  • zrem
  • zremrangebyscore

django存儲session

安裝

pip install django-redis-sessions==0.5.6

修改setting.py文件

SESSION_ENGINE = ‘redis_sessions.session‘
SESSION_REDIS_HOST = ‘localhost‘
SESSION_REDIS_PORT = 6379
SESSION_REDIS_DB = 2
SESSION_REDIS_PASSWORD = ‘‘
SESSION_REDIS_PREFIX = ‘session‘

測試

# 打開app01/views.py,創建視圖
def session_set(request):
      request.session[‘name‘]=‘kernel‘
      return HttpResponse(‘ok‘)

  def session_get(request):
      name=request.session[‘name‘]
      return HttpResponse(name)
# 配置url
# 在烏班圖連接redis並切換到上文指定的數據庫
redis-cli
select 2
keys *  # 1) "session:xddes84rchmy8ejsph43cqrrnaii31ji"
get session:xddes84rchmy8ejsph43cqrrnaii31ji
通過base64解密

No.7 主從服務

主從概念

  • 一個master可以擁有多個slave,一個slave又可以擁有多個slave,如此就形成了龐大的集群架構
  • master主要被用來寫數據,slave被用來讀數據
  • 通過主從配置實現讀寫分離

主從配置

配置主

# 查看當前主機的ip地址
ifconfig
# 修改/etc/redis/redis.conf
sudo vim /etc/redis/redis.conf
bind 192.168.1.189
# 重啟redis服務
sudo service redis stop
redis-server /etc/redis/redis.conf

配置從

# 復制主服務的配置文件
sudo cp /etc/redis/redis.conf slave.conf
# 修改redis/slave.conf文件
sudo vi slave.conf 
bind 192.168.1.200
slaveof 192.168.1.189 6379
# 啟動redis服務
sudo redis-server /etc/redis/slave.conf
# 查看主從關系
redis-cli -h 192.168.1.189 -p 6379 info Replication

No.8 Redis集群

為什麽要有集群?

之前介紹了主從的概念,可以一主多從,但是如果當訪問量過多,例如雙11,主服務器肯定會掛掉,大公司一般會有很多的服務器,放在不同的地方,這樣呢,一來保證數據的安全性,二來保證用戶連接到的那臺服務器離自己最近,通信質量最好

集群的概念?

集群是一組相互獨立的通過網絡互聯的計算機,它們構成了一個組,並以單一系統的模式加以管理,一個客戶與集群相互作用時,集群像是一個獨立的服務器,集群配置是用於提高可用性和可縮放性

Redis集群分類

  • 軟件

    • 只有一臺主機,在這臺主機上安裝了許多個服務
  • 硬件

    • 存在於多臺主機,每臺電腦上都啟動了redis服務或多個服務器

配置機器1

創建?件9420.conf

port 9420
bind 192.168.1.189
daemonize yes # 守護進程
pidfile 9420.pid # 將運行後的進程ID寫到9420.pid文件中
cluster-enabled yes # 開啟集群
cluster-config-file 9420_node.conf # 集群節點的配置文件
cluster-node-timeout 15000 # 連接集群節點的超時時間
appendonly yes

創建文件9421.conf

port 9421
bind 192.168.1.189
daemonize yes
pidfile 9421.pid
cluster-enabled yes
cluster-config-file 9421_node.conf
cluster-node-timeout 15000
appendonly yes

創建文件9422.conf

port 9422
bind 192.168.1.189
daemonize yes
pidfile 9422.pid
cluster-enabled yes
cluster-config-file 9422_node.conf
cluster-node-timeout 15000
appendonly yes

使?配置?件啟動redis服務

redis-server 9420.conf
redis-server 9421.conf
redis-server 9422.conf

配置機器2

創建文件9423.conf

port 9423
bind 192.168.1.200
daemonize yes
pidfile 9423.pid
cluster-enabled yes
cluster-config-file 9423_node.conf
cluster-node-timeout 15000
appendonly yes

創建文件9424.conf

port 9424
bind 192.168.1.200
daemonize yes
pidfile 9424.pid
cluster-enabled yes
cluster-config-file 9424_node.conf
cluster-node-timeout 15000
appendonly yes

創建文件9425.conf

port 9425
bind 192.168.1.200
daemonize yes
pidfile 9425.pid
cluster-enabled yes
cluster-config-file 9425_node.conf
cluster-node-timeout 15000
appendonly yes

使?配置?件啟動redis服務

redis-server 9423.conf
redis-server 9424.conf
redis-server 9425.conf

創建集群

  • redis的安裝包中包含了redis-trib.rb,?於創建集群
  • 接下來的操作在192.168.1.189機器上進?
  • 將命令復制,這樣可以在任何?錄下調?此命令
sudo cp /usr/share/doc/redis-tools/examples/redis-trib.rb /usr/local/bin/
  • 安裝ruby環境,因為redis-trib.rb是?ruby開發的
sudo apt-get install ruby
  • 運?如下命令創建集群
redis-trib.rb create --replicas 1 192.168.1.189:9420 192.168.1.189:9421 192.168.1.189:9422 192.168.1.200:9423 192.168.1.200:9424 192.168.1.200:9425
# 可能會報錯,因為安裝的ruby不是最新的
gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
sudo gem install redis 通過 gem 安裝 redis 的相關依賴
# 然後重新執?指令

如何確定哪個服務器上寫數據:CRC16

redis集群在設計的時候,就考慮到了去中心化,去中間件,也就是說,集群中的每個節點都是平等的,每個節點都保存各自的數據和整個集群的狀態,每個節點都和其他所有節點相連接,而且這些連接處於活躍狀態,這樣保證我們獲取到其他節點的數據,redis采用一種叫哈希槽的方式來分配數據,redis集群默認分為16384的槽,當我們設計一個key時,會用一種名叫CRC16的算法來取模得到所屬的槽,然後將key分到這個槽的節點上,redis集群會把數據放到master節點上,然後這個master和其對應的slave之間進行數據同步,當讀取數據時,也根據?致性哈希算法到對應的master節點獲取數據,只有當?個master掛掉之後,才會啟動?個對應的salve節點,充當 master

與Python交互

安裝包

pip install redis-py-cluster

栗子

from rediscluster import *
if __name__ == ‘__main__‘:
  try:
      # 構建所有的節點,Redis會使?CRC16算法,將鍵和值寫到某個節點上
      startup_nodes = [
          {‘host‘: ‘192.168.1.189‘, ‘port‘: ‘9420‘},
          {‘host‘: ‘192.168.1.189‘, ‘port‘: ‘9421‘},
          {‘host‘: ‘192.168.1.189‘, ‘port‘: ‘9422‘},
      ]
      # 構建StrictRedisCluster對象
      src=StrictRedisCluster(startup_nodes=startup_nodes,decode_responses=True)
      # 設置鍵為name、值為itheima的數據
      result=src.set(‘name‘,‘kernel‘)
      print(result)
      # 獲取鍵為name
      name = src.get(‘name‘)
      print(name)
  except Exception as e:
      print(e)

參考資料

  • redis集群搭建<http://www.cnblogs.com/wuxl360/p/5920330.html>
  • [Python]搭建redis集群<http://blog.5ibc.net/p/51020.html>

Python全棧開發之Redis