day11--RabbitMQ、Redis
??? RabbitMQ:就是消息隊列與Python里面的queue功能類似。線程和進程queue只能Python自己使用;不同機器和程序傳遞消息就要使用RabbitMQ了,中間傳遞。
??? RabbitMQ的功能與Queue的功能一樣,不同的是,線程queue.Queue()用來不同線程之間進行傳遞消息;進程Queue()用來子進程和父進程之間的數據交互;或者同屬于同一父進程下多個子進程進行交互。
??? RabbitMQ可以實現多個程序之間的數據交互,不需要讓程序去各自維護,統一通過中間商,RabbitMQ實現即可。
??? RabbitMQ地址:(http://erlang.org/download/?S=A/snapshots/otp_src_R14B01.readme/otp_doc_man_R16A_RELEASE_CANDIDATE.tar.gz/otp_win32_R10B-1a.exe/otp_doc_html_R16B.tar.gz/otp_doc_man_R10B-5.tar.gz)
?
??? RabbitMQ是使用erlang開發的
??? RabbitMQ隊列
??? 安裝?http://www.rabbitmq.com/install-standalone-mac.html
??? 安裝python rabbitMQ module
??? pip install pika
??? easy_install pika
??? https://pypi.python.org/pypi/pika
? ??實現最簡單的隊列通信 ??
??? 由于Linux電腦嘗試了很多次,配置沒有弄好,參考網址:https://www.cnblogs.com/alex3714/articles/5248247.html
??? send端
?
import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel() #聲明一個管道#聲明queue channel.queue_declare(queue='hello') #聲明一個"hello"的queue#n RabbitMQ a message can never be sent directly to the queue, it always needs to go through an exchange. channel.basic_publish(exchange='',routing_key='hello',body='Hello World!') #routing_key是queue的名稱 print(" [x] Sent 'Hello World!'") connection.close()?
??? receive端
import pikaconnection = pika.BlockingConnection(pika.ConnectionParameters('localhost')) channel = connection.channel()#You may ask why we declare the queue again ? we have already declared it in our previous code. # We could avoid that if we were sure that the queue already exists. For example if send.py program #was run before. But we're not yet sure which program to run first. In such cases it's a good # practice to repeat declaring the queue in both programs. channel.queue_declare(queue='hello')def callback(ch, method, properties, body):print(" [x] Received %r" % body)channel.basic_consume(callback, #如果收到消息,就調用callback函數來處理消息queue='hello', #從那個隊列里面接收消息no_ack=True) #不確認,no_ack=True,服務器端不確認;print(' [*] Waiting for messages. To exit press CTRL+C') channel.start_consuming()????? Work Queues
???
??? 在這種模式下,RabbitMQ會默認把p發的消息依次分發給各個消費者(c),跟負載均衡差不多
??? Redis操作(http://www.cnblogs.com/wupeiqi/articles/5132791.html)(http://www.cnblogs.com/alex3714/articles/6217453.html)(https://www.cnblogs.com/alex3714/articles/5248247.html)
??? 正常程序之間可以通過json和pickle傳遞數據,是通過文件。但是文件之間傳輸效率太低了。因此引入了緩存,緩存是放在內存中(硬盤效率太低),因此找一個中間媒介。現在常用的就是redis,下面來了解一下:
? ? redis是一個key-value存儲系統。和Memcached類似,它支持存儲的value類型相對更多,包括string(字符串)、list(鏈表)、set(集合)、zset(sorted set --有序集合)和hash(哈希類型)。這些數據類型都支持push/pop、add/remove及取交并集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支持各種不同方式的排序。與memcached一樣,為了保證效率,數據都是緩存在內存中。區別是redis會周期性的把更新的數據寫入磁盤或者把修改操作寫入追加的記錄文件,并且在次基礎上實現了master-slave(主從)同步。 ? 
??? Redis優點
??? 1.異常快速?:?Redis是非常快的,每秒可以執行大約110000設置操作,81000個/每秒的讀取操作;
??? 2.支持豐富的數據類型?:?Redis支持最大多數開發人員已經知道如列表,集合,可排序集合,哈希等數據類型;這使得在應用中很容易解決的各種問題,因為我們知道哪些問題處理使用哪種數據類型更好解決;
??? 3.操作都是原子的?:?所有?Redis?的操作都是原子,從而確保當兩個客戶同時訪問?Redis?服務器得到的是更新后的值(最新值);
??? 4.MultiUtility工具:Redis是一個多功能實用工具,可以在很多如:緩存,消息傳遞隊列中使用(Redis原生支持發布/訂閱),在應用程序中,如:Web應用程序會話,網站頁面點擊數等任何短暫的數據;
? ??安裝Redis環境
??? 一、Redis安裝和基本使用 
? ??啟動服務端
src/redis-server??? 啟動客戶端
1 src/redis-cli 2 redis> set foo bar 3 OK 4 redis> get foo 5 "bar"??? 二、Python操作Redis
??? Python操作Redis
sudo pip install redis or sudo easy_install redis or 源碼安裝詳見:https://github.com/WoLpH/redis-py? ?? 緩存里面的數據是共享的,是存儲在內存中,硬盤的效率太低,redis緩存也是通過socket基礎原理來實現數據的共享。redis就是一個類似字典key-value的緩存系統。
??? API使用
??? redis-py 的API的使用可以分類為:
??? 1.連接方式
??? 2.連接池
??? 3.操作
??????? String 操作???????? #簡單的keys-value操作
??????? Hash 操作
??????? List 操作
??????? Set 操作
??????? Sort Set 操作?????? #有序集合
??? 4.管道
??? 5.發布訂閱
??? 1、操作模式
???? redis-py提供兩個類Redis和StrictRedis用于實現Redis的命令,StrictRedis用于實現大部分官方的命令,并使用官方的語法和命令,Redis是StrictRedis的子類,用于向后兼容舊版本的redis-py。 
使用redis設置屬性:
  127.0.0.1:6379> set name alex
  OK
  127.0.0.1:6379> set age 22
  OK
??? set設置 name名字 alex值
??? keys *查看屬性
??? get來獲取屬性值(get name、get age)實現了兩個程序之間的數據共享,QQ、微信都能來取數據。??? 如果使用get獲取屬性,屬性不存在,則為空,如下:
? ??127.0.0.1:6379> get name
  "alex"
  127.0.0.1:6379> get foo
  "bar"
  127.0.0.1:6379> get alex
  (nil)
  127.0.0.1:6379> get age
  "22"
??? set使用方式:
??? set name alex ex 2中,ex 2代表設置存活時間,2代表兩秒,exists存在。set設置屬性的存活時間。
? ? 2、連接池
? ? redis-py使用connection pool來管理對一個redis server的所有連接,避免每次建立、釋放連接的開銷。默認,每個Redis實例都會維護一個自己的連接池。可以直接建立一個連接池,然后作為參數Redis,這樣就可以實現多個Redis實例共享一個連接池。經常取數據,建立socket連接,建立連接池,從池子里面取數據。
?
import redispool = redis.ConnectionPool(host="127.0.0.1",port=6379) #設置一個連接池,所有程序都從這個池子里面取數據
r = redis.Redis(connection_pool=pool) #建立一個連接實例
r.set("school","oldboy")
print(r.get("school"))
運行結果如下:
b'oldboy'
?
? ??set(name, value, ex=None, px=None, nx=False, xx=False)
在Redis中設置值,默認,不存在則創建,存在則修改 參數:ex,過期時間(秒)px,過期時間(毫秒)nx,如果設置為True,則只有name不存在時,當前set操作才執行xx,如果設置為True,則只有name存在時,崗前set操作才執行??? nx屬性是,如果屬性不存在,才設置,否則不會設置,如下:
127.0.0.1:6379[1]> set name alex OK 127.0.0.1:6379[1]> set name Alex nx (nil) 127.0.0.1:6379[1]> get name "alex"??? 上面,我們設置了name屬性,接著我們來覆蓋這個屬性,正常如果沒有nx屬性,"alex"將被“Alex"值覆蓋,但是這里設置了nx,由于name存在,不能覆蓋。nx的作用就是如果屬性存在,則設置不成功,否則設置成功。
??? xx只有當屬性存在的時候,操作才成功,即只覆蓋原來屬性,原來屬性不存在不會創建新的屬性,如下:
127.0.0.1:6379[1]> get name "alex" 127.0.0.1:6379[1]> set name Alex xx OK 127.0.0.1:6379[1]> get name "Alex" 127.0.0.1:6379[1]> set age 22 xx (nil)??? 從上面程序可以看出,xx是當屬性不存在的時候不會設置成功,只有當屬性存在了,覆蓋原來屬性,是用來覆蓋原來屬性的,屬性存在覆蓋,不存在不會創建。
??? setnx(name, value)
? ??設置值,只有name不存在時,執行設置操作(添加) ?
??? setex(name, time, value)
# 設置值 # 參數:# time,過期時間(數字秒 或 timedelta對象)??? psetex(key,milliseconds,value)
# 設置值 # 參數:# time_ms,過期時間(數字毫秒 或 timedelta對象)??? mset(*args, **kwargs)
批量設置值 如:mset(k1='v1', k2='v2')或mget({'k1': 'v1', 'k2': 'v2'})??? 批量設置參數,如下:
??? 127.0.0.1:6379[1]> mset k1 v1 k2 v2
  OK
  127.0.0.1:6379[1]> get k1
  "v1"
  127.0.0.1:6379[1]> get k2
  "v2"
??? get(name)
? ? 獲取值
? ??mget(keys, *args) ? ? 
??? mget(keys,*args)是批量獲取值,如下:
??? 127.0.0.1:6379[1]> mget k1 k2
  1) "v1"
  2) "v2"
