1. 程式人生 > 實用技巧 >EXCHANGE [FANOUT] 多播

EXCHANGE [FANOUT] 多播

目錄


Redis使用

安裝

Python操作Redis普通連線

1 pip install redis
#簡單使用
    from redis import Redis
    #獲取redis連線
    conn = Redis(host='127.0.0.1',port=6379)
    #key取值
    ret = conn.get('name')

    print(ret)#b'alex'

Python操作Redis連線池

#redis_pool\redis_pool.py

    import redis
    #連線池物件,最大連線數100
    POOL = redis.ConnectionPool(host='127.0.0.1',port=6379,max_connections=100)

#redis_pool\redis_pool.py  

    import redis
    from redis_pool import POOL
    #執行這句話就是從連線池拿出一個連線
    r = redis.Redis(connection_pool=POOL)

    ret = r.get('name')

    print(ret)#b'alex'

Redis資料型別

string(字串)
list(列表)
set(集合)
zset(有序集合)
hash(雜湊)
String(字串)操作
string在記憶體中按照一個name一個value來儲存,看圖1

#加*表示重點
set(name, value, ex=None, px=None, nx=False, xx=False)*
#設定值,不存在則建立,存在則修改,
引數:
	ex過期時間秒
    px過期時間毫秒
    nx為True時,key不存在時,才會執行,key存在則不執行操作
    xx為True時,key不存在時,不會執行操作,key存在才會執行
    
setnx(name, value)
#設定值,key不存在,才會執行,存在不會執行操作

setex(name, value, time)
#設定值,引數time過期時間數字秒,或timedelta物件

psetex(name, time_ms, value)
#設定值,引數time_ms過期時間數字毫秒,或timedelta物件

mset(*args,**kwargs)*
#批量設定值,如
	mset(k1='v1',k2='v2')
    mset({'k1':'v1','k2':'v2'})

get(key)*    
#獲取值

mget(keys,*args)*
#批量獲取,如
	mget('k1','k2')
    mget(['k1','k2'])

getset(name, value)*
#設定值並獲取原來的值

getrange(key, start, end)
#獲取子序列,根據位元組獲取,非字元,引數:
	start開始位置的索引(前閉後閉)#漢字佔3個位元組
    end結束位置的的索引(前閉後閉)

setrange(name, offset, value)
#修改字串內容,從指定索引向後修改,新值比原值長則向後新增,引數:
	0ffset開始修改字串的索引,漢字佔3個位元組
    value指要設定的指

setbit(name, offset, value)
#對key對應的值的二進位制(010101001)進行操作,引數:
	offset開始位的索引,需要將值轉成二進位制(1位元組等於8位二進位制)索引
    value值只能是0或1
    
getbit(name, offset)
# 獲取key對應值開始索引的二進位制的值0或1

bitcount(key, start=None, end=None)
#獲取key對應值的二進位制的值中的1的個數,引數:
	strat二進位制起始位置
    end二進位制結束位置
   
bitop(operation, dest, *keys)
#獲取多個值,並將值做位運算,將最後的值儲存至新的key對應的值,引數:
	operation可以是AND(並)、OR(或)、NOT(非)、XOR(異或)
	dest新的key名
    *keys要查詢的key
	如:
    conn.bitop('AND','name_1','name1','name2','name3')
    #獲取key,'name1','name2','name3'對應的值,做位運算(並集),然後將結果儲存到name_1對應的值中

strlen(name)
#返回key對應值的位元組長度(漢字三個位元組)

incr(self, name, amount=1)#incrby(self, name, amount=1)*
#自增key對應的值,當key不存在時,則建立key對應值是amount的值,否則則自增,引數:
	amount自增數,必須是整數

incrbyfloat(self, name, amount=1.0)
#自增key對應的值,key不存在時,則建立key=amount,否則自增,引數:
	amount自增數,必須是浮點型

decr(self, name, amount=1)*
#自減key對應的值,key不存在時,則建立key=amount,否則則自減,引數:
	amount自減數,必須是整數
    
append(key, value)*
#在key對應的值後面追加內容,引數:
	value要追加的字串

圖1

Hash(雜湊)操作
#Hash在記憶體中的儲存格式,value值必須是字串型別,看圖1

#加*表示重點
hset(name, key, value)*
#name對應的hash中設定一個鍵值對,不存在建立,存在則修改,引數:
	name指redis儲存hash的name
    key指name對應的hash的key
    value指name對應的hash的value
    
hmset(name, mapping)*
#在name對應的hash中批量設定鍵值對,引數:
	mapping是字典,比如{'k1':'v1','k2','v2'}
    
