Python操作三大數(shù)據(jù)庫 - Redis數(shù)據(jù)庫

1. Redis數(shù)據(jù)庫介紹

1.1 介紹

  1. 了解NoSQL數(shù)據(jù)庫
    為什么要拋棄關系型數(shù)據(jù)庫绊谭?
    為什么NoSQL數(shù)據(jù)庫的讀寫速度遠超MySQL
    有哪些常用的NoSQL數(shù)據(jù)庫?
  2. 安裝Redis數(shù)據(jù)庫
    安裝Redis數(shù)據(jù)庫
    安裝Redis Desktop Manager客戶端
  3. Redis相關配置
    端口號汪拥、密碼达传、占用內(nèi)存大小、持久化方案等

1.2 Redis數(shù)據(jù)庫的安裝和配置

  1. 利用緩存優(yōu)化數(shù)據(jù)的讀寫
    應用程序 - 緩存 - 數(shù)據(jù)庫 - 硬盤
  2. 高速緩存的應用案例
    微博大V的微博數(shù)據(jù)被存放于高速緩存中迫筑,普通人的數(shù)據(jù)存放于普通NoSQL數(shù)據(jù)庫里宪赶。
    門戶網(wǎng)站、電商網(wǎng)站脯燃、視頻網(wǎng)站首頁的內(nèi)容都需要緩存逊朽。
    雙十一購物狂歡節(jié),訂單先被高速緩存曲伊,然后負載低谷期再寫入數(shù)據(jù)庫叽讳。
    電商平臺秒殺、搶購業(yè)務需要用高速緩存來實現(xiàn)順序操作坟募。
  3. Redis簡介
    Redis是美國VMware公司開源的NoSQL數(shù)據(jù)庫產(chǎn)品岛蚤,基于Key-Value存儲格式,可將數(shù)據(jù)保存在內(nèi)存或者硬盤中懈糯。
    可以將使用頻率高的熱數(shù)據(jù)放到Redis數(shù)據(jù)庫中涤妒,并保存到內(nèi)存中。
  4. Redis性能
    Redis是單線程模型的NoSQL數(shù)據(jù)庫赚哗,由C語言編寫她紫,官方提供的數(shù)據(jù)是可以達到100000+QPS(每秒內(nèi)查詢次數(shù))。
    image.png
  5. Redis安裝
    (1) 參考文檔
    (2) 安裝目錄
    /usr/local/redis-5.0.5
    (3) 啟動
# 直接啟動
?  ~ redis-server
# 使用配置啟動
?  ~ cd /usr/local/redis-5.0.7
?  redis-5.0.7 redis-server redis.conf  
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.7 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 8930
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'

注釋:日志在控制臺中輸出屿储。
(4) 退出
查看redispidps aux|grep redis
結(jié)束進程:kill -15 pid

  1. Redis命令行客戶端
?  ~ redis-cli
127.0.0.1:6379> select 0
OK
127.0.0.1:6379> set username scott
OK
127.0.0.1:6379> get username
"scott"
127.0.0.1:6379> del username
(integer) 1
127.0.0.1:6379> get username
(nil)
127.0.0.1:6379> 

Redis內(nèi)置了16個邏輯庫(0-15)贿讹,每個邏輯庫都是空的,可以通過select index選擇邏輯庫够掠。

  1. 安裝圖形客戶端
    RedisDesktopManager是目前最優(yōu)秀的Redis圖形客戶端工具民褂。
    image.png

    參考文檔:http://www.sohu.com/a/281755318_100264293
    注意:RedisDesktopManager是用來連接Redis(redis-cli),而不是啟動Redis(redis-server)疯潭。
  2. Redis的持久化
    為了防止意外宕機丟失數(shù)據(jù)赊堪,Redis提供了兩種持久化的方式。
    (1) RDB持久化
    在指定的時間間隔內(nèi)將內(nèi)存中的數(shù)據(jù)集快照寫入磁盤竖哩,實際操作過程是fork一個子進程哭廉,先將數(shù)據(jù)集寫入臨時文件,寫入成功后相叁,再替換之前的文件遵绰,用二進制壓縮存儲辽幌。
save 900 1 # 900秒內(nèi)寫入1次,則同步
save 300 10 # 300秒內(nèi)寫入10次街立,則同步
save 60 10000 # 60秒內(nèi)寫入10000次舶衬,則同步

(2) AOF持久化
以日志的形式記錄服務器所處理的每一個寫埠通、刪除操作赎离,查詢操作不會記錄,以文本的方式記錄端辱,可以打開文件看到詳細的操作記錄梁剔。

# appendfsync no  # 表示系統(tǒng)決定同步頻率
appendfsync everysec # 表示每秒同步一次
# appendfsync always # 表示每次修改數(shù)據(jù)都同步
  1. Redis配置參數(shù)(一)
序號 參數(shù) 作用
1 port 端口號,默認6379
2 bind 允許的IP舞蔽,默認只允許本機訪問
3 timeout client空閑多少秒后關閉連接荣病,默認0代表無限制。
4 loglevel 日志級別渗柿,分為:debug个盆、verbosenotice朵栖、warning颊亮,默認為notice
5 logfile 日志文件地址
6 syslog-enabled 將日志輸出到控制臺(yes),將日志輸出到日志文件(no)
  1. 修改配置
    (1) 修改
    /usr/local/redis-5.0.7/redis.conf
