日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

Python 操作 redis

發布時間:2024/7/23 python 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python 操作 redis 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

官網命令(英文)列表:http://redis.io/commands?

Redis 教程:http://www.redis.net.cn/tutorial/3501.html

Redis 命令參考:http://redisdoc.com/index.html

Windows 中 redis 的下載及安裝、設置:https://www.cnblogs.com/jylee/p/9844965.html

?

?

1、Redis-cli 命令總結

?

Redis 提供了豐富的命令(command)對數據庫和各種數據類型進行操作,這些 command 可以在 Linux 終端使用。在編程時,比如使用 Redis 的 python 包,這些命令都有對應的方法。下面將Redis提供的命令做一總結。

1、連接操作相關的命令quit:關閉連接(connection)auth:簡單密碼認證2、對value操作的命令exists(key): 確認一個key是否存在del(key): 刪除一個keytype(key): 返回值的類型keys(pattern):返回滿足給定pattern的所有keyrandomkey: 隨機返回key空間的一個keyrename(oldname, newname):將key由oldname重命名為newname,若newname存在則刪除newname表示的keydbsize: 返回當前數據庫中key的數目expire: 設定一個key的活動時間(s)ttl: 獲得一個key的活動時間select(index): 按索引查詢move(key, dbindex):將當前數據庫中的key轉移到有dbindex索引的數據庫flushdb: 刪除當前選擇數據庫中的所有keyflushall: 刪除所有數據庫中的所有key3、對String操作的命令set(key, value): 給數據庫中名稱為key的string賦予值valueget(key): 返回數據庫中名稱為key的string的valuegetset(key, value):給名稱為key的string賦予上一次的valuemget(key1, key2,…, key N): 返回庫中多個string(它們的名稱為key1,key2…)的valuesetnx(key, value): 如果不存在名稱為key的string,則向庫中添加string,名稱為key,值為valuesetex(key, time, value): 向庫中添加string(名稱為key,值為value)同時,設定過期時間timemset(key1, value1, key2, value2,…key N, value N): 同時給多個string賦值,名稱為key i的string賦值value imsetnx(key1, value1, key2, value2,…key N, value N):如果所有名稱為key i的string都不存在,則向庫中添加string,名稱key i賦值為value iincr(key):名稱為key的string增1操作incrby(key, integer):名稱為key的string增加integerdecr(key):名稱為key的string減1操作decrby(key, integer):名稱為key的string減少integerappend(key, value):名稱為key的string的值附加valuesubstr(key, start, end):返回名稱為key的string的value的子串4、對List操作的命令rpush(key, value):在名稱為key的list尾添加一個值為value的元素lpush(key, value):在名稱為key的list頭添加一個值為value的 元素llen(key):返回名稱為key的list的長度lrange(key, start, end):返回名稱為key的list中start至end之間的元素(下標從0開始,下同)ltrim(key, start, end):截取名稱為key的list,保留start至end之間的元素lindex(key, index):返回名稱為key的list中index位置的元素lset(key, index, value):給名稱為key的list中index位置的元素賦值為valuelrem(key, count, value):刪除count個名稱為key的list中值為value的元素。count為0,刪除所有值為value的元素,count>0從頭至尾刪除count個值為value的元素,count<0從尾到頭刪除|count|個值為value的元素。 lpop(key):返回并刪除名稱為key的list中的首元素 rpop(key):返回并刪除名稱為key的list中的尾元素 blpop(key1, key2,… key N, timeout):lpop命令的block版本。即當timeout為0時,若遇到名稱為key i的list不存在或該list為空,則命令結束。如果timeout>0,則遇到上述情況時,等待timeout秒,如果問題沒有解決,則對keyi+1開始的list執行pop操作。brpop(key1, key2,… key N, timeout):rpop的block版本。參考上一命令。rpoplpush(srckey, dstkey):返回并刪除名稱為srckey的list的尾元素,并將該元素添加到名稱為dstkey的list的頭部5、對Set操作的命令sadd(key, member):向名稱為key的set中添加元素membersrem(key, member) :刪除名稱為key的set中的元素memberspop(key) :隨機返回并刪除名稱為key的set中一個元素smove(srckey, dstkey, member) :將member元素從名稱為srckey的集合移到名稱為dstkey的集合scard(key) :返回名稱為key的set的基數sismember(key, member) :測試member是否是名稱為key的set的元素sinter(key1, key2,…key N) :求交集sinterstore(dstkey, key1, key2,…key N) :求交集并將交集保存到dstkey的集合sunion(key1, key2,…key N) :求并集sunionstore(dstkey, key1, key2,…key N) :求并集并將并集保存到dstkey的集合sdiff(key1, key2,…key N) :求差集sdiffstore(dstkey, key1, key2,…key N) :求差集并將差集保存到dstkey的集合smembers(key) :返回名稱為key的set的所有元素srandmember(key) :隨機返回名稱為key的set的一個元素6、對zset(sorted set)操作的命令zadd(key, score, member):向名稱為key的zset中添加元素member,score用于排序。如該元素已存在,則根據score更新該元素的順序。zrem(key, member) :刪除名稱為key的zset中的元素memberzincrby(key, increment, member) :如果在名稱為key的zset中已經存在元素member,則該元素的score增加increment;否則向集合中添加該元素,其score的值為incrementzrank(key, member) :返回名稱為key的zset(元素已按score從小到大排序)中member元素的rank(即index,從0開始),若沒有member元素,返回“nil”zrevrank(key, member) :返回名稱為key的zset(元素已按score從大到小排序)中member元素的rank(即index,從0開始),若沒有member元素,返回“nil”zrange(key, start, end):返回名稱為key的zset(元素已按score從小到大排序)中的index從start到end的所有元素zrevrange(key, start, end):返回名稱為key的zset(元素已按score從大到小排序)中的index從start到end的所有元素zrangebyscore(key, min, max):返回名稱為key的zset中score >= min且score <= max的所有元素 zcard(key):返回名稱為key的zset的基數 zscore(key, element):返回名稱為key的zset中元素element的score zremrangebyrank(key, min, max):刪除名稱為key的zset中rank >= min且rank <= max的所有元素 zremrangebyscore(key, min, max) :刪除名稱為key的zset中score >= min且score <= max的所有元素zunionstore / zinterstore(dstkeyN, key1,…,keyN, WEIGHTS w1,…wN, AGGREGATE SUM|MIN|MAX):對N個zset求并集和交集,并將最后的集合保存在dstkeyN中。對于集合中每一個元素的score,在進行AGGREGATE運算前,都要乘以對于的WEIGHT參數。如果沒有提供WEIGHT,默認為1。默認的AGGREGATE是SUM,即結果集合中元素的score是所有集合對應元素進行SUM運算的值,而MIN和MAX是指,結果集合中元素的score是所有集合對應元素中最小值和最大值。7、對Hash操作的命令hset(key, field, value):向名稱為key的hash中添加元素field<—>valuehget(key, field):返回名稱為key的hash中field對應的valuehmget(key, field1, …,field N):返回名稱為key的hash中field i對應的valuehmset(key, field1, value1,…,field N, value N):向名稱為key的hash中添加元素field i<—>value ihincrby(key, field, integer):將名稱為key的hash中field的value增加integerhexists(key, field):名稱為key的hash中是否存在鍵為field的域hdel(key, field):刪除名稱為key的hash中鍵為field的域hlen(key):返回名稱為key的hash中元素個數hkeys(key):返回名稱為key的hash中所有鍵hvals(key):返回名稱為key的hash中所有鍵對應的valuehgetall(key):返回名稱為key的hash中所有的鍵(field)及其對應的value8、持久化save:將數據同步保存到磁盤bgsave:將數據異步保存到磁盤lastsave:返回上次成功將數據保存到磁盤的Unix時戳shundown:將數據同步保存到磁盤,然后關閉服務9、遠程服務控制info:提供服務器的信息和統計monitor:實時轉儲收到的請求slaveof:改變復制策略設置config:在運行時配置Redis服務器

?

2、安裝

?

sudo apt-get install redis-server python 支持包: (其實就一個文件,搞過來就能用) sudo apt-get install python-redis

?

3、配置

?

配置一下吧,默認配置文件在: “/etc/redis/redis.conf” 綁定ip: “bind 127.0.0.1″ -> “bind 10.0.1.7″將磁盤同步改為 不同步或每秒同步,一直同步的話太慢了: “appendfsync always” -> “appendfsync no”檢查一下后臺執行是否打開: “daemonize yes”或者其他你想設置的,例如: 連接超時時間 : “timeout 300″ 運行級別: “loglevel notice” (個人認為默認的這個就挺好,非出現大異常,不用改為debug )

?

4、Python 操作 Redis 示例

?

redis-py 提供兩個類 Redis StrictRedis 用于實現 Redis 的命令。

  • StrictRedis 用于實現大部分官方的命令,并使用官方的語法和命令(比如,SET命令對應與StrictRedis.set方法)。
    ? ? 官方推薦使用 StrictRedis 方法。?
  • Redis StrictRedis 的子類,用于向后兼容舊版本的 redis-py。
    不推薦 Redis類,原因是它在 redis-cli 操作有些不一樣,主要不一樣是下面這三個方面。?
    • LREM:參數 ‘num’ 和 ‘value’ 的順序交換了一下,cli 是 lrem queueName 0 ‘string’ 。? 這里的0時所有的意思。 但是Redis這個類,把控制和string調換了。?
    • ZADD:實現時 score 和 value 的順序不小心弄反了,后來有人用了,就這樣了
    • SETEX:time 和 value 的順序反了