hget(name,key)*
#在name對應的hash中獲取根據key獲取value值

hmget(name, keys, *args)*
#在name對應的hash中獲取多個key對應的值。引數:
	keys要獲取key的集合,如['k1','k2','k3']
    *args要獲取的key,如k1,k2,k3
    例項:
        hmget('name',['k1','k2','k3'])
         hmget('name',k1,k2,k3)

hgetall(name)
#獲取name對應的hash的所有鍵值

hlen(name)
#獲取name對應的hash的鍵值對的個數

hkeys(name)
#獲取name對應的hash的所有的key的值

hvals(name)
#獲取name對應的hash的所有的value的值

hexists(name, key)
#檢查name對應的hash是否存在key

hdel(name,*keys)
#將name對應的hash指定的key的鍵值對刪除

hincrby(name, key, amount=1)*
#自增name對應的hash中指定的key的值,不存在則建立key=amount,引數:
	amount自增數,必須是整數
    
    
hincrbyfloat(name, key, amount=1.0)
#自增name對應的hash中指定key的值,不存在則建立key=amount,引數:
	amount自增數,必須是浮點數
    
    
hscan(name, cursor=0, match=None, count=None)
#增量式迭代獲取,對於資料大的非常有用,hscan可以實現分片式獲取資料,並非一次性將資料全部獲取,導致記憶體被撐爆,引數:
	cursor遊標,基於遊標分批獲取資料
    match匹配指定key,預設None,表示所有的key
    count每次分片最少獲取個數,預設None表示採用redis預設分片個數
    
hscan_iter(name, match=None, count=None)
#利用yield封裝hscan建立生成器,實現分批去redis中獲取資料,引數:
	match匹配指定key,預設Nnoe,表示所有的key
    count每次分片最少獲取個數,預設None表示採用redis的預設分片個數
    例項:for item in r.hscan_iter('xx'):
        	print item    
            
# 區分hgetall和hscan_iter            

List(列表)操作
#List在記憶體中按照一個name對應一個List來儲存,看圖1

#加*表示重點
lpush(name,values)*
#在name對應的list中新增元素,每個新的元素都新增到列表的最左邊,如:
	r.lpush('oo', 11,22,33)
    結果為: 33,22,11
    # 擴充套件:
        rpush(name, values) 表示從右向左操作

lpushx(name,value)
#在name對應的list中新增元素,只有name存在時,值新增到list最左邊
	擴充套件:rpushx(name, value) 表示從右向左操作
    
llen(name)*
#name對應的list元素的個數

linsert(name, where, refvalue, value))
#在name對應的list的某一個值前面或後面插入一個值,引數:
	where可以式BEFORE或AFTER(小寫也可以)
    refvalue標杆值,在它前後插入資料,如果存在多個標杆值,以找到的第一個為準
    value要插入的值
    
r.lset(name, index, value)
#對name對應的list的某一個索引位置重新賦值,引數:
	index指需要重新賦值的索引位置
    value要設定的值
    
r.lrem(name, value, num)
#在name對應的list中刪除指定的值,引數:
	value要刪除的值
    num:
    	num=0表示刪除該list中所有指定值
        num=2表示從前到後刪除兩個
        num=-2表示從後到前刪除兩個
        
lpop(name)*
#在name對應的list左側獲取第一個元素並在list中移除,返回值則是該元素
	擴充套件:rpop(name) 表示從右向左操作
    
lindex(name, index)
#在name對應的list中根據索引獲取list元素

lrange(name, start, end)*
#在name對應的list分片獲取資料,引數:
	start開始的索引位置
    end結束的索引位置
    
ltrim(name, start, end)
#在name對應的list中移除沒有在start-end索引之間的值,引數:
	start開始的索引位置
    end結束的索引位置
    
rpoplpush(src, dst)
#從一個列表取出最右邊的元素,提示新增到另一個list的最左邊,引數:
	src要獲取資料的list的name
    dst要新增資料的list的name
    
blpop(keys, timeout)*
#將多個list排列,按照從左到右去pop對應list的元素,引數:
	keys是個集合,要pop元素的集合
    timeout超時時間,當元素所有list的元素獲取玩之後,阻塞等待list內資料局的時間秒,0表示醫院阻塞,
    擴充套件:r.brpop(keys, timeout),從右向左獲取資料,應用場景:爬蟲實現簡單分散式:多個url放到列表裡,往裡不停放URL,程式迴圈取值,但是隻能一臺機器執行取值,可以把url放到redis中,多臺機器從redis中取值,爬取資料,實現簡單分散式