bind 0.0.0.0

timeout 300

logfile "logs.log"

syslog-enabled no

bind 127.0.0.1表示只有當前主機可以訪問當前Redis服務器陨溅。bind 0.0.0.0表示任何主機都能訪問當前Redis服務器终惑。
(2) 重啟Redis

?  ~ cd /usr/local/redis-5.0.7
?  redis-5.0.7 redis-server redis.conf  

此時在控制臺中不會輸出日志。而是生成/usr/local/redis-5.0.7/logs.log日志文件门扇。

image.png

  1. Redis配置參數(shù)(二)
序號 參數(shù) 作用
1 databases 邏輯庫的數(shù)量雹有,默認16
2 save RDB文件同步的頻率
3 rdbcompression 同步RDB文件的時候是否采用壓縮,默認yes
4 dbfilename rdb鏡像文件名稱臼寄,默認dump.rdb
5 dir rdb文件的目錄霸奕,默認./,為redis目錄
6 requirepass 訪問密碼吉拳,默認無需密碼
  1. 修改配置
    (1) 修改配置文件
databases 4

save 900 1
save 300 10
save 60 10000

requirepass abc123456

(2) 重啟Redis

?  ~ cd /usr/local/redis-5.0.7
?  redis-5.0.7 redis-server redis.conf 

(3) 使用RedisDesktopManager客戶端連接

image.png

  1. Redis配置參數(shù)(三)
序號 參數(shù) 作用
1 maxclients 最大連接數(shù)铅祸,默認無限制
2 maxmemory 占用內(nèi)存的大小,默認無限制
3 appendonly 開啟AOF備份
4 appendfilename AOF備份文件名
5 appendfsync AOF同步的頻率合武,分為no临梗、everysecalways

注釋:appendfsync值為no表示系統(tǒng)決定同步頻率稼跳,everysec表示每秒同步一次盟庞,always表示每次修改數(shù)據(jù)都同步。

  1. 修改配置
    (1) 修改配置文件
# save 900 1
# save 300 10
# save 60 10000

maxclients 2000

maxmemory 500m

appendonly yes

appendfilename "appendonly.aof"

appendfsync everysec

開啟AOF備份汤善,需要關閉RDB備份什猖。
(2) 重啟Redis

?  ~ cd /usr/local/redis-5.0.7
?  redis-5.0.7 redis-server redis.conf 

1.3 總結(jié)

  1. 技能清單
    學些了NoSQL數(shù)據(jù)庫的使用意義票彪。
    掌握了Redis數(shù)據(jù)庫的安裝方法。
    掌握了Redis客戶端的使用不狮。
    了解了Redis的常用配置降铸。

2. Redis常用數(shù)據(jù)結(jié)構(gòu)

2.1 介紹

  1. Redis的五種數(shù)據(jù)類型
    無條件查詢記錄,字段的計算和字段的別名
  2. RedisKey命令
    數(shù)據(jù)排序摇零、分頁推掸、去除重復記錄

2.2 Redis常用數(shù)據(jù)結(jié)構(gòu)

  1. Redis五種數(shù)據(jù)類型
    字符串、哈希驻仅、列表谅畅、集合、有序集合
  2. Redis字符串類型
    String類型既可以保存普通文字噪服,也可以保存序列化的二進制數(shù)據(jù)毡泻。
    String類型最大可以存儲512M數(shù)據(jù)。
  3. 字符串指令(一)
    (1) 設置Key-Value
    SET Key Value
    (2) 獲取Value
    GET Key
    (3) 刪除Key-Value
    DEL Key
    命令行客戶端示例如下:
?  ~ redis-cli -a "abc123456"
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
127.0.0.1:6379> SET email drew@163.com
OK
127.0.0.1:6379> GET email
"drew@163.com"
127.0.0.1:6379> DEl email
(integer) 1
127.0.0.1:6379> GET email
(nil)
127.0.0.1:6379> 

注釋:FLUSHDB清空當前邏輯庫粘优、FLUSHALL清空所有邏輯庫仇味。

  1. 字符串指令(二)
    (1) 獲取截取Value內(nèi)容
    GETRANGE Key 起始位置 結(jié)束位置
    (2) 獲取Value長度
    STRLEN Key
    (3) 設置帶有過期時間(秒)的Key-Value
    SETEX Key 時間數(shù)值 Value
Redis:0>set email drew@163.com
"OK"
Redis:0>getrange email 0 3
"drew"
Redis:0>getrange email 0 -1
"drew@163.com"
Redis:0>strlen email
"12"
Redis:0>setex username 5 drew
"OK"
Redis:0>get username
"drew"
Redis:0>get username
null
Redis:0>
  1. 字符串指令(三)
    (1) 設置多個Key-Value
    MSET Key1 Value1 Key2 Value2
    (2) 獲取多個Value
    MGET Key1 Key2
