一 .redis+python操作
1.redis
redis.windows.conf各項配置參數介紹 win版 https://www.cnblogs.com/xuchunlin/p/7097729.html
https://www.cnblogs.com/zhaohuhu/p/9140673.html#_label0_0
https://www.runoob.com/redis/redis-sorted-sets.html
https://www.cnblogs.com/wupeiqi/articles/5132791.html
Redis是一個開源(BSD許可),內存數據結構存儲,用作數據庫,緩存和消息代理。
它支持數據結構,如 字符串,散列,列表,集合,帶有范圍查詢的排序集,位圖,超級日志和帶有半徑查詢的地理空間索引。
Redis具有內置復制,Lua腳本,LRU驅逐,事務和不同級別的磁盤持久性,並通過Redis Sentinel提供高可用性和Redis
Cluster自動分區。
用於操作內存的軟件
可以做持久化
AOF
RDB
-相當於一個大字典
單進程單線程
redis常見性能問題和解決方案:
(1) Master最好不要做任何持久化工作,如RDB內存快照和AOF日志文件 (2) 如果數據比較重要,某個Slave開啟AOF備份數據,策略設置為每秒同步一次 (3) 為了主從復制的速度和連接的穩定性,Master和Slave最好在同一個局域網內 (4) 盡量避免在壓力很大的主庫上增加從庫 (5) 主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即:Master <- Slave1 <- Slave2 <- Slave3... 這樣的結構方便解決單點故障問題,實現Slave對Master的替換。如果Master掛了,可以立刻啟用Slave1做Master,其他不變。
2. resis+python
1. 連接池
redis-py使用connection pool來管理對一個redis server的所有連接,避免每次建立、釋放連接的開銷。默認,
每個Redis實例都會維護一個自己的連接池。可以直接建立一個連接池,然后作為參數Redis,這樣就可以實現多個Redis實例
共享一個連接池。
使用連接池
本質 維護一個已經和服務器連接成功了的socket
以后再發送數據時 直接獲取一個sockect 直接send數據
import redis pool = redis.ConnectionPool(host='192.168.18.11', port=6379) r = redis.Redis(connection_pool=pool) r.set('foo', 'Bar') print (r.get('foo')) #是一個字節 b'Bar'
2. redis字典操作(注意:redis操作時 只有第一層value支持 list dict..)
https://www.cnblogs.com/xuchunlin/p/7064860.html
redis支持五大數據類型,只支持第一層,也就說字典的value值,必須是字符串
如果value值想存字典,必須用json轉換一下,轉成字符串

import redis pool = redis.ConnectionPool(host='localhost', port=6379) conn= redis.Redis(connection_pool=pool) # 字典操作 """resds={ k1:{ username:nice, age:18 } }""" # 設置值 conn.hset("k1","username","nice") conn.hset("k1","age",18)
redis hash字典操作
reids:{ k1:'dafdadfasf', m1:{ 'key2':value2, 'key1':value1, } }
hset(name, key, value),插入值
# name對應的hash中設置一個鍵值對(不存在,則創建;否則,修改) # 參數: # name,redis的name # key,name對應的hash中的key # value,name對應的hash中的value # 注: # hsetnx(name, key, value),當name對應的hash中不存在當前key時則創建(相當於添加) # 設置值 # conn.hset('m1','cao','曹蕊')
hmset(name, mapping),批量插入值
# 在name對應的hash中批量設置鍵值對 # 參數: # name,redis的name # mapping,字典,如:{'k1':'v1', 'k2': 'v2'} # 如: # r.hmset('xx', {'k1':'v1', 'k2': 'v2'}) # 批量插入設置值 # conn.hmset('m2', {'cao': 100, 'bai': 101})
hget(name,key),取值
# 在name對應的hash中獲取根據key獲取value # 取值,根據大字典的key,再去查key print(conn.hget('m2','cao'))
hmget(name, keys, *args) 批量取值
# 在name對應的hash中獲取多個key的值 # 參數: # name,reids對應的name # keys,要獲取key集合,如:['k1', 'k2', 'k3'] # *args,要獲取的key,如:k1,k2,k3 # 如: # r.mget('xx', ['k1', 'k2']) # 或 # print r.hmget('xx', 'k1', 'k2') print(conn.hmget('m2','cao','bai')) print(conn.hmget('m2',['cao','bai']))
hlen(name)
# 獲取name對應的hash中鍵值對的個數 # print(conn.hlen('m2'))
hkeys(name)
# 獲取name對應的hash中所有的key的值 # print(conn.hkeys('m2'))
hvals(name)
# 獲取name對應的hash中所有的value的值 # print(conn.hvals('m2'))
hexists(name, key)
# 檢查name對應的hash是否存在當前傳入的key # print(conn.hexists('m2','cao'))
hdel(name,*keys)
# 將name對應的hash中指定key的鍵值對刪除 print(re.hdel('xxx','sex','name')) # conn.hdel('m2','key1','key2') # 這樣可以 # conn.hdel('m2',*['key1','key2']) # 這樣不行 # conn.hdel('m2',['key1','ke
hincrby用來統計一個東西的數量的頻繁增加(name, key, amount=1) 計數器
hincrby應用場景: 統計文章閱讀數:key是文章id,value是文章閱讀數,有一個閱讀者,數字加一,固定一個時間,將數據同步到數據庫,
一定要寫日志,避免出錯,還能查找到 # 自增name對應的hash中的指定key的值,不存在則創建key=amount # 參數: # name,redis中的name # key, hash對應的key # amount,自增數(整數) conn.hincrby('m1','key3')
hincrbyfloat(name, key, amount=1.0)
# 自增name對應的hash中的指定key的值,不存在則創建key=amount # 參數: # name,redis中的name # key, hash對應的key # amount,自增數(浮點數) # 自增name對應的hash中的指定key的值,不存在則創建key=amount
hgetall(name)——慎用,一次性取出數據前需要先hlen看下長度
# 獲取name對應hash的所有鍵值 print(re.hgetall('xxx').get(b'name')) # 根據key把所有的值取出來 # print(conn.hgetall('m2'))
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 應用場景: 比如我redis中字典有10000w條數據,全部都打印出來 hscan——指定游標,然后取多少值 for i in range(1000): conn.hset('m2','key%s'%i,'value%s'%i) 指定每次取10條,直到取完 ret=conn.hscan_iter('m2',count=100) 不要用這種方式,一下全部取出,redis可能會被撐爆,或者先用len查看下長度再決定使用getall或者其他 ret=conn.hgetall('m2')
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時,表示數據已經通過分片獲取完畢
3. redis列表操作(隊列:先進先出 棧:后進先出)
https://www.cnblogs.com/zl1991/p/10552160.html