#! /usr/bin/env python #coding=utf-8 import redis print redis.__file__r = redis.Redis(host='10.0.1.7', port=6379, db=1) # 連接,可選不同數據庫,這里選擇 db=1# ----------------------------------------------------------------- info = r.info() # 看信息 for key in info:print "%s: %s" % (key, info[key])print '\ndbsize: %s' % r.dbsize() # 查數據庫大小 print "ping %s" % r.ping() # 看連接 # r.select(2) # 選數據庫 # r.move('a',2) # 移動數據去2數據庫# 其他 # r.save('a') # 存數據 # r.lastsave('a') # 取最后一次save時間 # r.flush() # 刷新 # r.shutdown() # 關閉所有客戶端,停掉所有服務,退出服務器# ----------------------------------------------------------------- # 它有四種類型: string(key,value)、list(序列)、set(集合)、zset(有序集合,多了一個順序屬性) # 不知道你用的哪種類型? # print r.get_type('a') #可以告訴你 # -----------------------------------------------------------------# --------------------------- string操作 --------------------------- print '-' * 20 r['c1'] = 'bar' # 塞數據 # 或者 r.set('c2','bar') # 塞數據print 'getset:', r.getset('c2','jj') # 這里有個 getset屬性,如果為True 可以在存新數據時將上次存儲內容同時搞出來 print 'incr:', r.incr('a') # 設置一個遞增的整數 每執行一次它自加1: print 'decr:', r.decr('a') # 設置一個遞減的整數print 'r['']:', r['c1'] # 取數據 # 或者 print 'get:', r.get('a') # 取數據 # 或者 print 'mget:', r.mget('c1','c2') # 同時取一批 # 或者 print 'keys:', r.keys('c*') # 同時取一批 它們的名字(key)很像 而恰好你又不想輸全部# 或者 print 'randomkey:', r.randomkey() # 隨機取一個:print 'existes:', r.exists('a') # 查看一個數據有沒有 有是1, 沒有是0 print 'delete:', r.delete('cc') # 刪數據 1是刪除成功 0和None是沒這個東西# ----------------------------批量操作---------------------------- print 'delete:', r.delete('c1','c2')# 其他 r.rename('a','c3') # 改名 r.expire('c3',10) # 讓數據10秒后過期 說實話我不太明白么意思 r.ttl('c3') # 看剩余過期時間 不存在返回-1# ---------------------------- 序列(list)操作:它是兩頭通的 ---------------------------- print '-'*20 r.push('b','gg') # 塞入 r.push('b','hh') # 塞入 r.push('b','ee',head=True) # head 屬性控制是不是從另一頭塞 print 'list len:', r.llen('b') # 看長度 print 'list lrange:', r.lrange('b',start=0,end=-1) # 列出一批出來 print 'list index 0:', r.lindex('b',0) # 取出一位# 修剪列表 # 若start 大于end, 則將這個list清空 print 'list ltrim :', r.ltrim('b',start=0,end=3) # 只留 從0到3四位# -------------------------------- 集合(set)操作 -------------------------------- r.sadd('s', 'a') # 塞數據 r.scard('s') # 判斷一個set長度為多少, 即獲取集合的成員數。不存在為0 r.sismember('s','a') # 判斷set中一個對象是否存在 r.sadd('s2','a') r.sinter('s1','s2') # 求交集 r.sinterstore('s3','s1','s2') # 求交集并將結果賦值 r.smembers('s3') # 看一個set對象 r.sunion('s1','s2') # 求并集 r.sunionstore('ss','s1','s2','s3') # 求并集 并將結果返回 r.sdiff('s1','s2','s3') # 在s1中有,但在s2和s3中都沒有的數 r.sdiffstore('s4','s1','s2') # 這個你懂的 r.srandmember('s1') # 取個隨機數# -------------------------------- 有序集合(zset)操作 -------------------------------- #'zadd', 'zcard', 'zincr', 'zrange', 'zrangebyscore', 'zrem', 'zscore' # 分別對應:添加, 數量, 自加1, 取數據, 按照積分(范圍)取數據, 刪除, 取積分

?

?

5、使用 Python 操作 Redis

?

1. 安裝 pyredis

首先安裝pip

<SHELL># apt-get install python-pip
......
<SHELL># pip install --proxy=http://172.1.2.6:8080 redis
? Downloading redis-2.9.1.tar.gz (62kB): 62kB downloaded
? Running setup.py (path:/tmp/pip_build_root/redis/setup.py) egg_info for package redis
? ......
? Successfully installed redis
? Cleaning up...

也可以使用easy_install的方式來安裝:easy_install redis

或者直接編譯安裝:

? ? ? ? wget https://pypi.python.org/packages/source/r/redis/redis-2.9.1.tar.gz
? ? ? ? tar xvzf redis-2.9.1.tar.gz
? ? ? ? cd redis-2.9.1
? ? ? ? python setup.py install

?

2 . 簡單的 redis 操作

redis 連接實例是線程安全的,可以直接將 redis 連接實例設置為一個全局變量,直接使用。如果需要另一個Redis實例(or Redis數據庫)時,就需要重新創建redis連接實例來獲取一個新的連接。同理,python 的 redis 沒有實現 select 命令。

>>> import redis >>> r = redis.Redis(host='localhost',port=6379,db=0) >>> r.set('guo','shuai') True >>> r.get('guo') 'shuai' >>> r['guo'] 'shuai' >>> r.keys() ['guo'] >>> r.dbsize() #當前數據庫包含多少條數據 1L >>> r.delete('guo') 1 >>> r.save() #執行“檢查點”操作,將數據寫回磁盤。保存時阻塞 True >>> r.get('guo'); >>> r.flushdb() #清空r中的所有數據 True

?

3. pipeline 操作

管道(pipeline)是redis在提供單個請求中緩沖多條服務器命令的基類的子類。它通過減少服務器-客戶端之間反復的TCP數據庫包,從而大大提高了執行批量命令的功能。

>>> p = r.pipeline() --創建一個管道 >>> p.set('hello','redis') >>> p.sadd('faz','baz') >>> p.incr('num') >>> p.execute() [True, 1, 1] >>> r.get('hello') 'redis'

管道的命令可以寫在一起,如:

>>> p.set('hello','redis').sadd('faz','baz').incr('num').execute()

默認的情況下,管道里執行的命令可以保證執行的原子性,執行pipe = r.pipeline(transaction=False)可以禁用這一特性。

?

Redis 連接池?

Redis 的連接池的方法:

pool = redis.ConnectionPool(host='localhost', port=6379, db=0) r = redis.Redis(connection_pool=pool)

?StrictRedis的連接池的實現方式:

pool = redis.ConnectionPool(host='127.0.0.1', port=6379) r = redis.StrictRedis(connection_pool=pool)

看下官方的創建redis的時候,都可以添加什么參數。?

class redis.StrictRedis(host='localhost', port=6379, db=0, password=None, socket_timeout=None, connection_pool=None, charset='utf-8', errors='strict', decode_responses=False, unix_socket_path=None )# Implementation of the Redis protocol. # This abstract class provides a Python interface to all Redis commands and an implementation of the Redis protocol. # Connection and Pipeline derive from this, implementing how the commands are sent and received to the Redis server

redis 的連接附加的參數里面,默認編碼是utf-8

?

Python Redis pipeline操作:https://www.cnblogs.com/kangoroo/p/7647052.html

?Pipeline:“管道”,和很多設計模式中的“管道”具有同樣的概念,pipleline的操作,將明確client與server端的交互,都是“單向的”:你可以將多個command,依次發給server,但在此期間,你將無法獲得單個command的響應數據,此后你可以關閉“請求”,然后依次獲取每個command的響應結果。
?

? ? 從簡單來說,在IO操作層面,對于client而言,就是一次批量的連續的“write”請求,然后是批量的連續的“read”操作。其實對于底層Socket-IO而言,對于client而言,只不過是多次write,然后一次read的操作;對于server端,input通道上read到數據之后,就會立即被實施,也會和非pipeline一樣在output通道上輸出執行的結果,只不過此時數據會被阻塞在網絡緩沖區上,直到client端開始read或者關閉鏈接。神秘的面紗已被解開,或許你也能創造一個pipeline的實現。

redis通過pipeline提升吞吐量:https://www.cnblogs.com/littleatp/p/8419796.html

非pipleline模式:
? ? client?? ? ? ? ? ? ? ? ? ?server

? ? Request? ? ---->? ? 執行
? ? ? ? ? ? ? ? ? ? ?<----? ? Response
? ? Request? ? ---->? ? 執行
? ? ? ? ? ? ? ? ? ? ?<----? ? Response

Pipeline模式下:
? ? client? ? ? ? ? ? ? ? ? ? server

? ? Request? ? ---->? ? 執行。Server將響應結果隊列化
? ? Request? ? ---->? ? 執行。Server將響應結果隊列化
? ? ? ? ? ? ? ? ? ? ?<----? ? Response
? ? ? ? ? ? ? ? ? ? ?<----? ? Response

?

? ? Client端根據Redis的數據協議,將響應結果進行解析,并將結果做類似于“隊列化”的操作。

?

從兩個圖的對比中可看出,普通的請求模型是同步的,每次請求對應一次IO操作等待;

而Pipeline 化之后所有的請求合并為一次IO,除了時延可以降低之外,還能大幅度提升系統吞吐量。

?

  • pipeline機制可以優化吞吐量,但無法提供原子性/事務保障,而這個可以通過Redis-Multi等命令實現。
    參考這里:https://redis.io/topics/transactions
  • 部分讀寫操作存在相關依賴,無法使用pipeline實現,可利用Script機制,但需要在可維護性方面做好取舍。

官方文檔-Redis-Pipelining
官方文檔-Redis-Transaction

?

?

?