Redis:0>mset username jack sex male age 24
"OK"
Redis:0>mget username sex age 
 1)  "jack"
 2)  "male"
 3)  "24"
  1. 字符串指令(四)
    (1) 在Value結(jié)尾追加內(nèi)容
    APPEND Key 字符串
Redis:0>setex temp 60 ABCD
"OK"
Redis:0>get temp
"ABCD"
Redis:0>append temp 1234
"8"
Redis:0>get temp
"ABCD1234"
Redis:0>get temp
null
  1. 字符串指令(五)
    (1) Value自增1
    INCR Key
    (2) Value自增指定的整數(shù)值
    INCRBY Key 整數(shù)
    (3) Value自增指定的浮點數(shù)
    INCRBYFLOAT Key 浮點數(shù)
    (4) Value自減1
    DECR Key
    (5) Value自減指定的整數(shù)值
    DECRBY Key 整數(shù)
Redis:0>setex num 100 0
"OK"
Redis:0>incr num
"1"
Redis:0>get num
"1"
Redis:0>incrby num 20
"21"
Redis:0>get num
"21"
Redis:0>incrby num -2
"19"
Redis:0>get num
"19"
Redis:0>incrbyfloat num 2.56
"21.56"
Redis:0>get num
"21.56"
Redis:0>incrbyfloat num -4.6
"16.96"
Redis:0>get num
"16.96"

注意:并沒有DECRBYFLOAT自減指定的浮點數(shù)的方法。

  1. Redis哈希類型
    哈希類型可以保存更復雜的結(jié)構(gòu)化數(shù)據(jù)雹顺。
  2. 哈希指令(一)
    (1) 設置哈希表字段
    HSET Key k v
    (2) 設置哈希表多個字段
    HMSET Key k v k v
    (3) 獲取哈希表某個字段值
    HGET Key k
    (4) 獲取哈希表多個字段值
    HMGET Key k1 k2 k3
    (5) 獲取哈希表所有字段值
    HGETALL Key
    (6) 獲取哈希表中所有字段key
    HKEYS Key
    (7) 獲取哈希表中所有字段value
    HVALS Key
    (8) 獲取哈希表中字段數(shù)量
    HLEN Key
    (9) 判斷哈希表是否含有某個字段
    HEXISTS Key k1
    (10) 刪除哈希表的字段
    HDEL Key k1 k2
Redis:0>hset 8000 ename Tom
"1"
Redis:0>hset 8000 job SELESMAN
"1"
Redis:0>hmset 9000 ename Scott job SALESMAN deptno 10
"OK"
Redis:0>hget 9000 ename
"Scott"
Redis:0>hmget 9000 ename deptno job
 1)  "Scott"
 2)  "10"
 3)  "SALESMAN"
Redis:0>hgetall 9000
 1)  "ename"
 2)  "Scott"
 3)  "job"
 4)  "SALESMAN"
 5)  "deptno"
 6)  "10"
Redis:0>hkeys 9000
 1)  "ename"
 2)  "job"
 3)  "deptno"
Redis:0>hvals 9000
 1)  "Scott"
 2)  "SALESMAN"
 3)  "10"
Redis:0>hlen 9000
"3"
Redis:0>hexists 9000 job
"1"
Redis:0> hdel 9000 job deptno
"2"
Redis:0>hkeys 9000
 1)  "ename"
  1. 哈希指令(二)
    (1) 哈希表的某個字段加上指定的整數(shù)值
    HINCRBY Key k num
    (2) 哈希表的某個字段機上指定的浮點數(shù)
    HINCRBYFLOAT Key k float
Redis:0>hmset 8000 deptno 10 sal 4000
"OK"
Redis:0>hincrby 8000 deptno 5 
"15"
Redis:0>hincrbyfloat 8000 sal 500.5
"4500.5"
  1. Redis列表類型
    列表類型可以保存序列化數(shù)據(jù)丹墨。
    注釋:列表元素可以重復。
  2. 列表指令
    (1) 右側(cè)插入元素
    RPUSH Key 值1 值2 值3
    (2) 左側(cè)插入元素
    LPUSH Key 值1 值2
    (3) 設置列表指定位置的值
    LSET Key 位置 值
    (4) 截取子列表
    LRANGE Key 其實位置 結(jié)束位置
    (5) 獲取列表長度
    LLEN Key
    (6) 獲取指定位置元素
    LINDEX Key 位置
    (7) 指定元素前/后插入元素
    LINSERT Key before/after 指定元素 插入元素
    (8) 刪除第一個元素
    LPOP Key
    (9) 刪除最后一個元素
    RPOP Key
    (10) 刪除指定元素
    LREM Key 刪除數(shù)量(從左往右刪) 值
Redis:0>rpush dname 技術(shù)部 后勤部 售后部
"3"
Redis:0>lpush dname 秘書處
"4"
Redis:0>lset dname 2 銷售部 
"OK"
Redis:0>lrange dname 0 2
 1)  "秘書處"
 2)  "技術(shù)部"
 3)  "銷售部"
Redis:0>lrange dname 0 -1
 1)  "秘書處"
 2)  "技術(shù)部"
 3)  "銷售部"
 4)  "售后部"