??? getset(name, value)
??? 設置新值并獲取原來的值
? ? getset(name,value)是設置并獲取原來的新值,如果原來的值不存在,則(nil),如果原來的值存在,獲取原來的值,并把新值賦值給原來的屬性。如下:
? ? 127.0.0.1:6379[1]> getset k1 alex ? ? ? ? ? ? ? ? ?? #給k1設置新值,并獲取k1原來的值
  "v1"??????????????????????????????????????????????????????? #獲取到了k1原來的值
  127.0.0.1:6379[1]> getset k8 tom
  (nil)?????????????????????????????????????????????????????? #屬性k8不存在,則獲取不到原來的值,但是可以設置k8=tom
  127.0.0.1:6379[1]> get k1
  "alex"????????????????????????????????????????????????????? #屬性k1的值重新設置了
??? 127.0.0.1:6379[1]> get k8
  "tom"?????????????????????????????????????????????????????? #雖然k8不存在,但是可以設置
??? getrange(key, start, end)
?
# 獲取子序列(根據字節獲取,非字符) # 參數:# name,Redis 的 name# start,起始位置(字節)# end,結束位置(字節) # 如: "武沛齊" ,0-3表示 "武"?
??? 127.0.0.1:6379> getrange school 0 2
  "old"
??? getrange是獲取鍵值的切片長度,字符長度。中文是以字節形式獲取的,在redis里面,都是以字節形式存儲的。
? ? 127.0.0.1:6379> getrange myname 0 2
  "\xe8\x80\xbf"