pipeline 和“事務”是兩個完全不同的概念。pipeline只是表達“交互”中操作的傳遞的方向性,pipeline也可以在事務中運行,也可以不在。無論如何,pipeline中發送的每個command都會被server立即執行,如果執行失敗,將會在此后的相應中得到信息;也就是pipeline并不是表達“所有command都一起成功”的語義;但是如果pipeline的操作被封裝在事務中,那么將有事務來確保操作的成功與失敗(事實上,Redis的事務,仍然不像嚴格意義上的事務

pipeline 只是把多個redis指令一起發出去,redis并沒有保證這些指定的執行是原子的。
multi 相當于一個 redis 的 transaction 的,保證整個操作的原子性,避免由于中途出錯而導致最后產生的數據不一致。
pipeline 方式執行效率要比其他方式高。啟用 multi 寫入要比沒有開啟 multi 慢一點。

?Pipeline在某些場景下非常有用,比如有多個command需要被“及時的”提交,而且他們對相應結果沒有互相依賴,而且對結果響應也無需立即獲得,那么pipeline就可以充當這種“批處理”的工具;而且在一定程度上,可以較大的提升性能,性能提升的原因主要是TCP鏈接中較少了“交互往返”的時間。

pipeline 期間將“獨占”鏈接,此期間將不能進行非“管道”類型的其他操作,直到pipeline關閉;
如果你的pipeline的指令集很龐大,為了不干擾鏈接中的其他操作,你可以為pipeline操作新建Client鏈接,讓pipeline和其他正常操作分離在2個client中。不過pipeline事實上所能容忍的操作個數,和socket-output緩沖區大小/返回結果的數據尺寸都有很大的關系;同時也意味著每個redis-server同時所能支撐的pipeline鏈接的個數,也是有限的,這將受限于server的物理內存或網絡接口的緩沖能力。

?

Transaction(事務):
?

Redis 事務 以及 Python 操作示例 :http://www.cnblogs.com/kangoroo/p/7535405.html

? ? Redis提供了簡單的“事務”能力,MULTI,EXEC,DISCARD,WATCH/UNWATCH指令用來操作事務。

? ? 只有把 watch命令結合起來用,方可顯現出其具有事務的功能

  • ? ? MUTIL:開啟事務,此后所有的操作將會添加到當前鏈接的事務“操作隊列”中。
  • ? ? EXEC:提交事務
  • ? ? DISCARD:取消事務,記住,此指令不是嚴格意義上的“事務回滾”,只是表達了“事務操作被取消”的語義,將會導致事務的操作隊列中的操作不會被執行,且事務關閉。
  • ? ? WATCH/UNWATCH:“觀察”,這個操作也可以說是Redis的特殊功能,但是也可說是Redis不能提供“絕對意義上”的事務能力而增加的一個“補充特性”(比如事務隔離,多事務中操作沖突解決等);在事務開啟前,可以對某個KEY注冊“WATCH”,如果在事務提交后,將會首先檢測“WATCH”列表中的KEY集合是否被其他客戶端修改,如果任意一個KEY 被修改,都將會導致事務直接被“DISCARD”;即使事務中沒有操作某個WATCH KEY,如果此KEY被外部修改,仍然會導致事務取消。事務執行成功或者被DISCARD,都將會導致WATCH KEY被“UNWATCH”,因此事務之后,你需要重新WATCH。WATCH需要在事務開啟之前執行。
  • WATCH所注冊的KEY,事實上無論是被其他Client修改還是當前Client修改,如果不重新WATCH,都將無法在事務中正確執行。WATCH指令本身就是為事務而生,你或許不會在其他場景下使用WATCH

    Redis中,如果一個事務被提交,那么事務中的所有操作將會被順序執行,且在事務執行期間,其他client的操作將會被阻塞;Redis采取了這種簡單而“粗魯”的方式來確保事務的執行更加的快速和更少的外部干擾因素。

    EXEC指令將會觸發事務中所有的操作被寫入AOF文件(如果開啟了AOF),然后開始在內存中實施這些數據變更操作;Redis將會盡力確保事務中所有的操作都能夠執行,如果redis環境故障,有可能導致事務未能成功執行,那么需要在redis重啟后增加額外的校驗工作。

    ? ?如果在EXEC指令被提交之前,Redis-server即檢測到提交的某個指令存在語法錯誤,那么此事務將會被提前標記為DISCARD,此后事務提交也將直接被駁回;但是如果在EXEC提交后,在實施數據變更時(Redis將不會預檢測數據類型,比如你對一個“非數字”類型的key執行INCR操作),某個操作導致了ERROR,那么redis仍然不會回滾此前已經執行成功的操作,而且也不會中斷ERROR之后的其他操作繼續執行。對于開發者而言,你務必關注事務執行后返回的結果(結果將是一個集合,按照操作提交的順序排列,對于執行失敗的操作,結果將是一個ERROR)。

    ? ? Redis的事務之所以如此設計,它為了確保本身的性能,同時不引入“關系型數據庫”的設計復雜度

    ?

    ?

    總結:

    1. Multi :

      1.1. 每發送一條指令,都需要單獨發給服務器,服務器再單獨返回“該條指令已加入隊列”這個消息。這是比Pipeline慢的原因之一。
      1.2. Multi執行的時候會先暫停其他命令的執行,類似于加了個鎖,直到整個Multi結束完成再繼續其他客戶端的請求。這是Multi能保證一致性的原因,也是比Pipeline慢的原因之二。(需要讀Redis Server的代碼,從TCPDump上看不出)

    2. Pipeline :
      2.1. 將所有命令打包一次性發送。發送成功后,服務端不用返回類似“命令已收到”這樣的消息,而是一次性批量執行所有命令,成功后再一次性返回所有處理結果。
      2.2. 服務端處理命令的時候,不需要加鎖,而是與其他客戶端的命令混合在一起處理,所以無法保證一致性。

    適用場景 :
    1. 如果要順序執行一組命令(既網上所謂的“Redis事務”),Multi很合適。
    2. 如果要往Redis里批量插入Log, 或者使用Redis List做為隊列并插入很多消息的話,Pipleline是挺合適的。?

    ?

    示例代碼:

    #!/usr/bin/python3 # -*- coding: utf-8 -*- # @Author : # @File : test.py # @Software : PyCharm # @description : Redis 事務 和 鎖機制 import redis import time from redis import WatchError import multiprocessingREDIS_HOST = '127.0.0.1' REDIS_PORT = 6379 r_pool = redis.ConnectionPool(host=REDIS_HOST, port=REDIS_PORT) r = redis.StrictRedis(connection_pool=r_pool)def add_data():for v in range(100):r.zadd('set', v, v)def run(name):loop = Truewith r.pipeline() as pipe:while loop:try:pipe.zrevrange('set', -9999999999, 9999999999, withscores=True)[0]row_value_score = pipe.execute()[0][0] # <class 'tuple'>: (b'99', 99.0)value = row_value_score[0]pipe.watch('set')pipe.multi()results = pipe.zrem('set', value.decode('utf-8')).execute()pipe.unwatch() # 沒有發生異常時,刪除鎖if results[0]:# 刪除成功,繼續刪除 下一條數據print('{0} {1}'.format(name, results), end='')print(' value: {0}, score: {1}'.format(row_value_score[0], row_value_score[1]))else:# 刪除失敗(說明數據已經被別的進程刪除)。繼續刪除下一條數據print('{0} 刪除失敗,讀取數據 '.format(name), end='')print('{0} {1}'.format(name, results), end='')print(' value: {0}, score: {1}'.format(row_value_score[0], row_value_score[1]))except WatchError as watch_error:pipe.unwatch()print(watch_error, '{0} 釋放鎖,繼續下次循環'.format(name))except IndexError as index_error:loop = False# print(index_error)except BaseException as e:print(e)# print('hello', name)time.sleep(0.2)if __name__ == '__main__':add_data()process_nums = []for i in range(100): # 起 100 個進程p = multiprocessing.Process(target=run, args=('process_%s' % i,))process_nums.append(p)p.start()for i in range(len(process_nums)):process_nums[i].join()pass

    可以把 代碼中?time.sleep(0.2) 的代碼注釋掉看下效果(下面是有睡眠時間的運行結果):

    process_1 [1] value: b'99', score: 99.0 process_2 [1] value: b'98', score: 98.0 process_0 [1] value: b'97', score: 97.0 process_3 [1] value: b'96', score: 96.0 process_4 [1] value: b'95', score: 95.0 process_1 [1] value: b'94', score: 94.0 process_2 [1] value: b'93', score: 93.0 process_0 [1] value: b'92', score: 92.0 process_3 [1] value: b'91', score: 91.0 process_5 [1] value: b'90', score: 90.0 process_4 [1] value: b'89', score: 89.0 process_1 [1] value: b'88', score: 88.0 process_7 [1] value: b'87', score: 87.0 process_2 [1] value: b'86', score: 86.0 process_9 [1] value: b'85', score: 85.0 process_0 [1] value: b'84', score: 84.0 process_6 刪除失敗,讀取數據 process_6 [0] value: b'84', score: 84.0 process_3 [1] value: b'83', score: 83.0 process_5 [1] value: b'82', score: 82.0 process_4 [1] value: b'81', score: 81.0 process_8 [1] value: b'80', score: 80.0 process_1 [1] value: b'79', score: 79.0 process_7 [1] value: b'78', score: 78.0 process_2 [1] value: b'77', score: 77.0 Watched variable changed. process_9 釋放鎖,繼續下次循環 Watched variable changed. process_6 釋放鎖,繼續下次循環 Watched variable changed. process_0 釋放鎖,繼續下次循環 Watched variable changed. process_3 釋放鎖,繼續下次循環 Watched variable changed. process_5 釋放鎖,繼續下次循環 process_4 刪除失敗,讀取數據 process_4 [0] value: b'77', score: 77.0 process_8 [1] value: b'76', score: 76.0 process_10 [1] value: b'75', score: 75.0 Watched variable changed. process_11 釋放鎖,繼續下次循環 process_1 [1] value: b'74', score: 74.0 process_7 [1] value: b'73', score: 73.0 process_13 [1] value: b'72', score: 72.0 process_6 [1] value: b'71', score: 71.0 Watched variable changed. process_9 釋放鎖,繼續下次循環 Watched variable changed. process_0 釋放鎖,繼續下次循環 process_2 刪除失敗,讀取數據 process_2 [0] value: b'71', score: 71.0 process_5 [1] value: b'70', score: 70.0 process_3 刪除失敗,讀取數據 process_3 [0] value: b'70', score: 70.0 process_4 刪除失敗,讀取數據 process_4 [0] value: b'70', score: 70.0 process_8 刪除失敗,讀取數據 process_8 [0] value: b'70', score: 70.0 process_11 [1] value: b'69', score: 69.0 process_10 刪除失敗,讀取數據 process_10 [0] value: b'69', score: 69.0 process_1 [1] value: b'68', score: 68.0 process_7 [1] value: b'67', score: 67.0 process_12 [1] value: b'66', score: 66.0 process_15 [1] value: b'65', score: 65.0 process_13 [1] value: b'64', score: 64.0 process_6 [1] value: b'63', score: 63.0 process_9 [1] value: b'62', score: 62.0 process_0 刪除失敗,讀取數據 process_0 [0] value: b'62', score: 62.0 process_2 刪除失敗,讀取數據 process_2 [0] value: b'62', score: 62.0 process_5 刪除失敗,讀取數據 process_5 [0] value: b'62', score: 62.0 process_8 刪除失敗,讀取數據 process_8 [0] value: b'62', score: 62.0 process_4 [1] value: b'61', score: 61.0 Watched variable changed. process_3 釋放鎖,繼續下次循環 process_11 [1] value: b'60', score: 60.0 process_10 [1] value: b'59', score: 59.0 process_1 [1] value: b'58', score: 58.0 process_7 [1] value: b'57', score: 57.0 process_12 [1] value: b'56', score: 56.0 process_14 [1] value: b'55', score: 55.0 process_16 刪除失敗,讀取數據 process_16 [0] value: b'55', score: 55.0 process_15 [1] value: b'54', score: 54.0 process_13 [1] value: b'53', score: 53.0 process_6 [1] value: b'52', score: 52.0 process_9 [1] value: b'51', score: 51.0 process_8 [1] value: b'50', score: 50.0 Watched variable changed. process_3 釋放鎖,繼續下次循環 process_5 刪除失敗,讀取數據 process_5 [0] value: b'50', score: 50.0 Watched variable changed. process_4 釋放鎖,繼續下次循環 process_2 刪除失敗,讀取數據 process_2 [0] value: b'50', score: 50.0 process_0 刪除失敗,讀取數據 process_0 [0] value: b'50', score: 50.0 process_11 [1] value: b'49', score: 49.0 process_10 [1] value: b'48', score: 48.0 process_1 [1] value: b'47', score: 47.0 process_7 [1] value: b'46', score: 46.0 process_12 [1] value: b'45', score: 45.0 process_14 [1] value: b'44', score: 44.0 Watched variable changed. process_16 釋放鎖,繼續下次循環 process_15 [1] value: b'43', score: 43.0 process_22 [1] value: b'42', score: 42.0 process_13 [1] value: b'41', score: 41.0 process_6 [1] value: b'40', score: 40.0 process_9 [1] value: b'39', score: 39.0 process_0 刪除失敗,讀取數據 process_0 [0] value: b'39', score: 39.0 process_2 刪除失敗,讀取數據 process_2 [0] value: b'39', score: 39.0 process_4 [1] value: b'38', score: 38.0 Watched variable changed. process_5 釋放鎖,繼續下次循環 process_3 刪除失敗,讀取數據 process_3 [0] value: b'38', score: 38.0 process_8 刪除失敗,讀取數據 process_8 [0] value: b'38', score: 38.0 process_17 [1] value: b'37', score: 37.0 process_21 [1] value: b'36', score: 36.0 process_11 [1] value: b'35', score: 35.0 Watched variable changed. process_10 釋放鎖,繼續下次循環 process_1 [1] value: b'34', score: 34.0 process_7 [1] value: b'33', score: 33.0 process_12 [1] value: b'32', score: 32.0 process_14 [1] value: b'31', score: 31.0 process_16 刪除失敗,讀取數據 process_16 [0] value: b'31', score: 31.0 process_19 [1] value: b'30', score: 30.0 process_15 [1] value: b'29', score: 29.0 process_20 [1] value: b'28', score: 28.0 process_18 [1] value: b'27', score: 27.0 process_22 [1] value: b'26', score: 26.0 process_13 [1] value: b'25', score: 25.0 process_6 [1] value: b'24', score: 24.0 process_9 [1] value: b'23', score: 23.0 process_0 刪除失敗,讀取數據 process_0 [0] value: b'23', score: 23.0 process_2 [1] value: b'22', score: 22.0 process_4 刪除失敗,讀取數據 process_4 [0] value: b'22', score: 22.0 process_3 [1] value: b'21', score: 21.0 Watched variable changed. process_5 釋放鎖,繼續下次循環 process_8 [1] value: b'20', score: 20.0 process_21 [1] value: b'19', score: 19.0 process_10 [1] value: b'18', score: 18.0 Watched variable changed. process_11 釋放鎖,繼續下次循環 process_1 [1] value: b'17', score: 17.0 process_7 [1] value: b'16', score: 16.0 process_12 [1] value: b'15', score: 15.0 process_16 [1] value: b'13', score: 13.0 process_14 刪除失敗,讀取數據 process_14 [0] value: b'13', score: 13.0 process_17 [1] value: b'14', score: 14.0 process_19 [1] value: b'12', score: 12.0 process_15 [1] value: b'11', score: 11.0 process_23 [1] value: b'10', score: 10.0 process_20 [1] value: b'9', score: 9.0 process_18 [1] value: b'8', score: 8.0 process_22 [1] value: b'7', score: 7.0 process_13 [1] value: b'6', score: 6.0 process_6 [1] value: b'5', score: 5.0 process_9 [1] value: b'4', score: 4.0 process_0 [1] value: b'3', score: 3.0 process_2 [1] value: b'2', score: 2.0 process_5 [1] value: b'1', score: 1.0 process_3 [1] value: b'0', score: 0.0Process finished with exit code 0

    ?

    ?

    ?

    4. 應用場景 – 頁面點擊數

    《Redis Cookbook》對這個經典場景進行詳細描述。假定我們對一系列頁面需要記錄點擊次數。例如論壇的每個帖子都要記錄點擊次數,而點擊次數比回帖的次數的多得多。如果使用關系數據庫來存儲點擊,可能存在大量的行級鎖爭用。所以,點擊數的增加使用redis的INCR命令最好不過了。
    當redis服務器啟動時,可以從關系數據庫讀入點擊數的初始值(1237這個頁面被訪問了34634次)

    >>> r.set("visit:1237:totals",34634) True

    每當有一個頁面點擊,則使用INCR增加點擊數即可。

    >>> r.incr("visit:1237:totals") 34635 >>> r.incr("visit:1237:totals") 34636

    頁面載入的時候則可直接獲取這個值

    >>> r.get ("visit:1237:totals") '34636'

    ?

    5. 使用hash類型保存多樣化對象

    當有大量類型文檔的對象,文檔的內容都不一樣時,(即“表”沒有固定的列),可以使用hash來表達。

    >>> r.hset('users:jdoe', 'name', "John Doe") 1L >>> r.hset('users:jdoe', 'email', 'John@test.com') 1L >>> r.hset('users:jdoe', 'phone', '1555313940') 1L >>> r.hincrby('users:jdoe', 'visits', 1) 1L >>> r.hgetall('users:jdoe') {'phone': '1555313940', 'name': 'John Doe', 'visits': '1', 'email': 'John@test.com'} >>> r.hkeys('users:jdoe') ['name', 'email', 'phone', 'visits']

    6. 應用場景 – 社交圈子數據

    在社交網站中,每一個圈子(circle)都有自己的用戶群。通過圈子可以找到有共同特征(比如某一體育活動、游戲、電影等愛好者)的人。當一個用戶加入一個或幾個圈子后,系統可以向這個用戶推薦圈子中的人。
    我們定義這樣兩個圈子,并加入一些圈子成員。

    >>> r.sadd('circle:game:lol','user:debugo') 1 >>> r.sadd('circle:game:lol','user:leo') 1 >>> r.sadd('circle:game:lol','user:Guo') 1 >>> r.sadd('circle:soccer:InterMilan','user:Guo') 1 >>> r.sadd('circle:soccer:InterMilan','user:Levis') 1 >>> r.sadd('circle:soccer:InterMilan','user:leo') 1

    #獲得某一圈子的成員

    >>> r.smembers('circle:game:lol') set(['user:Guo', 'user:debugo', 'user:leo']) redis> smembers circle:jdoe:family

    可以使用集合運算來得到幾個圈子的共同成員:

    >>> r.sinter('circle:game:lol', 'circle:soccer:InterMilan') set(['user:Guo', 'user:leo']) >>> r.sunion('circle:game:lol', 'circle:soccer:InterMilan') set(['user:Levis', 'user:Guo', 'user:debugo', 'user:leo'])

    7. 應用場景 – 實時用戶統計

    Counting Online Users with Redis介紹了這個方法。當我們需要在頁面上顯示當前的在線用戶時,就可以使用Redis來完成了。首先獲得當前時間(以Unix timestamps方式)除以60,可以基于這個值創建一個key。然后添加用戶到這個集合中。當超過你設定的最大的超時時間,則將這個集合設為過期;而當需要查詢當前在線用戶的時候,則將最后N分鐘的集合交集在一起即可。由于redis連接對象是線程安全的,所以可以直接使用一個全局變量來表示。

    ?

    import time import redis from datetime import datetime ONLINE_LAST_MINUTES = 5 r = redis.Redis()def mark_online(user_id): #將一個用戶標記為onlinenow = int(time.time()) #當前的UNIX時間戳expires = now + (app.config['ONLINE_LAST_MINUTES'] * 60) + 10 #過期的UNIX時間戳all_users_key = 'online-users/%d' % (now // 60) #集合名,包含分鐘信息user_key = 'user-activity/%s' % user_id p = r.pipeline()p.sadd(all_users_key, user_id) #將用戶id插入到包含分鐘信息的集合中p.set(user_key, now) #記錄用戶的標記時間p.expireat(all_users_key, expires) #設定集合的過期時間為UNIX的時間戳p.expireat(user_key, expires)p.execute()def get_user_last_activity(user_id): #獲得用戶的最后活躍時間last_active = r.get('user-activity/%s' % user_id) #如果獲取不到,則返回Noneif last_active is None:return Nonereturn datetime.utcfromtimestamp(int(last_active))def get_online_users(): #獲得當前online用戶的列表current = int(time.time()) // 60 minutes = xrange(app.config['ONLINE_LAST_MINUTES'])return r.sunion(['online-users/%d' % (current - x) #取ONLINE_LAST_MINUTES分鐘對應集合的交集for x in minutes])

    ?

    redis基本命令和基本用法詳解

    1、redis連接

    redis-py 提供兩個類 Redis 和 StrictRedis 用于實現 Redis 的命令,StrictRedis 用于實現大部分官方的命令,并使用官方的語法和命令,Redis是StrictRedis的子類,用于向后兼容舊版本的redis-py。import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫r = redis.Redis(host='192.168.19.130', port=6379) host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r.set('foo', 'Bar') key是"foo" value是"bar" 將鍵值對存入redis緩存print r.get('foo') Bar 取出鍵foo對應的值

    ?

    ?

    ?

    2、連接池

    redis-py使用connection pool來管理對一個redis server的所有連接,避免每次建立、釋放連接的開銷。默認,每個Redis實例都會維護一個自己的連接池。可以直接建立一個連接池,然后作為參數Redis,這樣就可以實現多個Redis實例共享一個連接池import redis 通過python操作redis緩存pool = redis.ConnectionPool(host='192.168.19.130', port=6379) # host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379 r = redis.Redis(connection_pool=pool) r.set('foo', 'Bar') # key是"foo" value是"bar" 將鍵值對存入redis緩存 print r.get('foo') # Bar 取出鍵foo對應的值


    3、redis基本命令_string

    ?

    set(name, value, ex=None, px=None, nx=False, xx=False)在Redis中設置值,默認,不存在則創建,存在則修改 參數: ex,過期時間(秒) px,過期時間(毫秒) nx,如果設置為True,則只有name不存在時,當前set操作才執行 xx,如果設置為True,則只有name存在時,當前set操作才執行import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379)host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例1 ex,過期時間(秒) 這里過期時間是3秒,3秒后p,鍵foo的值就變成None r.set('foo', 'Bar',ex=3) key是"foo" value是"bar" 將鍵值對存入redis緩存 print r.get('foo') Bar 取出鍵foo對應的值2 px,過期時間(豪秒) 這里過期時間是3豪秒,3毫秒后,鍵foo的值就變成None r.set('foo', 'Bar',px=3) key是"foo" value是"bar" 將鍵值對存入redis緩存 print r.get('foo') Bar 取出鍵foo對應的值3 nx,如果設置為True,則只有name不存在時,當前set操作才執行 (新建) print(r.set('foo', 'Bar',nx=True)) None--已經存在 如果鍵foo已經存在,那么輸出是True;如果鍵foo不存在,輸出是None4 xx,如果設置為True,則只有name存在時,當前set操作才執行 (修改) print(r.set('foo1', 'Bar',xx=True)) True--已經存在 如果鍵foo已經存在,那么輸出是None;如果鍵foo不存在,輸出是True5 setnx(name, value) 設置值,只有name不存在時,執行設置操作(添加) print(r.setnx("foo2","bar")) False--已經存在的話,無法執行6 setex(name, value, time) 設置值 參數: time,過期時間(數字秒 或 timedelta對象) r.setex("foo","bar",5) print r.get('foo') 5秒后,取值就從bar變成None7 psetex(name, time_ms, value) 設置值 參數: time_ms,過期時間(數字毫秒 或 timedelta對象) r.psetex("foo",5000,"bar") print r.get('foo') 5000毫秒后,取值就從bar變成None8 mset(*args, **kwargs) 批量設置值 如: mset(k1='v1', k2='v2') 或 mget({'k1': 'v1', 'k2': 'v2'}) r.mset(k1="v1",k2="v2") 這里k1 和k2 不能帶引號 一次設置對個鍵值對 print r.mget("k1","k2") ['v1', 'v2'] 一次取出多個鍵對應的值 print r.mget("k1") ['v1']9 mget(keys, *args) 批量獲取 如: mget('ylr', 'wupeiqi') 或 r.mget(['ylr', 'wupeiqi']) print r.mget("foo","foo1","foo2","k1","k2") [None, 'Bar', 'bar', 'v1', 'v2'] 將目前redis緩存中的鍵對應的值批量取出來10 getset(name, value) 設置新值并獲取原來的值 print(r.getset("foo1","bar_NEW")) Bar 設置的新值是"bar_NEW" 設置前的值是Bar11 getrange(key, start, end) 獲取子序列(根據字節獲取,非字符) 參數: name,Redis 的 name start,起始位置(字節) end,結束位置(字節) 如: "武沛齊" ,0-3表示 "武" r.set("foo1","武沛齊") 漢字 print(r.getrange("foo1",0,2)) 取索引號是0-2 前3位的字節 武 切片操作 (一個漢字3個字節 1個字母一個字節 每個字節8bit) print(r.getrange("foo1",0,-1)) 取所有的字節 武沛齊 切片操作r.set("foo1","bar_new") 字母 print(r.getrange("foo1",0,2)) 取索引號是0-2 前3位的字節 bar 切片操作 (一個漢字3個字節 1個字母一個字節 每個字節8bit) print(r.getrange("foo1",0,-1)) 取所有的字節 bar_new 切片操作12 setrange(name, offset, value) 修改字符串內容,從指定字符串索引開始向后替換(新值太長時,則向后添加) 參數: offset,字符串的索引,字節(一個漢字三個字節) value,要設置的值 r.setrange("foo1",1,"aaa") print(r.get("foo1")) baaanew 原始值是bar_new 從索引號是1開始替換成aaa 變成 baaanew bar_new13 setbit(name, offset, value) 對name對應值的二進制表示的位進行操作 參數: name,redis的name offset,位的索引(將值變換成二進制后再進行索引) value,值只能是 1 或 0注:如果在Redis中有一個對應: n1 = "foo", 那么字符串foo的二進制表示為:01100110 01101111 01101111 所以,如果執行 setbit('n1', 7, 1),則就會將第7位設置為1, 那么最終二進制則變成 01100111 01101111 01101111,即:"goo"擴展,轉換二進制表示: source = "陳思維" source = "foo" for i in source: num = ord(i) print bin(num).replace('b','') 特別的,如果source是漢字 "陳思維"怎么辦? 答:對于utf-8,每一個漢字占 3 個字節,那么 "陳思維" 則有 9個字節 對于漢字,for循環時候會按照 字節 迭代,那么在迭代時,將每一個字節轉換 十進制數,然后再將十進制數轉換成二進制 11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 10010000 -------------------------- ----------------------------- ----------------------------- 陳思維13 應用場景 :統計uv 注:如果在Redis中有一個對應: n1 = "foo", 那么字符串foo的二進制表示為:01100110 01101111 01101111 所以,如果執行 setbit('n1', 7, 1),則就會將第7位設置為1, 那么最終二進制則變成 01100111 01101111 01101111,即:"goo" r.set("foo","foo1") foo1的二進制表示為:01100110 01101111 01101111 00110001 這里f對應的ascii值是102 折算二進制是 01100110 (64+32+4+2) 這里o對應的ascii值是111 折算二進制是 01101111 (64+32+8+4+2+1) 這里數字1對應的ascii值是49 折算二進制是 00110001 (32+16+1) r.setbit("foo",7,1) 將第7位設置為1, print(r.get("foo")) goo1 那么最終二進制則變成 01100111 01101111 01101111 00000001 print(ord("f")) 102 將字符f的ascii對應的值打印出來 print(ord("o")) 111 將字符o的ascii對應的值打印出來 print(chr(103)) g 將ascii數字103對應的字符打印出來 print(ord("1")) 49 將數字1的ascii對應的值打印出來擴展,轉換二進制表示: source = "陳思維" source = "foo1" for i in source: num = ord(i) print(num) 打印每個字母字符或者漢字字符對應的ascii碼值 f-102-0b100111-01100111 print(bin(num)) 打印每個10進制ascii碼值轉換成二進制的值 0b1100110(0b表示二進制) print bin(num).replace('b','') 將二進制0b1100110替換成01100110特別的,如果source是漢字 "陳思維"怎么辦? 答:對于utf-8,每一個漢字占 3 個字節,那么 "陳思維" 則有 9個字節 對于漢字,for循環時候會按照 字節 迭代,那么在迭代時,將每一個字節轉換 十進制數,然后再將十進制數轉換成二進制 11100110 10101101 10100110 11100110 10110010 10011011 11101001 10111101 1001000014 getbit(name, offset) 獲取name對應的值的二進制表示中的某位的值 (0或1) print(r.getbit("foo1",0)) 0 foo1對應的二進制 4個字節 32位 第0位是0還是115 bitcount(key, start=None, end=None) 獲取name對應的值的二進制表示中 1 的個數 參數: key,Redis的name start 字節起始位置 end,字節結束位置 print(r.get("foo")) goo1 01100111 print(r.bitcount("foo",0,1)) 11 表示前2個字節中,1出現的個數16 bitop(operation, dest, *keys) 獲取多個值,并將值做位運算,將最后的結果保存至新的name對應的值參數: operation,AND(并) 、 OR(或) 、 NOT(非) 、 XOR(異或) dest, 新的Redis的name *keys,要查找的Redis的name如: bitop("AND", 'new_name', 'n1', 'n2', 'n3') 獲取Redis中n1,n2,n3對應的值,然后講所有的值做位運算(求并集),然后將結果保存 new_name 對應的值中 r.set("foo","1") 0110001 r.set("foo1","2") 0110010 print(r.mget("foo","foo1")) ['goo1', 'baaanew'] print(r.bitop("AND","new","foo","foo1")) "new" 0 0110000 print(r.mget("foo","foo1","new"))source = "12" for i in source: num = ord(i) print(num) 打印每個字母字符或者漢字字符對應的ascii碼值 f-102-0b100111-01100111 print(bin(num)) 打印每個10進制ascii碼值轉換成二進制的值 0b1100110(0b表示二進制) print bin(num).replace('b','') 將二進制0b1100110替換成0110011017 strlen(name) 返回name對應值的字節長度(一個漢字3個字節) print(r.strlen("foo")) 4 'goo1'的長度是418 incr(self, name, amount=1) 自增 name對應的值,當name不存在時,則創建name=amount,否則,則自增。 參數: name,Redis的name amount,自增數(必須是整數) 注:同incrby r.set("foo",123) print r.mget("foo","foo1","foo2","k1","k2") ['123', '2', 'bar', 'v1', 'v2'] r.incr("foo",amount=1) print r.mget("foo","foo1","foo2","k1","k2") ['124', '2', 'bar', 'v1', 'v2']19 incrbyfloat(self, name, amount=1.0) 自增 name對應的值,當name不存在時,則創建name=amount,否則,則自增。 參數: name,Redis的name amount,自增數(浮點型) r.set("foo1","123.0") print r.mget("foo","foo1","foo2","k1","k2") ['124', '123.0', 'bar', 'v1', 'v2'] r.incrbyfloat("foo1",amount=2.0) r.incrbyfloat("foo3",amount=3.0) print r.mget("foo","foo1","foo2","foo3","k1","k2") ['124', '125', 'bar', '-3', 'v1', 'v2']20 decr(self, name, amount=1) 自減 name對應的值,當name不存在時,則創建name=amount,否則,則自減。 參數: name,Redis的name amount,自減數(整數) r.decr("foo4",amount=3) 遞減3 r.decr("foo1",amount=1) 遞減1 print r.mget("foo","foo1","foo2","foo3","foo4","k1","k2") ['goo1', '121', 'bar', '15', '-18', 'v1', 'v2']21 append(key, value) 在redis name對應的值后面追加內容 參數: key, redis的name value, 要追加的字符串 r.append("foo","abc") 在foo對應的值goo1后面追加字符串abc print r.mget("foo","foo1","foo2","foo3","foo4","k1","k2") ['goo1abc', '121', 'bar', '15', '-18', 'v1', 'v2']


    4 redis基本命令_hash

    ?

    import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379)host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例1 單個增加--修改(單個取出)--沒有就新增,有的話就修改 hset(name, key, value) name對應的hash中設置一個鍵值對(不存在,則創建;否則,修改) 參數: name,redis的name key,name對應的hash中的key value,name對應的hash中的value 注: hsetnx(name, key, value),當name對應的hash中不存在當前key時則創建(相當于添加) r.hset("foo_hash1","k1","v1") print(r.mget("foo","foo1","foo2","foo3","foo4","k1","k2")) ['goo1abcabc', '121', 'bar', '15', '-18', 'v1', 'v2'] 取字符串 print(r.hget("foo_hash1","k1")) v1 單個取hash的key print(r.hmget("foo_hash1","k1")) ['v1'] 批量取hash的keyr.hsetnx("foo_hash1","k2","v2") 只能新建 print(r.hget("foo_hash1","k2")) v2 print(r.hmget("foo_hash1","k2")) ['v2']2 批量增加(取出) hmset(name, mapping) 在name對應的hash中批量設置鍵值對 參數: name,redis的name mapping,字典,如:{'k1':'v1', 'k2': 'v2'} 如: r.hmset('xx', {'k1':'v1', 'k2': 'v2'}) r.hmset("foo_hash2",{"k2":"v2","k3":"v3"}) print(r.hget("foo_hash2","k2")) v2 單個取出"foo_hash2"的key-k2對應的value print(r.hmget("foo_hash2","k2","k3")) ['v2', 'v3'] 批量取出"foo_hash2"的key-k2 k3對應的value --方式1 print(r.hmget("foo_hash2",["k2","k3"])) ['v2', 'v3'] 批量取出"foo_hash2"的key-k2 k3對應的value --方式2hget(name,key) 在name對應的hash中獲取根據key獲取value hmget(name, keys, *args) 在name對應的hash中獲取多個key的值 參數: name,reids對應的name keys,要獲取key集合,如:['k1', 'k2', 'k3'] *args,要獲取的key,如:k1,k2,k3 如: r.hmget('xx', ['k1', 'k2']) 或 print r.hmget('xx', 'k1', 'k2')3 取出所有的鍵值對 hgetall(name) 獲取name對應hash的所有鍵值 print(r.hgetall("foo_hash1")) {'k2': 'v2', 'k1': 'v1'}4 得到所有鍵值對的格式 hash長度 hlen(name) 獲取name對應的hash中鍵值對的個數 print(r.hlen("foo_hash1")) 25 得到所有的keys(類似字典的取所有keys) hkeys(name) 獲取name對應的hash中所有的key的值 print(r.hkeys("foo_hash1")) ['k1', 'k2'] 取出所有的keys6 得到所有的value(類似字典的取所有value) hvals(name) 獲取name對應的hash中所有的value的值 print(r.hvals("foo_hash1")) ['v1', 'v2'] 取出所有的values7 判斷成員是否存在(類似字典的in) hexists(name, key) 檢查name對應的hash是否存在當前傳入的key print(r.hexists("foo_hash1","k3")) False 不存在 print(r.hexists("foo_hash1","k1")) True 存在8 刪除鍵值對 hdel(name,*keys) 將name對應的hash中指定key的鍵值對刪除 print(r.hgetall("foo_hash1")) {'k2': 'v2', 'k1': 'v1'} r.hset("foo_hash1","k2","v3") 修改已有的key k2 r.hset("foo_hash1","k1","v1") 新增鍵值對 k1 r.hdel("foo_hash1","k1") 刪除一個鍵值對 print(r.hgetall("foo_hash1")) {'k2': 'v3'}9 自增自減整數(將key對應的value--整數 自增1或者2,或者別的整數 負數就是自減) hincrby(name, key, amount=1) 自增name對應的hash中的指定key的值,不存在則創建key=amount 參數: name,redis中的name key, hash對應的key amount,自增數(整數) r.hset("foo_hash1","k3",123) r.hincrby("foo_hash1","k3",amount=-1) print(r.hgetall("foo_hash1")) {'k3': '122', 'k2': 'v3', 'k1': 'v1'} r.hincrby("foo_hash1","k4",amount=1) 不存在的話,value默認就是1 print(r.hgetall("foo_hash1")) {'k3': '122', 'k2': 'v3', 'k1': 'v1', 'k4': '4'}10 自增自減浮點數(將key對應的value--浮點數 自增1.0或者2.0,或者別的浮點數 負數就是自減) hincrbyfloat(name, key, amount=1.0) 自增name對應的hash中的指定key的值,不存在則創建key=amount 參數: name,redis中的name key, hash對應的key amount,自增數(浮點數) 自增name對應的hash中的指定key的值,不存在則創建key=amount r.hset("foo_hash1","k5","1.0") r.hincrbyfloat("foo_hash1","k5",amount=-1.0) 已經存在,遞減-1.0 print(r.hgetall("foo_hash1")) r.hincrbyfloat("foo_hash1","k6",amount=-1.0) 不存在,value初始值是-1.0 每次遞減1.0 print(r.hgetall("foo_hash1")) {'k3': '122', 'k2': 'v3', 'k1': 'v1', 'k6': '-6', 'k5': '0', 'k4': '4'}11 取值查看--分片讀取 hscan(name, cursor=0, match=None, count=None) 增量式迭代獲取,對于數據大的數據非常有用,hscan可以實現分片的獲取數據,并非一次性將數據全部獲取完,從而放置內存被撐爆 參數: name,redis的name cursor,游標(基于游標分批取獲取數據) match,匹配指定key,默認None 表示所有的key count,每次分片最少獲取個數,默認None表示采用Redis的默認分片個數 如: 第一次:cursor1, data1 = r.hscan('xx', cursor=0, match=None, count=None) 第二次:cursor2, data1 = r.hscan('xx', cursor=cursor1, match=None, count=None) ... 直到返回值cursor的值為0時,表示數據已經通過分片獲取完畢 print(r.hscan("foo_hash1")) (0L, {'k3': '122', 'k2': 'v3', 'k1': 'v1', 'k6': '-6', 'k5': '0', 'k4': '4'})12 hscan_iter(name, match=None, count=None) 利用yield封裝hscan創建生成器,實現分批去redis中獲取數據 參數: match,匹配指定key,默認None 表示所有的key count,每次分片最少獲取個數,默認None表示采用Redis的默認分片個數 如: for item in r.hscan_iter('xx'): print item print(r.hscan_iter("foo_hash1")) <generator object hscan_iter at 0x027B2C88> 生成器內存地址 for item in r.hscan_iter('foo_hash1'): print item ('k3', '122') ('k2', 'v3') ('k1', 'v1') ('k6', '-6') ('k5', '0') ('k4', '4')


    5 redis基本命令_list

    ?

    import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379)host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例1 增加(類似于list的append,只是這里是從左邊新增加)--沒有就新建 lpush(name,values) 在name對應的list中添加元素,每個新的元素都添加到列表的最左邊 如: r.lpush('oo', 11,22,33) 保存順序為: 33,22,11 擴展: rpush(name, values) 表示從右向左操作 r.lpush("foo_list1",11,22) 從列表的左邊,先添加11,后添加22 print(r.lrange("foo_list1",0,20)) ['22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11'] 切片取出值,范圍是索引號0-20 print(r.llen("foo_list1")) 18 長度是182 增加(從右邊增加)--沒有就新建 r.rpush("foo_list1",2,3,4) 在列表的右邊,依次添加2,3,4 print(r.lrange("foo_list1",0,-1)) ['22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '2', '3', '4'] 切片取出值,范圍是索引號0-最后一個元素 print(r.llen("foo_list1")) 21 列表長度是213 往已經有的name的列表的左邊添加元素,沒有的話無法創建 lpushx(name,value) 在name對應的list中添加元素,只有name已經存在時,值添加到列表的最左邊 更多: rpushx(name, value) 表示從右向左操作 r.lpushx("foo_list2",1) 這里"foo_list2"不存在 print(r.lrange("foo_list2",0,-1)) [] print(r.llen("foo_list2")) 0r.lpushx("foo_list1",1) 這里"foo_list1"之前已經存在,往列表最左邊添加一個元素,一次只能添加一個 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['1', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '2', '3', '4'] print(r.llen("foo_list1")) 22 列表長度是224 往已經有的name的列表的右邊添加元素,沒有的話無法創建 r.rpushx("foo_list1",1) 這里"foo_list1"之前已經存在,往列表最右邊添加一個元素,一次只能添加一個 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['1', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '2', '3', '4','1'] print(r.llen("foo_list1")) 23 列表長度是235 新增(固定索引號位置插入元素) linsert(name, where, refvalue, value)) 在name對應的列表的某一個值前或后插入一個新值 參數: name,redis的name where,BEFORE或AFTER refvalue,標桿值,即:在它前后插入數據 value,要插入的數據 r.linsert("foo_list1","before","22","33") 往列表中左邊第一個出現的元素"22"前插入元素"33" print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['1', '33', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '2', '3', '4', '1'] print(r.llen("foo_list1")) 24 列表長度是246 修改(指定索引號進行修改) r.lset(name, index, value) 對name對應的list中的某一個索引位置重新賦值 參數: name,redis的name index,list的索引位置 value,要設置的值 r.lset("foo_list1",4,44) 把索引號是4的元素修改成44 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 print(r.llen("foo_list1")) 24 列表長度是247 刪除(指定值進行刪除) r.lrem(name, value, num) 在name對應的list中刪除指定的值 參數: name,redis的name value,要刪除的值 num, num=0,刪除列表中所有的指定值; num=2,從前到后,刪除2個; num=1,從前到后,刪除左邊第1個 num=-2,從后向前,刪除2個 r.lrem("foo_list1","2",1) 將列表中左邊第一次出現的"2"刪除 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['1', '33', '22', '11', '44', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '22', '11', '3', '4', '1'] print(r.llen("foo_list1")) 23 列表長度是23r.lrem("foo_list1","11",0) 將列表中所有的"11"刪除 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['1', '33', '22', '44', '22', '22', '22', '22', '22', '22', '22', '3', '4', '1'] print(r.llen("foo_list1")) 14 列表長度是148 刪除并返回 lpop(name) 在name對應的列表的左側獲取第一個元素并在列表中移除,返回值則是第一個元素 更多: rpop(name) 表示從右向左操作 print(r.lpop("foo_list1")) 刪除最左邊的22,并且返回刪除的值22 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['44', '22', '22', '22', '22', '22', '22', '22', '3', '4', '1'] print(r.llen("foo_list1")) 11 列表長度是11print(r.rpop("foo_list1")) 刪除最右邊的1,并且返回刪除的值1 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素 ['44', '22', '22', '22', '22', '22', '22', '22', '3', '4'] print(r.llen("foo_list1")) 10 列表長度是109 刪除索引之外的值 ltrim(name, start, end) 在name對應的列表中移除沒有在start-end索引之間的值 參數: name,redis的name start,索引的起始位置 end,索引結束位置 r.ltrim("foo_list1",0,8) 刪除索引號是0-8之外的元素,值保留索引號是0-8的元素 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['44', '22', '22', '22', '22', '22', '22', '22', '3']10 取值(根據索引號取值) lindex(name, index) 在name對應的列表中根據索引獲取列表元素 print(r.lindex("foo_list1",0)) 44 取出索引號是0的值 print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['44', '22', '22', '22', '22', '22', '22', '22', '3', '4']11 移動 元素從一個列表移動到另外一個列表 rpoplpush(src, dst) 從一個列表取出最右邊的元素,同時將其添加至另一個列表的最左邊 參數: src,要取數據的列表的name dst,要添加數據的列表的name r.rpoplpush("foo_list1","foo_list2") print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['44', '22', '22', '22', '22', '22', '22'] print(r.lrange("foo_list2",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['22', '3']12 移動 元素從一個列表移動到另外一個列表 可以設置超時 brpoplpush(src, dst, timeout=0) 從一個列表的右側移除一個元素并將其添加到另一個列表的左側 參數: src,取出并要移除元素的列表對應的name dst,要插入元素的列表對應的name timeout,當src對應的列表中沒有數據時,阻塞等待其有數據的超時時間(秒),0 表示永遠阻塞 r.brpoplpush("foo_list2","foo_list1",timeout=2) print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['22', '3', '44', '22', '22', '22', '22', '22', '22'] print(r.lrange("foo_list2",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) []13 一次移除多個列表 blpop(keys, timeout) 將多個列表排列,按照從左到右去pop對應列表的元素 參數: keys,redis的name的集合 timeout,超時時間,當元素所有列表的元素獲取完之后,阻塞等待列表內有數據的時間(秒), 0 表示永遠阻塞 更多: r.brpop(keys, timeout),從右向左獲取數據 r.blpop("foo_list1",timeout=2) print(r.lrange("foo_list1",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉) ['22', '3', '44', '22', '22', '22', '22', '22', '22'] print(r.lrange("foo_list2",0,-1)) 切片取出值,范圍是索引號0-最后一個元素(這里是包含最后一個元素的,是左閉右閉)14 自定義增量迭代 由于redis類庫中沒有提供對列表元素的增量迭代,如果想要循環name對應的列表的所有元素,那么就需要: 1、獲取name對應的所有列表 2、循環列表 但是,如果列表非常大,那么就有可能在第一步時就將程序的內容撐爆,所有有必要自定義一個增量迭代的功能: def list_iter(name): """ 自定義redis列表增量迭代 :param name: redis中的name,即:迭代name對應的列表 :return: yield 返回 列表元素 """ list_count = r.llen(name) for index in xrange(list_count): yield r.lindex(name, index)使用 for item in list_iter('foo_list1'): ['3', '44', '22', '22', '22'] 遍歷這個列表 print item


    6 redis基本命令_set

    ?

    import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379)host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例Set操作,Set集合就是不允許重復的列表1 新增 sadd(name,values) name對應的集合中添加元素 r.sadd("foo_set1",33,44,55,66) 往集合中添加一個元素 11 print(r.smembers("foo_set1")) set(['11']) 獲取集合中所有的成員 print(r.scard("foo_set1")) 1 集合的長度是1r.sadd("foo_set2",66,77) 往集合中添加2個元素 22,33 print(r.smembers("foo_set2")) set(['22',"33"]) 獲取集合中所有的成員 print(r.scard("foo_set2")) 2 集合的長度是22 獲取元素個數 類似于len scard(name) 獲取name對應的集合中元素個數3 獲取集合中所有的成員 smembers(name) 獲取name對應的集合的所有成員3-1 獲取集合中所有的成員--元組形式 sscan(name, cursor=0, match=None, count=None) print(r.sscan("foo_set1")) (0L, ['11', '22', '33', '55'])3-2 獲取集合中所有的成員--迭代器的方式 sscan_iter(name, match=None, count=None) 同字符串的操作,用于增量迭代分批獲取元素,避免內存消耗太大 for i in r.sscan_iter("foo_set1"): print(i)4 差集 sdiff(keys, *args) 在第一個name對應的集合中且不在其他name對應的集合的元素集合 print(r.sdiff("foo_set1","foo_set2")) set(['11']) 在集合foo_set1但是不在集合foo_set2中 print(r.smembers("foo_set1")) set(['22',"11"]) 獲取集合中所有的成員 print(r.smembers("foo_set2")) set(['22',"33"]) 獲取集合中所有的成員5 差集--差集存在一個新的集合中 sdiffstore(dest, keys, *args) 獲取第一個name對應的集合中且不在其他name對應的集合,再將其新加入到dest對應的集合中 r.sdiffstore("foo_set3","foo_set1","foo_set2") print(r.smembers("foo_set1")) set(['22',"11"]) 獲取集合1中所有的成員 print(r.smembers("foo_set2")) set(['22',"33"]) 獲取集合2中所有的成員 print(r.smembers("foo_set3")) set(['11']) 獲取集合3中所有的成員6 交集 sinter(keys, *args) 獲取多一個name對應集合的交集 print(r.sinter("foo_set1","foo_set2")) set(['22']) 取2個集合的交集 print(r.smembers("foo_set1")) set(['22',"11"]) 獲取集合1中所有的成員 print(r.smembers("foo_set2")) set(['22',"33"]) 獲取集合2中所有的成員7 交集--交集存在一個新的集合中 sinterstore(dest, keys, *args) 獲取多一個name對應集合的并集,再將其加入到dest對應的集合中 r.sinterstore("foo_set3","foo_set1","foo_set2") print(r.smembers("foo_set1")) set(['22',"11"]) 獲取集合1中所有的成員 print(r.smembers("foo_set2")) set(['22',"33"]) 獲取集合2中所有的成員 print(r.smembers("foo_set3")) set(['22']) 獲取集合3中所有的成員7-1 并集 sunion(keys, *args) 獲取多個name對應的集合的并集 print(r.sunion("foo_set1","foo_set2")) set(['11', '22', '33', '77', '55', '66']) print(r.smembers("foo_set1")) set(['11', '33', '22', '55']) 獲取集合1中所有的成員 print(r.smembers("foo_set2")) set(['33', '77', '66', '22']) 獲取集合2中所有的成員7-2 并集--并集存在一個新的集合 sunionstore(dest,keys, *args) 獲取多一個name對應的集合的并集,并將結果保存到dest對應的集合中 r.sunionstore("foo_bingji","foo_set1","foo_set2") print(r.smembers("foo_set1")) set(['11', '33', '22', '55']) 獲取集合1中所有的成員 print(r.smembers("foo_set2")) set(['33', '77', '66', '22']) 獲取集合2中所有的成員 print(r.smembers("foo_bingji")) set(['11', '22', '33', '77', '55', '66'])8 判斷是否是集合的成員 類似in sismember(name, value) 檢查value是否是name對應的集合的成員 print(r.sismember("foo_set1",11)) True 11是集合的成員 print(r.sismember("foo_set1","11")) True print(r.sismember("foo_set1",23)) False 23不是集合的成員9 移動 smove(src, dst, value) 將某個成員從一個集合中移動到另外一個集合 r.smove("foo_set1","foo_set4",11) print(r.smembers("foo_set1")) set(['22',"11"]) 獲取集合1中所有的成員 print(r.smembers("foo_set4")) set(['22',"33"]) 獲取集合4中所有的成員10 刪除--隨機刪除并且返回被刪除值 spop(name) 從集合移除一個成員,并將其返回,說明一下,集合是無序的,所有是隨機刪除的 print(r.smembers("foo_set1")) set(['11', '22', '33', '44', '55', '66']) 獲取集合1中所有的成員 print(r.spop("foo_set1")) 44 (這個刪除的值是隨機刪除的,集合是無序的) print(r.smembers("foo_set1")) set(['11', '33', '66', '22', '55']) 獲取集合1中所有的成員11 刪除--指定值刪除 srem(name, values) 在name對應的集合中刪除某些值 print(r.smembers("foo_set1")) set(['11', '33', '66', '22', '55']) r.srem("foo_set1",66) 從集合中刪除指定值 66 print(r.smembers("foo_set1")) set(['11', '33', '22', '55'])12 隨機獲取多個集合的元素 srandmember(name, numbers) 從name對應的集合中隨機獲取 numbers 個元素 print(r.srandmember("foo_set1",3)) ['33', '55', '66'] 隨機獲取3個元素 print(r.smembers("foo_set1")) set(['11', '33', '66', '22', '55'])


    07 redis基本命令_有序set

    ?

    import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379) host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例Set操作,Set集合就是不允許重復的列表,本身是無序的 有序集合,在集合的基礎上,為每元素排序;元素的排序需要根據另外一個值來進行比較, 所以,對于有序集合,每一個元素有兩個值,即:值和分數,分數專門用來做排序。1 新增 zadd(name, *args, **kwargs) 在name對應的有序集合中添加元素 如: zadd('zz', 'n1', 1, 'n2', 2) 或 zadd('zz', n1=11, n2=22) r.zadd("foo_zset1",n3=11,n4=22) r.zadd("foo_zset2",n3=11,n4=23) print(r.zcard("foo_zset1")) 2 長度是2 2個元素 print(r.zrange("foo_zset1",0,-1)) ['n1', 'n2'] 獲取有序集合中所有元素 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n1', 11.0), ('n2', 22.0)] 獲取有序集合中所有元素和分數2 獲取有序集合元素個數 類似于len zcard(name) 獲取name對應的有序集合元素的數量3 獲取有序集合的所有元素 r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float) 按照索引范圍獲取name對應的有序集合的元素 參數: name,redis的name start,有序集合索引起始位置(非分數) end,有序集合索引結束位置(非分數) desc,排序規則,默認按照分數從小到大排序 withscores,是否獲取元素的分數,默認只獲取元素的值 score_cast_func,對分數進行數據轉換的函數 更多: 從大到小排序 zrevrange(name, start, end, withscores=False, score_cast_func=float) 按照分數范圍獲取name對應的有序集合的元素 zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float) 從大到小排序 zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)3-1 從大到小排序 zrevrange(name, start, end, withscores=False, score_cast_func=float) print(r.zrevrange("foo_zset1",0,-1)) ['n2', 'n1'] 只獲取元素,不顯示分數 print(r.zrevrange("foo_zset1",0,-1,withscores=True)) [('n2', 22.0), ('n1', 11.0)] 獲取有序集合中所有元素和分數,安裝分數倒序3-2 按照分數范圍獲取name對應的有序集合的元素 zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float) print(r.zrangebyscore("foo_zset1",15,25)) ['n2'] print(r.zrangebyscore("foo_zset1",12,22, withscores=True)) [('n2', 22.0)] 在分數是12-22之間(左閉右閉),取出符合條件的元素3-3 從大到小排序 zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float) print(r.zrevrangebyscore("foo_zset1",22,11,withscores=True)) [('n2', 22.0), ('n1', 11.0)] 在分數是22-11之間(左閉右閉),取出符合條件的元素 按照分數倒序3-4 獲取所有元素--默認按照分數順序排序 zscan(name, cursor=0, match=None, count=None, score_cast_func=float) print(r.zscan("foo_zset1")) (0L, [('n3', 11.0), ('n4', 22.0), ('n2', 30.0)])3-5 獲取所有元素--迭代器 zscan_iter(name, match=None, count=None,score_cast_func=float) for i in r.zscan_iter("foo_zset1"): 遍歷迭代器 print(i) ('n3', 11.0) ('n4', 22.0) ('n2', 30.0)4 zcount(name, min, max) 獲取name對應的有序集合中分數 在 [min,max] 之間的個數 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n1', 11.0), ('n2', 22.0)] print(r.zcount("foo_zset1",11,22)) 25 自增 zincrby(name, value, amount) 自增name對應的有序集合的 name 對應的分數 r.zincrby("foo_zset1","n2",amount=2) 每次將n2的分數自增2 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n1', 11.0), ('n2', 30.0)]6 獲取值的索引號 zrank(name, value) 獲取某個值在 name對應的有序集合中的排行(從 0 開始) 更多: zrevrank(name, value),從大到小排序 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n1', 11.0), ('n2', 30.0)] print(r.zrank("foo_zset1","n1")) 0 n1的索引號是0 這里按照分數順序(從小到大) print(r.zrank("foo_zset1","n2")) 1 n2的索引號是1print(r.zrevrank("foo_zset1","n1")) 1 n1的索引號是1 這里安照分數倒序(從大到小)7 刪除--指定值刪除 zrem(name, values) 刪除name對應的有序集合中值是values的成員 如:zrem('zz', ['s1', 's2']) print(r.zrange("foo_zset1",0,-1,withscores=True)) r.zrem("foo_zset2","n3") 刪除有序集合中的元素n1 刪除單個 print(r.zrange("foo_zset1",0,-1,withscores=True))8 刪除--根據排行范圍刪除,按照索引號來刪除 zremrangebyrank(name, min, max) 根據排行范圍刪除 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n3', 11.0), ('n4', 22.0), ('n2', 30.0)] r.zremrangebyrank("foo_zset1",0,1) 刪除有序集合中的索引號是0,1的元素 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n2', 30.0)]9 刪除--根據分數范圍刪除 zremrangebyscore(name, min, max) 根據分數范圍刪除 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n3', 11.0), ('n4', 22.0), ('n2', 30.0)] r.zremrangebyscore("foo_zset1",11,22) 刪除有序集合中的分數是11-22的元素 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n2', 30.0)]10 獲取值對應的分數 zscore(name, value) 獲取name對應有序集合中 value 對應的分數 print(r.zrange("foo_zset1",0,-1,withscores=True)) [('n3', 11.0), ('n4', 22.0), ('n2', 30.0)] print(r.zscore("foo_zset1","n3")) 11.0 獲取元素n3對應的分數11.0import redis 導入redis模塊,通過python操作redis 也可以直接在redis主機的服務端操作緩存數據庫pool = redis.ConnectionPool(host='192.168.19.130', port=6379) host是redis主機,需要redis服務端和客戶端都起著 redis默認端口是6379r = redis.Redis(connection_pool=pool) 創建實例


    08 其他常用操作

    ?

    1 刪除 delete(*names) 根據刪除redis中的任意數據類型(string、hash、list、set、有序set)1-1刪除string r.set('foo', 'Bar') print(r.strlen("foo")) 3 3ge 字節 print(r.getrange("foo",0,-1)) Bar r.delete("foo") 刪除字符串類型的foo print(r.get("foo")) None print(r.getrange("foo",0,-1)) print(r.strlen("foo")) 0 0個字節1-2 刪除hash r.hset("foo_hash4","k1","v1") print(r.hscan("foo_hash4")) (0L, {'k1': 'v1'}) r.delete("foo_hash4") 刪除hash類型的鍵值對 print(r.hscan("foo_hash4")) (0L, {})2 檢查名字是否存在 exists(name) 檢測redis的name是否存在 print(r.exists("foo_hash4")) True 存在就是True print(r.exists("foo_hash5")) False 不存在就是False2-1 r.lpush("foo_list5",11,22) print(r.lrange("foo_list5",0,-1)) ['22', '11', '22', '11'] print(r.exists("foo_list5")) True 存在就是True print(r.exists("foo_list6")) False 不存在就是False3 模糊匹配 keys(pattern='*') 根據模型獲取redis的name 更多: KEYS * 匹配數據庫中所有 key 。 KEYS h?llo 匹配 hello , hallo 和 hxllo 等。 KEYS h*llo 匹配 hllo 和 heeeeello 等。 KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo print(r.keys("foo*")) ['foo_hash1', 'foo_bingji', 'foo_list1', 'foo_list2', 'foo3', 'foo_set2', 'foo_hash4', 'foo_zset2', 'foo2', 'foo4', 'foo_set1', 'foo_zset1', 'foo_hash2', 'foo1', 'foo_list5', 'foo_set3']4 設置超時時間 expire(name ,time) 為某個redis的某個name設置超時時間 r.lpush("foo_list5",11,22) r.expire("foo_list5",time=10) print(r.lrange("foo_list5",0,-1))5 重命名 rename(src, dst) 對redis的name重命名為 r.rename("foo_list6","foo_list5") print(r.lrange("foo_list5",0,-1)) ['22', '11'] print(r.lrange("foo_list6",0,-1)) []6 隨機獲取name randomkey() 隨機獲取一個redis的name(不刪除) print(r.keys("foo*")) ['foo_set1', 'foo3', 'foo_set2', 'foo_zset2', 'foo4', 'foo_zset1', 'foo_list5', 'foo2', 'foo_hash2', 'foo1', 'foo_set3', 'foo_hash1', 'foo_hash4', 'foo_list2', 'foo_bingji'] print(r.randomkey()) foo_hash2 隨機獲取一個name7 獲取類型 type(name) 獲取name對應值的類型 print(r.type("foo_hash2")) hash print(r.type("foo_set1")) set print(r.type("foo3")) string8 查看所有元素 scan(cursor=0, match=None, count=None) print(r.hscan("foo_hash2")) (0L, {'k3': 'v3', 'k2': 'v2'}) print(r.sscan("foo_set3")) (0L, ['22']) print(r.zscan("foo_zset2")) (0L, [('n4', 23.0)]) print(r.getrange("foo1",0,-1)) 121 --字符串 print(r.lrange("foo_list5",0,-1)) ['22', '11'] --列表9 查看所有元素--迭代器 scan_iter(match=None, count=None) for i in r.hscan_iter("foo_hash2"):--遍歷 print(i) ('k3', 'v3') ('k2', 'v2')for i in r.sscan_iter("foo_set3"): print(i) 22for i in r.zscan_iter("foo_zset2"): print(i) ('n4', 23.0)__author__ = 'Administrator' -*- coding:utf-8 -*-管道 redis-py默認在執行每次請求都會創建(連接池申請連接)和斷開(歸還連接池)一次連接操作, 如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,并且默認情況下一次pipline 是原子性操作。import redispool = redis.ConnectionPool(host='192.168.19.130', port=6379)r = redis.Redis(connection_pool=pool)pipe = r.pipeline(transaction=False) pipe = r.pipeline(transaction=True)r.set('name', 'jack') r.set('role', 'sb')pipe.execute()print(r.get("name")) jack print(r.get("role")) sb

    ?

    ?

    ?

    ?

    總結

    以上是生活随笔為你收集整理的Python 操作 redis的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。