Redis:0>llen dname
"4"
Redis:0>lindex dname 2
"銷售部"
Redis:0>linsert dname before 秘書處 董事會
"5"
Redis:0>lrange dname 0 -1
 1)  "董事會"
 2)  "秘書處"
 3)  "技術(shù)部"
 4)  "銷售部"
 5)  "售后部"
Redis:0>lpop dname
"董事會"
Redis:0>rpop dname
"售后部"
Redis:0>lrange dname 0 -1
 1)  "秘書處"
 2)  "技術(shù)部"
 3)  "銷售部"
Redis:0>rpush dname 技術(shù)部
"4"
Redis:0>lpush dname 技術(shù)部
"5"
Redis:0>lrange dname 0 -1
 1)  "技術(shù)部"
 2)  "秘書處"
 3)  "技術(shù)部"
 4)  "銷售部"
 5)  "技術(shù)部"
Redis:0>lrem dname 2 技術(shù)部
"2"
Redis:0>lrange dname 0 -1
 1)  "秘書處"
 2)  "銷售部"
 3)  "技術(shù)部"
  1. Redis集合類型
    可以將集合看做是元素不可以重復的列表无拗。
    注釋:集合不可以重復带到、沒有索引、根據(jù)哈希值排序英染。
  2. 集合指令
    (1) 集合添加元素
    SADD Key item1 item2 item3
    (2) 查看集合元素
    SMEMBERS Key
    (3) 獲取集合長度
    SCARD Key
    (4) 判斷是否含有某個元素
    SISMEMBER Key item
    (5) 刪除元素
    SREM Key item1 item2
    (6) 隨機刪除并返回集合的某個元素
    SPOP Key
    (7) 隨機返回集合中的元素
    SRANDMEMBER Key 數(shù)量
Redis:0>sadd empno 8001 8002 8003 8002
"3"
Redis:0>smembers empno
 1)  "8001"
 2)  "8002"
 3)  "8003"
Redis:0>scard empno
"3"
Redis:0> sismember empno 8002
"1"
Redis:0> srem empno 8001
"1"
Redis:0>smembers empno
 1)  "8002"
 2)  "8003"
Redis:0> del empno
"1"
Redis:0> sadd empno 3 5 1 2 9
"5"
Redis:0>srandmember empno 3
 1)  "5"
 2)  "9"
 3)  "3"
Redis:0>spop empno
"2"
Redis:0>spop empno
"9"
Redis:0>smembers empno
 1)  "1"
 2)  "3"
 3)  "5"
  1. Redis有序集合類型
    有序集合是帶有排序功能的集合(無重復值)揽惹,Redis會按照元素分數(shù)值排序弯菊。
  2. 有序集合指令
    (1) 添加元素
    ZADD Key 分數(shù)值 元素 分數(shù)值 元素
    (2) 提升元素的分數(shù)值
    ZINCRBY Key 分數(shù)值 元素
    (3) 獲取正序指定范圍元素
    ZRANGE Key 起始序號 結(jié)束序號
    (4) 獲取倒序指定范圍元素
    ZREVRANGE Key 起始序號 結(jié)束序號
    (5) 獲得有序集合長度
    ZCARD Key
    (6) 查詢某個分數(shù)值區(qū)間內(nèi)的元素數(shù)量
    ZCOUNT Key 最小分數(shù)值 最大分數(shù)值
    (7) 返回元素的分數(shù)值
    ZSCORE Key 元素
    (8) 獲取分數(shù)值區(qū)間內(nèi)的集合內(nèi)容(升序)
    ZRANGEBYSCORE Key 最小分數(shù)值 最大分數(shù)值
    其中谊却,(表示開區(qū)間,+inf表示正無窮递览,-inf表示負無窮闪金。
    (9) 獲取分數(shù)值區(qū)間內(nèi)的集合內(nèi)容(降序)
    ZREVRANGEBYSCORE Key 最大分數(shù)值 最小分數(shù)值
    (10) 獲取元素的升序排名(從0開始)
    ZRANK Key 元素
    (11) 獲取元素的降序排名(從0開始)
    ZREVRANK Key 元素
    (12) 刪除有序集合中的元素
    ZREM Key 元素1 元素2
    (13) 刪除排名區(qū)間內(nèi)的元素
    ZREMRANGEBYRANK Key 最小排名 最大排名
    (14) 刪除分數(shù)值區(qū)間內(nèi)的元素
    ZREMRANGEBYSCORE Key 最小分數(shù)值 最大分數(shù)值
    注意:字符串元素需要添加雙引號疯溺。-n序號表示倒數(shù)第n個。
Redis:0>zadd keyword 0 "鹿晗" 0 "馬云" 0 "張朝陽"
"3"
Redis:0>zrange keyword 0 1
 1)  "張朝陽"
 2)  "馬云"
Redis:0>zincrby keyword 1 "鹿晗"
"1"
Redis:0>zincrby keyword 5 "馬云"
"5"
Redis:0>zincrby keyword 2 "張朝陽" 
"2"
Redis:0>zrevrange keyword 0 -1
 1)  "馬云"
 2)  "張朝陽"
 3)  "鹿晗"