??? setrange(name, offset, value)
?
# 修改字符串內容,從指定字符串索引開始向后替換(新值太長時,則向后添加) # 參數:# offset,字符串的索引,字節(一個漢字三個字節)# value,要設置的值?
??? setrange(name,offset,value)從某個設定的位置開始覆蓋,如下:
??? 127.0.0.1:6379> get school
  "oldboy"
  127.0.0.1:6379> setrange school 2 alex
  (integer) 6
  127.0.0.1:6379> get school
  "olalex"
??? setrange(name,offset,value)向下偏移offset個字符,覆蓋新的值value
??? 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-------------------------- ----------------------------- -----------------------------武 沛 齊??? bitcount統計列表中1的個數,bitcount,假如要統計一個網站的人數,可以使用數據庫來進行統計,可以通過設置不存在的變量來統計網站在線的人數,比如一個人登錄,就把這個人的ID設置為1,根據網站注冊人的ID編號,即是第幾個用戶,然后設置一個不存在的屬性,如下:
127.0.0.1:6379> setbit n1 1 1 (integer) 0 127.0.0.1:6379> setbit n1 2 1 (integer) 0 127.0.0.1:6379> setbit n1 5 1 (integer) 0 127.0.0.1:6379> bitcount n1 (integer) 3通過每次用戶登錄之后,把用戶的二進制設置為1,統計1的個數,就能統計人數
上面通過設置,在n1中有三個1存在。
??? setbit(name,offset,value)是按照二進制形式存在的,10101010001001111010011100011100111111100000
??? getbit(name, offset)
? ??# 獲取name對應的值的二進制表示中的某位的值 (0或1) ??
? ? 127.0.0.1:6379> getbit n1 1
  (integer) 1
  127.0.0.1:6379> getbit n1 10
  (integer) 0
??? 通過獲取二進制位的值,1代表登錄,0代表未登錄。
??? bitcount(key, start=None, end=None)
??? bitcount(key,start=None,end=None)統計屬性值里面二進制1的個數,比如10100001里面有3個1,bitcount的值就為3.
??? 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 對應的值中??? strlen(name)
??? # 返回name對應值的字節長度(一個漢字3個字節)
??? 127.0.0.1:6379> get school
  "olalex\x00\x00\x00\x00tom"
  127.0.0.1:6379> strlen school
  (integer) 13
??? 獲取字節的長度,strlen(name)是獲取屬性值的字節長度。
??? incr(self, name, amount=1)
?
??? 127.0.0.1:6379> incr n4
  (integer) 1
  127.0.0.1:6379> incr n4
  (integer) 2
  127.0.0.1:6379> incr n4
  (integer) 3
??? 自增屬性,當有新值存在是,自動增加1
??? incrbyfloat(self, name, amount=1.0)
?
# 自增 name對應的值,當name不存在時,則創建name=amount,否則,則自增。# 參數:# name,Redis的name# amount,自增數(浮點型)?
??? 可以設置定值增加,incr是以1每次遞增,incrbyfloat可以以amout=n以任何形式的值自增,如下:
??? 127.0.0.1:6379> incrbyfloat n4 3
  "8"