import redis pool = redis.ConnectionPool(host='localhost', port=6379) conn= redis.Redis(connection_pool=pool) """ redis = { k1:[1,2,3,43,45] } """ conn.lpush('k1',1111)
lpush(name,values) # 在name對應的list中添加元素,每個新的元素都添加到列表的最左邊 # 如: # r.lpush('oo', 11,22,33) # 保存順序為: 33,22,11 # 擴展: # rpush(name, values) 表示從右向左操作 lpushx(name,value) # 在name對應的list中添加元素,只有name已經存在時,值添加到列表的最左邊 # 更多: # rpushx(name, value) 表示從右向左操作 llen(name) # name對應的list元素的個數 linsert(name, where, refvalue, value)) # 在name對應的列表的某一個值前或后插入一個新值 # 參數: # name,redis的name # where,BEFORE或AFTER # refvalue,標桿值,即:在它前后插入數據 # value,要插入的數據 r.lset(name, index, value) # 對name對應的list中的某一個索引位置重新賦值 # 參數: # name,redis的name # index,list的索引位置 # value,要設置的值 r.lrem(name, value, num) # 在name對應的list中刪除指定的值 # 參數: # name,redis的name # value,要刪除的值 # num, num=0,刪除列表中所有的指定值; # num=2,從前到后,刪除2個; # num=-2,從后向前,刪除2個 lpop(name) # 在name對應的列表的左側獲取第一個元素並在列表中移除,返回值則是第一個元素 # 更多: # rpop(name) 表示從右向左操作 lindex(name, index) 在name對應的列表中根據索引獲取列表元素 lrange(name, start, end) # 在name對應的列表分片獲取數據 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置 ltrim(name, start, end) # 在name對應的列表中移除沒有在start-end索引之間的值 # 參數: # name,redis的name # start,索引的起始位置 # end,索引結束位置 rpoplpush(src, dst) # 從一個列表取出最右邊的元素,同時將其添加至另一個列表的最左邊 # 參數: # src,要取數據的列表的name # dst,要添加數據的列表的name
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 表示永遠阻塞
自定義增量迭代 (- 通過yield創建一個生成器完成一點一點獲取 通過字典操作的源碼來的靈感)
由於redis類庫中沒有提供對列表元素的增量迭代,如果想要循環name對應的列表的所有元素,那么就需要:
# 1、獲取name對應的所有列表
# 2、循環列表
# 但是,如果列表非常大,那么就有可能在第一步時就將程序的內容撐爆,所有有必要自定義一個增量迭代的功能:
import redis conn = redis.Redis(host='47.94.172.250',port=6379,) def list_iter(key,count=100):
自定義redis列表增量迭代
:param name: redis中的name,即:迭代name對應的列表
:return: yield 返回 列表元素
index = 0 while True: data_list = conn.lrange('k1', index, index+count-1) if not data_list: return index += count for item in data_list: yield item print(conn.lrange('k1',0,101))
使用 for item in list_iter('k1',count=3): print(item)
- 事務+一次發送多個命令
conn = redis.Redis(host='47.94.172.250',port=6379) pipe = conn.pipeline(transaction=True) pipe.multi() pipe.set('k2','123') pipe.hset('k3','n1',666) pipe.lpush('k4','laonanhai') pipe.execute()