Redis:0>zrange keyword 0 1
 1)  "鹿晗"
 2)  "張朝陽"
Redis:0>zcard keyword
"3"
Redis:0>zcount keyword 2 5
"2"
Redis:0>zscore keyword "馬云"
"5"
Redis:0>zrangebyscore keyword 2 5
 1)  "張朝陽"
 2)  "馬云"
Redis:0>zrangebyscore keyword 2 (5
 1)  "張朝陽"
Redis:0>zrangebyscore keyword 2 +inf
 1)  "張朝陽"
 2)  "馬云"
Redis:0>zrevrangebyscore keyword 5 2
 1)  "馬云"
 2)  "張朝陽"
Redis:0>zrank keyword "馬云"
"2"
Redis:0>zrevrank keyword "馬云"
"0"
Redis:0>zadd keyword 9 "李彥宏"
"1"
Redis:0>zrem keyword "鹿晗"
"1"
Redis:0>zrevrange keyword 0 -1
 1)  "李彥宏"
 2)  "馬云"
 3)  "張朝陽"
Redis:0>zremrangebyrank keyword 0 1
"2"
Redis:0>zremrangebyscore keyword 9 9
"1"
Redis:0>zrevrange keyword 0 -1

Redis:0>zadd keyword 2 "張朝陽"  7 "李彥宏" 10 "馬云"
"3"
Redis:0>zremrangebyrank keyword 0 -3
"1"
Redis:0>zrevrange keyword 0 -1
 1)  "馬云"
 2)  "李彥宏"

2.3 Redis中常用命令

  1. Redis 命令參考
    https://class.imooc.com/lesson/943#mid=22498
  2. Redis中的Key命令
    (1) 刪除記錄
    DEL Key
    (2) 判斷是否存在某個Key
    EXISTS Key
    (3) 設置過期時間(秒)
    EXPIRE Key 秒值
    (4) 設置過期時間(毫秒)
    PEXPIRE Key 毫秒值
    (5) 設置過期時間(UNIX時間戳哎垦,單位為秒)
    EXPIREAT Key UNIX秒值
    (6) 設置過期時間(UNIX時間戳囱嫩,單位為毫秒)
    PEXPIREAT Key UNIX毫秒值
    (7) 移除過期時間
    PERSIST Key
    (8) 把記錄遷移到其他邏輯庫
    MOVE Key 新的邏輯庫
    (9) 修改Key名稱
    RENAME OldKey NewKey
    (10) 判斷值的數(shù)據(jù)類型
    TYPE Key
Redis:0>set name drew
"OK"
Redis:0>exists name
"1"
Redis:0>del name
"1"
Redis:0>exists name
"0"
Redis:0>set name drew
"OK"
Redis:0>expire name 5
"1"
Redis:0>get name
null
Redis:0>expireat name 15790764623 
"1"
Redis:0>move name 1
"1"
Redis:0>select 1
"OK"
Redis:1>get name
"drew"
Redis:1>rename name username
"OK"
Redis:1>get username
"drew"
Redis:1>sadd empno 8001 8002 8003 8002
"3"
Redis:1>type empno
"set"

2.4 總結(jié)

  1. 技能清單
    學習了Redis五種常用數(shù)據(jù)類型。
    掌握了操作Key的命令漏设。

3. Redis事務特性

3.1 介紹

  1. Redis事務機制
    Redis的事務機制的原理墨闲?
    Redis的事務具備具備ACID屬性嗎?
    Redis的事務能用來做什么郑口?
  2. 管理事務的命令
    WATCH鸳碧、UNWATCH盾鳞、MULTIEXEC瞻离、DISCARD

3.2 Redis事務特性

  1. 回顧MySQL數(shù)據(jù)庫事務機制
    數(shù)據(jù)庫引入事務機制是為了防止對數(shù)據(jù)文件進行直接操作的時候出現(xiàn)意外宕機腾仅,引發(fā)數(shù)據(jù)錯亂。
    undo日志記錄了數(shù)據(jù)修改之前的原始狀態(tài)套利,redo日志記錄了修改了哪些數(shù)據(jù)推励。
    undo日志和redo日志保證了業(yè)務操作的原子性。
  2. Redis數(shù)據(jù)庫事務機制
    Redis是異步單線程執(zhí)行日裙,一個線程對應所有客戶端吹艇。哪個客戶端上傳了命令惰蜜,線程就會執(zhí)行昂拂,并不能保證一個客戶端的多個命令不會被其他客戶端的命令插隊。
  3. Redis事務的特點
    Redis的事務和數(shù)據(jù)庫的事務有明顯差異抛猖,它并不滿足數(shù)據(jù)庫事務的ACID屬性格侯。 Redis的事務更像是批處理執(zhí)行。
序號 屬性 Redis MySQL
1 原子性 No Yes
2 一致性 Yes Yes
3 隔離性 Yes Yes
4 持久性 No Yes
  1. 監(jiān)控記錄
    為了保證事務的一致性财著,在開啟事務之前必須要使用WATCH命令監(jiān)視要操作的記錄联四。
    WATCH kill_num kill_user
  2. 開啟事務