??? append(key, value)
?
# 在redis name對應的值后面追加內容# 參數:key, redis的namevalue, 要追加的字符串?
??? 127.0.0.1:6379> get age
  "22"
  127.0.0.1:6379> append age tom
  (integer) 5
  127.0.0.1:6379> get age
  "22tom"
??? append(key,value)字符串的拼接,屬性拼接值。
??? Hash操作,redis中Hash在內存中的存儲格式如下圖:
? ??
??? hash操作其實就是字典的操作,name相當于字典名,hash是字典里面的鍵值對,如dict={"k1":"v1","k2":"v2"}就是這樣的鍵值對構成,而name屬性就是這個字典的名稱。
??? hset(name, key, value)
# name對應的hash中設置一個鍵值對(不存在,則創建;否則,修改)# 參數:# name,redis的name# key,name對應的hash中的key# value,name對應的hash中的value# 注:# hsetnx(name, key, value),當name對應的hash中不存在當前key時則創建(相當于添加)??? hset(name,key,value)其中,name就相當于字典的名,key鍵,value值,如下:
??? 127.0.0.1:6379> hset info name alex??????????????????? #定義一個字典info,name=alex
  (integer) 1
??? 127.0.0.1:6379> hset info age 38?????????????????????? #添加鍵值對age=38
  (integer) 1
??? hgetall name:獲取name屬性(字典中)所有鍵和值
??? 127.0.0.1:6379> hgetall info
  1) "name"
  2) "alex"
  3) "age"
  4) "38"
  5) "id"
  6) "3344"
??? hget(name,key)
??? #在name對應的hash中獲取根據key獲取value
??? 127.0.0.1:6379> hget info name
  "alex"
  127.0.0.1:6379> hget info age
  "38"
??? hkeys name:查看所有name屬性(字典)中的鍵
??? 127.0.0.1:6379> hkeys info
  1) "name"
  2) "age"
  3) "id"
??? hvals name:獲取所有name屬性(字典)中的值??? 127.0.0.1:6379> hvals info
  1) "alex"
  2) "38"
  3) "3344"
??? hmset(name, mapping)
?
# 在name對應的hash中批量設置鍵值對# 參數:# name,redis的name# mapping,字典,如:{'k1':'v1', 'k2': 'v2'}# 如:# r.hmset('xx', {'k1':'v1', 'k2': 'v2'})?
??? 127.0.0.1:6379> hmset info2 name wupeiqi age 33 id 3636??????????????? #批量設置屬性鍵-值
  OK
  127.0.0.1:6379> hkeys info2
  1) "name"
  2) "age"
  3) "id"
??? hmget(name, keys, *args)
 
??? hmget(name,keys,*args)批量獲取值,如下:
??? 127.0.0.1:6379> hmget info2 name age id ? ? ? ?? #同時獲取info2中的name,age,id鍵值
  1) "wupeiqi"
  2) "33"
  3) "3636"
??? hlen(name)
 ? ? ?# 獲取name對應的hash中鍵值對的個數 
?
??? 127.0.0.1:6379> hlen info2??????????????????????? #hlen info2獲取info2中的鍵的個數
  (integer) 3
??? hexists(name, key)
? ??# 檢查name對應的hash是否存在當前傳入的key,即判斷name字典中是否包含Key
? ? 127.0.0.1:6379> hexists info2 sex
  (integer) 0
  127.0.0.1:6379> hexists ifno2 name
  (integer) 0
  127.0.0.1:6379> hexists info2 age
  (integer) 1
??? hexists(name,key)判斷name字典中是否存在鍵key,存在返回1;不存在,返回0
??? hdel(name,*keys)
? ??# 將name對應的hash中指定key的鍵值對刪除 
? ? 127.0.0.1:6379> hvals info2
  1) "wupeiqi"
  2) "33"
  3) "3636"
  4) "female"
  127.0.0.1:6379> hdel info2 sex ? ? ? ? ?? #刪除info2字典中的sex鍵值對
  (integer) 1
  127.0.0.1:6379> hvals info2
  1) "wupeiqi"
  2) "33"
  3) "3636"
??? hincrby(name, key, amount=1)
?
??? HINCRBY key field increment
? ??127.0.0.1:6379> hincrby info2 age 1
  (integer) 34
??? hincrby info2 age 1意思是:info2字典中age鍵的值增加1,只有整數才能增加,info2中的name是不可以的,會報錯,ERR hash value is not an integer,提示hash值不是整數。
??? hincrbyfloat(name, key, amount=1.0)
?
# 自增name對應的hash中的指定key的值,不存在則創建key=amount# 參數:# name,redis中的name# key, hash對應的key# amount,自增數(浮點數)# 自增name對應的hash中的指定key的值,不存在則創建key=amount?
??? 自增函數,與上面一樣,只是可以使用浮點數
??? 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時,表示數據已經通過分片獲取完畢??? hscan(name,cursor=0,match=None,count=None)是用來模糊匹配字典中的屬性。
??? 127.0.0.1:6379> hscan info3 0 match k*????????? #獲取info3中以k開頭的鍵值對
  1) "0"
  2) 1) "k1"