brpoplpush(src, dst, timeout=0)    
#從一個列表的右側移除一個元素,並將其新增到另一個list的左側,引數:
	src取出並要移除元素的list的name
    dst要插入元素的list的name
    timeout當src對應的list中沒有資料時,阻塞等待其有資料的超時時間秒,0表示醫院阻塞
 
自定義增量迭代
# 由於redis類庫中沒有提供對列表元素的增量迭代,如果想要迴圈name對應的列表的所有元素,那麼就需要:
    # 1、獲取name對應的所有列表
    # 2、迴圈列表
# 但是,如果列表非常大,那麼就有可能在第一步時就將程式的內容撐爆,所有有必要自定義一個增量迭代的功能:
import redis
conn=redis.Redis(host='127.0.0.1',port=6379)
# conn.lpush('test',*[1,2,3,4,45,5,6,7,7,8,43,5,6,768,89,9,65,4,23,54,6757,8,68])
# conn.flushall()
def scan_list(name,count=2):
    index=0
    while True:
        data_list=conn.lrange(name,index,count+index-1)
        if not data_list:
            return
        index+=count
        for item in data_list:
            yield item
print(conn.lrange('test',0,100))
for item in scan_list('test',5):
    print('---')
    print(item)

Set(集合)操作
其他操作
delete(*names)
#刪除redis中任意資料型別

exists(name)
#檢查redis的name是否存在

keys(pattern='*')
#根據模型獲取redis的name,其他引數:
	KEYS * 匹配資料庫中所有 key 。
    KEYS h?llo 匹配 hello , hallo 和 hxllo 等。
    KEYS h*llo 匹配 hllo 和 heeeeello 等。
    KEYS h[ae]llo 匹配 hello 和 hallo ,不匹配 hillo 
	
expire(name ,time)
#為某個redis的某個name設定超時時間

rename(src, dst)
#對redis的name重新命名

move(name, db)
#將redis的某個值移動到指定的db下

randomkey()
#隨機獲取一個redis的name,不刪除

type(name)
#獲取nmae對應值的型別

scan(cursor=0, match=None, count=None)
scan_iter(match=None, count=None)
#同字串操作,用於增量迭代獲取key

管道

如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,並且預設情況下一次pipline 是原子性操作。#redis預設在執行每次請求都會建立(連線申請連線池)和斷開(歸還連線池)一次性操作,如果想要在一次請求中指定多個命令,則可以使用pipline實現一次請求指定多個命令,並且預設情況下一次pipline 是原子性操作(要麼全部成功,要麼全部失敗)。

#test.py
    import redis

    pool = redis.ConnectionPool(host='10.211.55.4', port=6379)

    r = redis.Redis(connection_pool=pool)

    # pipe = r.pipeline(transaction=False)
    pipe = r.pipeline(transaction=True)
    pipe.multi()
    pipe.set('name', 'alex')
    pipe.set('role', 'sb')

    pipe.execute()

Django使用Redis

#方式一,通用方式
    #utils\redis_pool.py
    
		import redis
        #POOL連線池,max_connections=100指最大連線數是100
        POOL = redis.ConnectionPool(host='127.0.0.1',port=6379,max_connections=100)
        
	#app01\views.py
    
        import redis
        from utils.redis_pool import POOL
        from django.shortcuts import render, HttpResponse
        def index(request):
            conn = redis.Redis(connection_pool=POOL)
            conn.set('hobby','sleep')
            return HttpResponse('設定成功')

        def order(request):
            conn = redis.Redis(connection_pool=POOL)
            ret = conn.get('hobby')
            print(ret)
            return HttpResponse('獲取成功')
        
#方式二,安裝django-redis模組
	pip install django-redis
    
    #settings.py配置
    
        CACHES = {
        "default": {
            "BACKEND": "django_redis.cache.RedisCache",
            "LOCATION": "redis://127.0.0.1:6379",
            "OPTIONS": {
                "CLIENT_CLASS": "django_redis.client.DefaultClient",
                "CONNECTION_POOL_KWARGS": {"max_connections": 100}
                # "PASSWORD": "123",
            }
        }
    }
	#views.py
    from django_redis import get_redis_connection
    conn = get_redis_connection('default')
    print(conn.hgetall('xxx'))

介面快取

#luffyapi\apps\home\views.py,BannerView類內    
    def banner_list(self,request,*args,**kwargs):
        banner_list = cache.get('banner_list')
        if not banner_list:
            #快取沒有去資料拿
            response = super().list(request,*args,**kwargs)
            #加到快取
            cache.set('banner_list',response.data,60*60*24)#banner_list一天過期
        return Response(data=banner_list)