MULTI
...
EXEC

開啟事務后所有操作都不會立即執(zhí)行,只有執(zhí)行EXEC命令的時候才會批處理執(zhí)行撑教。如果我們監(jiān)視的數(shù)據(jù)被其他客戶端修改了朝墩,那么我們開啟的事務就會自動關閉。

  1. 開啟事務后所有操作都不會立即執(zhí)行伟姐,只有執(zhí)行EXEC命令的時候才會批處理執(zhí)行收苏。
    控制臺1
Redis:0>set num 0
"OK"
Redis:0>watch num
"OK"
Redis:0>multi
"OK"
Redis:0>incr num 
"QUEUED"
Redis:0>incrby num 10
"QUEUED"

控制臺2

Redis:0>get num
"0"

控制臺1

Redis:0>exec
 1)  "1"
 2)  "11"

控制臺2

Redis:0>get num
"11"
  1. 如果我們監(jiān)視的數(shù)據(jù)被其他客戶端修改了,那么我們開啟的事務就會自動關閉愤兵。
    控制臺1
Redis:0>set num 0
"OK"
Redis:0>watch num
"OK"
Redis:0>multi
"OK"
Redis:0>incrby num 500
"QUEUED"

控制臺2

Redis:0>set num 50
"OK"
Redis:0>

控制臺1

Redis:0>exec

Redis:0>get num
"50"
  1. 取消事務
    Redis沒有事務的回滾機制鹿霸,并不能保證原子性。
    事務在沒有提交執(zhí)行(EXEC)前秆乳,是可以取消的懦鼠。如果事務已經(jīng)提交執(zhí)行(EXEC),就無法取消了屹堰。
    DISCARD
Redis:0>set num 0
"OK"
Redis:0>watch num
"OK"
Redis:0>multi
"OK"
Redis:0>set num 100
"QUEUED"
Redis:0>discard
"OK"
Redis:0>exec
"ERR EXEC without MULTI"
Redis:0>get num
"0"

3.3 總結(jié)

  1. 技能清單
    學習了Redis事務機制的原理
    掌握管理Redis事務的命令

4. Redis與Python交互

4.1 介紹

  1. 安裝redis-py模塊
    升級pip命令肛冶,用pip命令安裝redis-py模塊
  2. 掌握RedisCRUD操作
    redis-py模塊管理redis中的數(shù)據(jù),包括事務機制扯键。
  3. 編寫程序案例
    利用Python多線程睦袖,模擬電商秒殺活動的商品搶購,用Redis事務來避免超買和超賣忧陪。

4.2 Redis與Python的交互

1.redis-py模塊安裝
? ~ pip3 install redis

  1. redis-py創(chuàng)建連接
import redis

try:
    r = redis.Redis(
        host="localhost",
        port=6379,
        password="abc123456",
        db=0
    )
except Exception as e:
    print(e)

注意: 與MySQL不同扣泊,Redis沒有用戶管理近范。

  1. redis-py創(chuàng)建連接池
import redis

try:
    pool = redis.ConnectionPool(
        host="localhost",
        port=6379,
        password="abc123456",
        db=0,
        max_connections=200
    )
except Exception as e:
    print(e)
  1. redis-py創(chuàng)建與關閉連接
    從連接池中獲得的連接,不用關閉延蟹,垃圾回收的時候連接會自動被歸還到連接池评矩。
# 連接池文件代碼
import redis

try:
    pool = redis.ConnectionPool(
        host="localhost",
        port=6379,
        password="abc123456",
        db=0,
        max_connections=200
    )
except Exception as e:
    print(e)
# 連接文件代碼
import redis
from test.redis_db import pool

con = redis.Redis(
    connection_pool=pool
)
# ...
del con
  1. redis-py字符串指令(一)
    設置單個Key-Value
import time
import redis
from test.redis_db import pool

con = redis.Redis(
    connection_pool=pool
)

try:
    con.set("country", "英國")
    con.set("city", "倫敦")
    city = con.get("city").decode("utf-8")  # 倫敦
    print(city)  # 倫敦
    con.expire("city", 5)
    time.sleep(6)
    city = con.get("city")
    print(city)  # None
except Exception as e:
    print(e)
finally:
    del con

注意:中文需要使用decode("utf-8")解碼。

  1. redis-py字符串指令(二)
    設置多個Key-Value
import redis
from test.redis_db import pool

con = redis.Redis(
    connection_pool=pool
)

try:
    con.delete("country", "city")
    con.mset({"country": "德國", "city": "柏林"})
    result=con.mget("country", "city")
    print(result) # [b'\xe5\xbe\xb7\xe5\x9b\xbd', b'\xe6\x9f\x8f\xe6\x9e\x97']
    for one in result:
        print(one.decode("utf-8"))  # 德國 柏林
except Exception as e:
    print(e)
finally:
    del con

注釋:刪除redis字段con.delete("key1", "key2")阱飘。

  1. redis-py列表指令
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    con.rpush('dname', '董事會', '秘書處', '財務部', '技術(shù)部')
    con.lpop('dname')
    result = con.lrange('dname', 0, -1)
    for item in result:
        print(item.decode('utf-8'))