??? 2) "v1"
??? 3) "k2"
??? 4) "v2"
? ? 5) "k3"
? ? 6) "v3"
??? *代表所有,k*代表以*開頭。
??? 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?
??? List操作,redis中的List在在內存中按照一個name對應一個List來存儲。如圖:
??? redis中的列表就是我們常用的列表,只是方式不一樣,定義列表名和列表中的值,等價于name=list()
??? lpush(name,values)
# 在name對應的list中添加元素,每個新的元素都添加到列表的最左邊# 如:# r.lpush('oo', 11,22,33)# 保存順序為: 33,22,11# 擴展:# rpush(name, values) 表示從右向左操作?? lpush(name,values)就是定義一個名字為name的列表,往里面添加值,如下:
??? 127.0.0.1:6379> lpush names alex geng tom wupeiqi??? #定義了一個名字為names的列表,并添加alex,geng,tom,wupeiqi四個值到列表中
  (integer) 4
??? lrange name start end:查看列表中起始值,相當于切片,下面查看列表中所有的值:
??? 127.0.0.1:6379> lrange names 0 -1?????????? #查看列表names中所有的值
  1) "wupeiqi"
  2) "tom"
  3) "geng"
  4) "alex"
??? rpush(name,values)
??? # 在name對應的list中添加元素,每個新的元素都添加到列表的最右邊
??? 127.0.0.1:6379> rpush names 1 2 3
  (integer) 7
??? 往names列表的右邊添加元素
??? lpushx(name,value)
?
# 在name對應的list中添加元素,只有name已經存在時,值添加到列表的最左邊# 更多:# rpushx(name, value) 表示從右向左操作?
??? 127.0.0.1:6379> lpushx ages 22 ? ? ? ?? #列表ages不存在,不能插入值
  (integer) 0
  127.0.0.1:6379> lpushx names cang ? ? ? #列表names存在,可以插入值
  (integer) 
??? lpustx(name,value)是向列表中插入值,如果列表存在則插入,如果列表不存在,則不會創建新的列表,不能插入值。
??? llen(name)
??? # name對應的list元素的個數
 ? ??127.0.0.1:6379> llen names
  (integer) 8 ? 
??? llen(name)是查看列表的長度,即列表中有幾個元素。
??? linsert(name, where, refvalue, value)
?
??? linsert(name,where,refvalue,value),LINSERT key BEFORE|AFTER pivot value在某個值前或值后插入一個值,如下:
127.0.0.1:6379> lrange names 0 -1 1) "cang" 2) "wupeiqi" 3) "tom" 4) "geng" 5) "alex" 6) "6666" 7) "1" 8) "2" 9) "3" 127.0.0.1:6379> linsert names before wupeiqi 666 #在wupeiqi前面插入一個666 (integer) 10 127.0.0.1:6379> linsert names after wupeiqi 6666 #在wupeiqi后面插入一個6666值 (integer) 11 127.0.0.1:6379> lrange names 0 -11) "cang"2) "666"3) "wupeiqi"4) "6666"5) "tom"6) "geng"7) "alex"8) "6666"9) "1" 10) "2" 11) "3"??? linsert()是在指定的值前面或者后面插入一個值。
??? r.lset(name, index, value)
?
# 對name對應的list中的某一個索引位置重新賦值# 參數:# name,redis的name# index,list的索引位置# value,要設置的值?
??? lset(name,index,value)修改列表中某個索引位置的值,現在我們來修改列表names索引為2位置的值,如下:
127.0.0.1:6379> lrange names 0 3 1) "cang" 2) "666" 3) "wupeiqi" 4) "6666" 127.0.0.1:6379> lset names 2 ALEX #修改列表names中索引為2地方的值為ALEX OK 127.0.0.1:6379> lrange names 0 3 1) "cang" 2) "666" 3) "ALEX" 4) "6666"? ??r.lrem(name, value, num) ? ? ? ?LREM key count value
?
# 在name對應的list中刪除指定的值# 參數:# name,redis的name# value,要刪除的值# num, num=0,刪除列表中所有的指定值;# num=2,從前到后,刪除2個;# num=-2,從后向前,刪除2個?
??? lrem key count value刪除列表中的值,count是指定刪除幾個,value是刪除的值,key是列表名,如下:
127.0.0.1:6379> lrange names 0 -11) "cang"2) "666"3) "ALEX"4) "6666"5) "tom"6) "geng"7) "alex"8) "6666"9) "1" 10) "2" 11) "3" 127.0.0.1:6379> lrem names 1 1 #刪除列表中的1 (integer) 1 127.0.0.1:6379> lrem names 1 2 #刪除列表中的2 (integer) 1 127.0.0.1:6379> lrange names 0 -1 1) "cang" 2) "666" 3) "ALEX" 4) "6666" 5) "tom" 6) "geng" 7) "alex" 8) "6666" 9) "3"??? lpop(name)???????????????? LPOP key
# 在name對應的列表的左側獲取第一個元素并在列表中移除,返回值則是第一個元素# 更多:# rpop(name) 表示從右向左操作?
??? lpop(name)刪除列表中左邊的第一個值,rpop(name)刪除列表中右邊的第一個值,并返回,如下:
127.0.0.1:6379> lpop names #刪除列表names左側的第一個值,并返回這個值 "cang" 127.0.0.1:6379> rpop names #刪除列表names右側的第一個值,并返回這個值 "3"??? lindex(name, index) ? ? ? ? ?LINDEX key index
??? 在name對應的列表中根據索引獲取列表元素,即查詢列表中第index索引處的值
??? 127.0.0.1:6379> lindex names 1?????? #查詢列表names索引為1處的值
??? "ALEX"
??? lrange(name, start, end)
?
# 在name對應的列表分片獲取數據 # 參數:# name,redis的name# start,索引的起始位置# end,索引結束位置?
??? ltrim(name, start, end)???????? LTRIM key start stop
?
# 在name對應的列表中移除沒有在start-end索引之間的值 # 參數:# name,redis的name# start,索引的起始位置# end,索引結束位置?
??? ltrim(name,start,end)移除name列表索引start,end之間以外的所有元素,如下:
??? 127.0.0.1:6379> ltrim names 1 3???????????????? #移除names列表中處索引1-3之外所有的元素,只保留1-3之間的元素
  OK
??? 127.0.0.1:6379> lrange names 0 -1
??? 1) "ALEX"
  2) "6666"
  3) "tom"
??? rpoplpush(src, dst)
?
# 從一個列表取出最右邊的元素,同時將其添加至另一個列表的最左邊 # 參數:# src,要取數據的列表的name# dst,要添加數據的列表的name?
??? rpoplpush(src,dst)從一個列表右側拿出一個值,放入另外一個列表的左側。
??? blpop(keys, timeout)
?
# 將多個列表排列,按照從左到右去pop對應列表的元素# 參數:# keys,redis的name的集合# timeout,超時時間,當元素所有列表的元素獲取完之后,阻塞等待列表內有數據的時間(秒), 0 表示永遠阻塞# 更多:# r.brpop(keys, timeout),從右向左獲取數據?
??? brpoplpush(src, dst, timeout=0)
?
# 從一個列表的右側移除一個元素并將其添加到另一個列表的左側# 參數:# src,取出并要移除元素的列表對應的name# dst,要插入元素的列表對應的name# timeout,當src對應的列表中沒有數據時,阻塞等待其有數據的超時時間(秒),0 表示永遠阻塞?
??? Set操作,Set集合就是不允許重復的列表
? ? sadd(name,values)? 
? ??# name對應的集合中添加元素 ?? 
? ??127.0.0.1:6379> sadd nums 1 2 1 3 4??????????????? #創建一個nums集合,并往里面添加值
  (integer) 4 ?? 
??? smembers(name)
??? #獲取name集合中所有的元素
??? 127.0.0.1:6379> smembers nums?????????? #獲取集合nums中所有的元素
  1) "1"
  2) "2"
  3) "3"
  4) "4"
??? scard(name)
??? 獲取name對應的集合中元素個數
? ??127.0.0.1:6379> scard nums??????????????????????? #獲取集合nums中元素的個數,集合是無序的,無序集合,所以不能使用切片
  (integer) 4 ?? ?? 
??? sdiff(keys, *args)
??? 在第一個name對應的集合中且不在其他name對應的集合的元素集合
??? 127.0.0.1:6379> sadd numbers 1 2 3 6 7 9
  (integer) 6
  127.0.0.1:6379> sdiff nums numbers??????????? #獲取nums中有的,numbers中沒有的元素,即對稱差集,nums中有,numbers中沒有的元素
  1) "4"
??? sdiffstore(dest, keys, *args)
??? # 獲取第一個name對應的集合中且不在其他name對應的集合,再將其新加入到dest對應的集合中
??? sinter(keys, *args)
??? #獲取交集
??? 127.0.0.1:6379> sinter numbers nums???????????????? #獲取nums和numbers的交集
  1) "1"
  2) "2"
  3) "3"
??? sinterstore(dest, keys, *args)
??? # 獲取多一個name對應集合的交集,再講其加入到dest對應的集合中
??? 127.0.0.1:6379> smembers numbers
  1) "1"
  2) "2"
  3) "3"
  4) "6"
  5) "7"
  6) "9"