except Exception as e:
    print(e) # 秘書處 財務部 技術(shù)部
finally:
    del con
  1. redis-py集合指令
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    con.sadd('employee', 8001, 8002, 8003)
    con.srem('employee', 8002)
    result = con.smembers('employee')
    for one in result:
        print(one.decode('utf-8'))  # 8001 8003
    con.lpush("code", "Java", "PHP", "HTML", "Python")
    con.rpop("code")
    result = con.lrange("code", "0", "-1")
    for one in result:
        print(one.decode('utf-8'))  # Python HTML PHP
except Exception as e:
    print(e)
finally:
    del con
  1. redis-py有序集合指令
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    con.zadd('keyword', {'馬云': 0, '張朝陽': 0, "丁磊": 0})
    con.zincrby('keyword', 10, '馬云')
    result = con.zrevrange('keyword', 0, -1)
    for one in result:
        print(one.decode('utf-8'))  # 馬云 張朝陽 丁磊
except Exception as e:
    print(e)
finally:
    del con
  1. redis-py哈希指令
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    con.hmset('9527', {'name': 'Scott', 'sex': 'male', 'age': 35})
    con.hset('9527', 'city', '紐約')
    con.hdel('9527', 'sex')
    result = con.hexists('9527', 'name')
    print(result)  # True
    result = con.hgetall('9527')
    for key in result:
        print(key.decode('utf-8'), result.get(key).decode('utf-8'))
        # name Scott 
        # age 35
        # city 紐約
except Exception as e:
    print(e)
finally:
    del con
  1. redis-py的事務函數(shù)
    redis-py模塊用pipeline(管道)的方式向Redis服務器傳遞批處理命令和執(zhí)行事務斥杜。
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    pipeline = con.pipeline()
    pipeline.watch('9527')  # 監(jiān)視數(shù)據(jù)
    pipeline.multi()  # 開啟事務
    pipeline.hset('9527', 'name', 'Jack')
    pipeline.hset('9527', 'age', 23)
    pipeline.execute()  # 提交事務
except Exception as e:
    print(e)
finally:
    if 'pipeline' in dir():
        pipeline.reset()  # 只有重置pipeline,con對應的連接才會從連接池回收
    del con
  1. txt文檔中解析學生的信息沥匈,把語數(shù)外成績都超過85分的學生信息蔗喂,緩存到Redis哈希表中。
620,王偉,2-1,96,89,75
621,趙芳芳,2-1,71,62,80
622,許麗麗,2-2,96,88,89
624,胡倩倩,2-2,98,99,100
625,李偉,2-3,53,68,67
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    file = open(
        file="考試成績.txt",
        mode='r',
        encoding='utf-8'
    )
    data = file.read().splitlines()
    for item in data:
        temp = item.split(',')
        sid = temp[0]
        name = temp[1]
        class_no = temp[2]
        score_1 = int(temp[3])
        score_2 = int(temp[4])
        score_3 = int(temp[5])
        if score_1 >= 85 and score_2 >= 85 and score_3 >= 85:
            con.hmset(sid, {
                'name': name,
                'class_no': class_no,
                'score_1': score_1,
                'score_2': score_2,
                'score_3': score_3
            })
except Exception as e:
    print(e)
finally:
    if 'file' in dir():
        file.close()
    del con
  1. Python程序模擬300名觀眾高帖,為五位嘉賓(馬云缰儿、丁磊、張朝陽散址、馬化騰乖阵、李彥宏)隨機投票,最后按照降序排列結(jié)果预麸。
import random
from test.redis_db import pool
import redis

con = redis.Redis(
    connection_pool=pool
)

try:
    con.delete('ballot')
    con.zadd('ballot', {'馬云': 0, '丁磊': 0, '張朝陽': 0, '馬化騰': 0, '李彥宏': 0})
    names = ['馬云', '丁磊', '張朝陽', '馬化騰', '李彥宏']
    for i in range(0, 300):
        num = random.randint(0, 4)
        name = names[num]
        con.zincrby('ballot', 1, name)
    result = con.zrevrange('ballot', 0, -1, "WITHSCORES")  # 加上WITHSCORES瞪浸,表示獲得值和分數(shù)
    for item in result:
        print(item[0].decode('utf-8'), int(item[1]))
except Exception as e:
    print(e)
finally:
    del con
  1. Python線程池
    如果程序中經(jīng)常需要使用線程,頻繁的創(chuàng)建和銷毀線程會浪費很多硬件資源吏祸,所以需要把線程與任務分離開对蒲。線程池中的線程可以反復利用,省去了重復創(chuàng)建的麻煩贡翘。
import time
from concurrent.futures.thread import ThreadPoolExecutor

def say_hello():
    time.sleep(1)
    print('Hello')

executor = ThreadPoolExecutor(20)
for i in range(0, 10):
    executor.submit(say_hello)
  1. Python多線程模擬商品秒殺過程蹈矮,不可以出現(xiàn)超買和超賣的情況。假設A商品有10件參與秒殺活動床估,1000個用戶參與秒殺含滴,10分鐘秒殺自動結(jié)束。
from test.redis_db import pool
import redis
import random
from concurrent.futures.thread import ThreadPoolExecutor


# 生成1000個用戶id
s = set()
while True:
    if len(s) == 1000:
        break
    num = random.randint(10000, 100000)
    s.add(num)

# 創(chuàng)建連接
con = redis.Redis(
    connection_pool=pool
)
try:
    # 刪除相關數(shù)據(jù)
    con.delete('kill_total', 'kill_num', 'kill_flag', 'kill_user')
    # 初始化數(shù)據(jù)
    con.set('kill_total', 10)  # 一共10件秒殺商品
    con.set('kill_num', 0)  # 已秒殺幾件商品
    con.set('kill_flag', 1)  # 秒殺是否結(jié)束
    con.expire('kill_flag', 60 * 10)  # 10分鐘后描述結(jié)束
except Exception as e:
    print(e)
finally:
    del con

# 創(chuàng)建線程池
executor = ThreadPoolExecutor(200)

'''
kill_total 商品總數(shù)
kill_num 成功搶購數(shù)
kill_flag 有效標志位
kill_user 成功搶購的用戶ID
'''
def buy():
    connection = redis.Redis(
        connection_pool=pool
    )
    try:
        if connection.exists('kill_flag') == 1:
            pipeline = connection.pipeline()
            pipeline.watch('kill_num', 'kill_user')
            total = int(pipeline.get('kill_total').decode('utf-8'))
            num = int(pipeline.get('kill_num').decode('utf-8'))
            if num < total:
                pipeline.multi()
                pipeline.incr('kill_num')  # 已秒殺商品數(shù)加1
                user_id = s.pop()
                pipeline.rpush('kill_user', user_id)  # 保存秒殺到商品的用戶id
                pipeline.execute()
    except Exception as e:
        print(e)
    finally:
        if 'pipeline' in dir():
            pipeline.reset()
        del con


for i in range(0, 1000):
    executor.submit(buy)
print('秒殺已經(jīng)結(jié)束')

4.3 總結(jié)

  1. 技能清單
    掌握了redis-py模塊的連接池
    掌握了redis-py模塊的CRUD操作
    掌握了redis-py模塊的事務管理

5. 開發(fā)新聞管理系統(tǒng)

  1. 代碼地址
    https://github.com/nmwei/database-vega
  2. 技能清單
    完成了已審批新聞的緩存
    完成了刪除新聞丐巫,自動刪除redis緩存的功能
    完成了編輯新聞谈况,自動刪除redis緩存的功能
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市递胧,隨后出現(xiàn)的幾起案子碑韵,更是在濱河造成了極大的恐慌,老刑警劉巖缎脾,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祝闻,死亡現(xiàn)場離奇詭異,居然都是意外死亡遗菠,警方通過查閱死者的電腦和手機联喘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門华蜒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人豁遭,你說我怎么就攤上這事叭喜。” “怎么了蓖谢?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵捂蕴,是天一觀的道長。 經(jīng)常有香客問我闪幽,道長啥辨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任盯腌,我火速辦了婚禮溉知,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘腊嗡。我一直安慰自己着倾,他們只是感情好拾酝,可當我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布燕少。 她就那樣靜靜地躺著,像睡著了一般蒿囤。 火紅的嫁衣襯著肌膚如雪客们。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天材诽,我揣著相機與錄音底挫,去河邊找鬼。 笑死脸侥,一個胖子當著我的面吹牛建邓,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播睁枕,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼官边,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了外遇?” 一聲冷哼從身側(cè)響起注簿,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎跳仿,沒想到半個月后诡渴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡菲语,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年妄辩,在試婚紗的時候發(fā)現(xiàn)自己被綠了惑灵。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡眼耀,死狀恐怖泣棋,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情畔塔,我是刑警寧澤潭辈,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站澈吨,受9級特大地震影響把敢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜谅辣,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一修赞、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧桑阶,春花似錦柏副、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至萎河,卻和暖如春荔泳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背虐杯。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工玛歌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人擎椰。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓支子,卻偏偏與公主長得像,于是被迫代替她去往敵國和親达舒。 傳聞我的和親對象是個殘疾皇子值朋,可洞房花燭夜當晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 我知道我不伶俐也不討喜,知道自己偏執(zhí)休弃、固執(zhí)吞歼、死犟還牙尖嘴利∷可是篙骡,我知道了又能怎樣? 我知道自己有百般陋習,知道自...
    枝椏閱讀 367評論 0 2
  • # 一級標題 ## 二級標題 ### 三級標題 #### 四級標題 ##### 五級標題 ###### 六級標題
    wxh1000閱讀 142評論 0 3
  • 一部非常溫柔的荒島求生記杖玲,片中資源搶奪、各自為營淘正、部落斗爭等等的橋段都只是意思意思點到為止摆马,那塊神奇的隕石把一大群...
    蘊_Caroline閱讀 491評論 0 4
  • 公司開會,看到K鸿吆,比剛見到他的時候瘦了不少囤采。 我們同時去年進入公司的,在新員工培訓之后我們變成了無話不說的好友惩淳。期...
    愛笑的藍胖閱讀 795評論 9 4