??? sismember(name, value)
??? # 檢查value是否是name對應的集合的成員
? ??smove(src, dst, value) ?? 
? ?? #將某個成員從一個集合中移動到另外一個集合 ?? 
??? spop(name)
??? # 從集合的右側(尾部)移除一個成員,并將其返回
??? srandmember(name, numbers)
? ??# 從name對應的集合中隨機獲取 numbers 個元素 
? ??127.0.0.1:6379> srandmember nums 2????????? #從集合num2中隨機獲取兩個元素
? ? 1) "1"
? ? 2) "6" ? 
??? srem(name, values)
??? # 在name對應的集合中刪除某些值
? ? 127.0.0.1:6379> srem nums 6??????? #刪除集合中指定的值
  (integer) 1
? ??sunion(keys, *args) ?? 
??? # 獲取多一個name對應的集合的并集
? ??sunionstore(dest,keys, *args) ? 
? ?# 獲取多一個name對應的集合的并集,并將結果保存到dest對應的集合中? ???
???? sscan(name, cursor=0, match=None, count=None)
??? sscan_iter(name, match=None, count=None)
??? # 同字符串的操作,用于增量迭代分批獲取元素,避免內存消耗太大
? ??有序集合,在集合的基礎上,為每元素排序;元素的排序需要根據另外一個值來進行比較,所以,對于有序集合,每一個元素有兩個值,即:值和分數,分數專門用來做排序。 ??
??? zadd(name, *args, **kwargs) ? ? ? ?ZADD key [NX|XX] [CH] [INCR] score member [score member ...]? ? ?
# 在name對應的有序集合中添加元素 # 如:# zadd('zz', 'n1', 1, 'n2', 2)# 或# zadd('zz', n1=11, n2=22)??? 127.0.0.1:6379> zadd people 1 alex 2 wupeiqi??????????? #創建有序集合,有序集合名people,分數1,名字alex;分數2,名字wupeiqi
  (integer) 2
??? zrange(name,start,end) ? ? ? ? ? ? ? 
??? #根據分數高低進行排序
??? 127.0.0.1:6379> zrange people 0 -1 ? ? ? ? ? ? ? ?? #獲取有序集合中的索引元素
  1) "alex"
  2) "wupeiqi"
??? 在有序集合中,分數可以更改,但是值只有一個。
??? 可以顯示分數zrange name start end wihtscores
??? 127.0.0.1:6379> zrange people 0 -1 withscores?????????????????????? #顯示people有序集合的元素,并顯示分數
  1) "alex"
  2) "1"
  3) "wupeiqi"
  4) "2"
??? zcard(name)
??? # 獲取name對應的有序集合元素的數量
? ??127.0.0.1:6379> zcard people????? #獲取有序集合中的元素數量
  (integer) 2 ?? 
??? zcount(name, min, max)
??? # 獲取name對應的有序集合中分數 在 [min,max] 之間的個數
??? 127.0.0.1:6379> zcount people 1 9 ? ? ? ? ? #統計people集合中分數在1-9之間元素的個數
  (integer) 4
??? zincrby(name, value, amount)
??? # 自增name對應的有序集合的 name 對應的分數
??? 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)??? zrank(name, value)
獲取某個值在 name對應的有序集合中的排行(從 0 開始)# 更多:# zrevrank(name, value),從大到小排序??? zrangebylex(name, min, max, start=None, num=None)
# 當有序集合的所有成員都具有相同的分值時,有序集合的元素會根據成員的 值 (lexicographical ordering)來進行排序,而這個命令則可以返回給定的有序集合鍵 key 中, 元素的值介于 min 和 max 之間的成員 # 對集合中的每個成員進行逐個字節的對比(byte-by-byte compare), 并按照從低到高的順序, 返回排序后的集合成員。 如果兩個字符串有一部分內容是相同的話, 那么命令會認為較長的字符串比較短的字符串要大# 參數:# name,redis的name# min,左區間(值)。 + 表示正無限; - 表示負無限; ( 表示開區間; [ 則表示閉區間# min,右區間(值)# start,對結果進行分片處理,索引位置# num,對結果進行分片處理,索引后面的num個元素# 如:# ZADD myzset 0 aa 0 ba 0 ca 0 da 0 ea 0 fa 0 ga# r.zrangebylex('myzset', "-", "[ca") 結果為:['aa', 'ba', 'ca']# 更多:# 從大到小排序# zrevrangebylex(name, max, min, start=None, num=None)??? zrem(name, values)
# 刪除name對應的有序集合中值是values的成員# 如:zrem('zz', ['s1', 's2'])??? zremrangebyrank(name, min, max)
??? #根據排行范圍刪除
? ? zremrangebyscore(name,min,max) ??
??? #根據分數范圍刪除
??? zremrangebylex(name,min,max)
??? #根據值返回刪除??? zscore(name, value)
??? #獲取name對應有序集合中value對應的分數? ??? zinterstore(dest, keys, aggregate=None)
# 獲取兩個有序集合的交集,如果遇到相同值不同分數,則按照aggregate進行操作 # aggregate的值為: SUM MIN MAX??? zunionstore(dest, keys, aggregate=None)
# 獲取兩個有序集合的并集,如果遇到相同值不同分數,則按照aggregate進行操作 # aggregate的值為: SUM MIN MAX??? zscan(name, cursor=0, match=None, count=None, score_cast_func=float)
??? zscan_iter(name, match=None, count=None,score_cast_func=float)
??? # 同字符串相似,相較于字符串新增score_cast_func,用來對分數進行操作
??? 其他常用操作:
??? delete(*names)???? ---del name
# 根據刪除redis中的任意數據類型??? del name刪除redis中名字是name的集合,元素的名稱,如下:
127.0.0.1:6379> del n4 #刪除redis中名稱為n4的元素(字符串名稱,列表名,字典名,集合名,有序集合名) (integer) 1 127.0.0.1:6379> keys *1) "numbers"2) "names"3) "info2"4) "number"5) "myname"6) "foo"7) "nums"8) "info3"9) "age" 10) "info" 11) "n1" 12) "school" 13) "ifno2"??? exists(name)
# 檢測redis的name是否存在??? 127.0.0.1:6379> exists myname?? #檢測redis中是否存在名稱為myname的命名
  (integer) 1
  127.0.0.1:6379> exists tom
  (integer) 0
??? keys(pattern="*")
# 根據模型獲取redis的name# 更多:# KEYS * 匹配數據庫中所有 key 。# KEYS h?llo 匹配 hello , hallo 和 hxllo 等。# KEYS h*llo 匹配 hllo 和 heeeeello 等。# KEYS h[ae]llo 匹配 hello 和 hallo ,但不匹配 hillo??? keys(parrern="*")里面可以加正則表達式,默認是匹配所有,也可以加正則進行匹配
??? 127.0.0.1:6379> keys n*?????????????????? #匹配以n開頭的所有命名
  1) "numbers"
  2) "names"
  3) "number"
  4) "nums"
  5) "n1"
? ? expire(name,time) ?
# 為某個redis的某個name設置超時時間??? rename(src,dst)
# 對redis的name重命名為??? 修改名字,如下:
??? 127.0.0.1:6379> rename ifno2 info??????? #修改ifno2的名字為info
  OK
  127.0.0.1:6379> keys *
  1) "numbers"
  2) "names"
  3) "number"
  4) "nums"
  5) "age"
  6) "info"
  7) "school"
??? move(name,db) ?? #redis默認有15個db
# 將redis的某個值移動到指定的db下??? randomkey()
# 隨機獲取一個redis的name(不刪除)??? 127.0.0.1:6379> randomkey????????? #隨機獲取一個key
  "info"
  127.0.0.1:6379> randomkey
  "name
??? type(name)??
# 獲取name對應值的類型??? type(name)是查看變量的類型,是字典,集合、字符串等等;如下:
127.0.0.1:6379> type numbers #查看numbers的類型,集合 set 127.0.0.1:6379> type names #查看names的類型,列表 list 127.0.0.1:6379> type info #查看info的類型,hash哈希(即字典) hash 127.0.0.1:6379> type school #查看school的類型,字符串 string127.0.0.1:6379> type vip #查看vip的類型,有序集合
zset
??? scan(cursor=0,match=None,count=None)
??? scan_iter(match=None,count=None)
??? #同字符串操作,用戶增量迭代獲取key
??? 4、管道
? ??redis-py默認在執行每次請求都會創建(連接池申請連接)和斷開(歸還連接池)一次連接操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,并且默認情況下一次pipline 是原子性操作.
? ??5、發布訂閱 ?
? ??
??? 發布者:服務器
??? 訂閱者:Dashboad和數據處理(http://www.cnblogs.com/wupeiqi/articles/5132791.html)
??? Demo如下:
import redisclass RedisHelper:def __init__(self):self.__conn = redis.Redis(host='10.211.55.4')self.chan_sub = 'fm104.5'self.chan_pub = 'fm104.5'def public(self, msg):self.__conn.publish(self.chan_pub, msg)return Truedef subscribe(self):pub = self.__conn.pubsub()pub.subscribe(self.chan_sub)pub.parse_response()return pub??? 訂閱者:
from monitor.RedisHelper import RedisHelperobj = RedisHelper() redis_sub = obj.subscribe()while True:msg= redis_sub.parse_response()print msg??? 發布者:
from monitor.RedisHelper import RedisHelperobj = RedisHelper() obj.public('hello')轉載于:https://www.cnblogs.com/gengcx/p/7512807.html
總結
以上是生活随笔為你收集整理的day11--RabbitMQ、Redis的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: ORM的概念, ORM到底是什么
- 下一篇: shell 练习题01:列出使用最多的命
