前言
R: 代表 redis-cli
P: 代表 python的redis
準(zhǔn)備
pip install redis
pool = redis.ConnectionPool(host='39.107.86.223', port=6379, db=1)
redis = redis.Redis(connection_pool=pool)
redis.所有命令
下面命令所有命令我都省略了, 有和Python內(nèi)置函數(shù)沖突的我會(huì)加上 redis.
全局命令
-
dbsize(返回key的數(shù)量)
R: dbsize P: print(redis.dbsize())
-
exists(是否存在某key)
R: exists name P: exists('name')
-
keys(列出所有key,可使用通配符)
R: keys na* P: keys('na*') 注:時(shí)間復(fù)雜度為 O(n)
-
scan (對(duì)應(yīng)keys,迭代取出所有keys)
R: scan 0 match '*' count 4 P: keys_iter = redis.scan_iter(match='*', count=4) 注:這種scan,API后面也會(huì)有, 所以我全部放在最后的結(jié)束語中講
-
info (查看資源信息)
R: info # 也可以填參數(shù) info memory info cpu 等 P: redis.info() # redis.info('CPU') redis.info('MEMORY')
-
type (列出類型)
R: type name P: redis.type('name') # type和python的沖突了,所以這里我寫全了 redis中類型有: none string list set zset hash
過期時(shí)間
-
expire(設(shè)置)
R: expire name 秒數(shù) P: expire('name', 秒數(shù))
-
ttl(查詢)
R: ttl name P: ttl('name') # 返回剩余過期時(shí)間值 # 返回值為 -2 則代表 無此 key # 返回值為 -1 則代表 有此 key , 但未設(shè)置過期時(shí)間
-
persist(刪除)
R: persist name P: persist('name')
-
自增,自減
incr incrby 加上一個(gè)整數(shù) R: incr age 或 incrby age 1 P: incr age 1 或 incrby age 1 # python實(shí)現(xiàn) 的 incr 被 重定向?yàn)?incrby,所以用哪個(gè)都行 decr decrby 減去一個(gè)整數(shù) 同上 incrbyfloat 加減一個(gè)浮點(diǎn)數(shù) 同上
字符串相關(guān)操作
-
set 設(shè)置值
R: set name lin P: redis.set('name', 'lin') set選項(xiàng)(原子操作) nx(設(shè)置默認(rèn)值) R: set name lin nx P: redis.set('name', 'lin', nx=True) 注: nx 代表key不存在才會(huì)將值設(shè)置成功, 類似python dict的 setdefault,即給key設(shè)置默認(rèn)值 xx(更新值) R: set name Tom xx P: redis.set('name', 'lin', xx=True) 注: xx 代表key存在才會(huì)將值更新成功。 如果key不存在, 則更新失敗。
-
get 獲取值
R: get name P: redis.get('name') 注:通過py redis客戶端的 get取出的都是 字節(jié)二進(jìn)制類型, 所以需要手動(dòng)轉(zhuǎn)為對(duì)應(yīng)類型 前面提到的 incr decr 等, 操作返回結(jié)果直接就是 int, 而非 字節(jié)類型
-
mset 批量設(shè)置
R: mset name lin age 18 p: redis.mset( {'name': 'lin', 'age': 18} )
-
mget 批量獲取
R: mget name age p: redis.mget('name', 'age') # 返回值為 字節(jié)類型的 列表
-
getset 設(shè)置新值并返回舊值
R: getset name zhang P: print( redis.getset('name', 'zhang') )
-
append 字符串追加拼接
R: append name abc P: redis.append('name', 'abc')
-
strlen 獲取字符串長度
R: strlen name P: print( redis.strlen('name') ) 注: 與編程語言的普遍API不同的是, strlen返回的字符串 長度是 字符對(duì)應(yīng)編碼的長度。。。。 中文 utf-8 占 3個(gè)字節(jié)
-
getrange 字符串切片 (從0開始,前閉后閉)
R: getrange name 1 2 P: redis.getrange('name', 1, 2)
-
setrange 字符串按索引賦值(覆蓋)
R: setrange name 0 abc # 把第0個(gè)位置開始, 逐個(gè)覆蓋賦值為 abc, 多余的不變 P: redis.setrange('name', 0, 'abc')
-
del 刪除鍵值
R: del k1 k2 P: redis.delete(k1, k2)
Hash相關(guān)操作(可對(duì)應(yīng)為 文檔-屬性-值)
-
hset 設(shè)置 1條文檔,1個(gè)屬性-值
R: hset user name lin P: redis.hset('user', 'name', 'lin')
-
hget 獲取 1條文檔,1個(gè)屬性
R: hget user name P: print(redis.hget('user', 'name'))
-
hmset 設(shè)置 1條文檔, 多個(gè)屬性-值
R: hmset user name lin age 18 P: redis.hmset('user', {'user': 'lin', 'age': 18})
-
hmget 獲取 1條文檔, 多個(gè)屬性-值
R: hmget user name age P: print(redis.hmget('user', 'name', 'age'))
-
hkeys 獲取所有 key
R: hkeys user P: print(redis.hkeys('user'))
-
hvals 獲取所有 values
R: hvals user P: print(redis.hvals('user'))
-
hgetall 獲取 一條文檔,所有屬性值(慎用,見下一條API)
R: hgetall user # 返回為列表, 偶數(shù)索引為key,奇數(shù)索引為vaLue(從0開始) P: print(redis.hgetall('user')) # 返回為 dict格式 注: hgetall 會(huì)將所有key-value取出來,所以數(shù)據(jù)量龐大可能會(huì)造成性能影響。 大批量數(shù)據(jù)在python是怎么處理來著??????? 沒錯(cuò),就是迭代器,當(dāng)然python的redis模塊已為我們封裝好一個(gè)API,hscan_iter, 見一條API
-
hscan (hash迭代,大體上可代替 hgetall使用)
R: hscan user 0 match * count 200 # 按游標(biāo),按數(shù)量取 # 0代表游標(biāo)從頭開始 # match是關(guān)鍵字 # * 是key的通配符 # count 是一次接待的條數(shù) P: result_iter = redis.hscan_iter('user', match= 'na*', count=2) # python的 cursor參數(shù)沒有,是因?yàn)樵创a中被固定設(shè)置為 0了, 其他參數(shù)解釋同上 # 返回結(jié)果為可迭代對(duì)象,可遍歷取出。
-
hexists 檢測是否存在某key
R: hexists user name1 # 存在返回 1,不存在返回 0 P: print(redis.hexists('user', 'name')) # 存在返回True
-
hlen 統(tǒng)計(jì)獲取一個(gè)文檔,所有屬性的 總數(shù)
R: hlen user P: print(redis.hlen('user'))
-
hdel 刪除指定字段
R: hdel key field P: redis.hdel('key', 'field')
List相關(guān)操作
-
lpush (左壓棧)
R: lpush list1 1 2 3 P: redis.lpush('list1', 1,2,3)
-
rpush (右壓棧,同左壓棧,略)
-
lpop (左彈棧)
R: lpop list2 P: print(redis.lpop('list2'))
-
rpop (右彈棧,同左彈棧,略)
-
blpop (左阻塞彈棧,列表為空時(shí),就阻塞了)
R: blpop list2 1000 # 1000為過期時(shí)間為1000秒,1000秒后自動(dòng)解除阻塞,有值加入也會(huì)解除阻塞 P: redis.blpop('list2', timeout=1000)
-
brpop (右阻塞彈棧,同左阻塞彈棧,略)
-
linsert ( 在指定 值 的 前后 插入值)
R: linsert list2 before Tom jerry # 在Tom前插入 jerry, before代表之前 P: redis.linsert('list2', 'after', 'b', 'Tom') # 在b的后面插入Tom, after代表之后
-
lset (按索引賦值, 注意索引不要越界)
R:lset list2 4 zhang P: redis.lset('list2', 4, 'zhang')
-
lindex (按索引取值, 索引可正可負(fù))
R: lindex list2 -3 P: print(redis.lindex('list2', 3))
-
llen (獲取列表元素個(gè)數(shù))
R: llen list2 P: print(redis.llen('list2'))
-
ltrim (注意:在原數(shù)據(jù)上切片,不返回值。)
R: ltrim list2 3 10 # 保留 索引 3-10 的列表數(shù)據(jù),其他都刪除 P: print(redis.ltrim('list2', 2, -1)) # 索引前閉后閉,可正可負(fù)
-
lrem (刪除指定值)
R: lrem list2 0 Tom # 0 這個(gè)位置的參數(shù)代表刪除值的個(gè)數(shù) # 0 代表全部刪除, 刪除全部Tom值 # 正數(shù)代表 從左到右 刪除n個(gè)。 eg: lrem list2 5 Tom 即為 從左到右 刪除5個(gè)Tom值 # 負(fù)數(shù)代表 從右到左 刪除n個(gè)。 eg: lrem list2 -5 Tom 即為 從右到左 刪除5個(gè)Tom值 P: print(redis.lrem('list2', -5, 1)) # 解釋同上
-
lrange(遍歷,正負(fù)索引都可,前閉后閉)
R: lrange list1 0 -1 P: print(redis.lrange('list2', 0, -1))
Set相關(guān)操作
-
sadd (插入元素)
R: sadd set1 1 2 3 P: redis.sadd('set1', *[1,2,3])
-
srem (刪除指定值的元素)
R: srem set1 Tom P: redis.srem('set1', 'Tom')
-
scard (獲取集合中元素個(gè)數(shù))
R: scard set1 P: redis.scard('set1')
-
sismember (判斷某元素是否在集合)
R: sismember set1 Tom P: redis.sismember('set1', 'Tom')
-
srandmember (隨機(jī)取出集合指定個(gè)數(shù)元素)
“”“類似py的 random.choices,注意有s”“ R: srandmember set1 2 # 從集合隨機(jī)中取出2個(gè)元素 P: redis.srandmember('set1', 2)
-
smembers (取出集合中所有元素)
R: smembers set1 P: redis.smembers('set1') 注: 同 hgetall, 如果一次性取出,可能會(huì)出問題,所以需要迭代獲取,見下 sscan
-
sscan (游標(biāo)/迭代取出集合所有元素)
R: sscan set1 0 match * count 200 P: result_iter = redis.sscan_iter('set1', match='*', count=200) # 遍歷迭代
-
sdiff (差集)
R: sdiff sset1 sset2 P: print(redis.sdiff('sset1', 'sset2'))
-
sinter(交集)
R: sinter sset1 sset2 P: print(redis.sinter('sset1', 'sset2'))
-
sunion (并集)
R: sunion sset1 sset2 P: print(redis.sunion('sset1', 'sset2'))
zset 有序集合相關(guān)操作
-
zadd (有序插入)
R: zadd zset 100 Tom 90 Jerry # 100是權(quán)重,Tom是數(shù)據(jù)值, 注意redis-cli 權(quán)重在前,值在后 P: redis.zadd('zset', {'Tom': 100, 'Jerry': 90}) # 注意,py語法,權(quán)重作為字典的value 注特別注意: zadd的默認(rèn)機(jī)制是同值,不同權(quán)重時(shí),會(huì)更新值的權(quán)重 eg: 上面再插入一條 Tom, 不過這次的權(quán)重是 50 ( zadd zset 50 Tom),則Tom的權(quán)重會(huì)更新為50 這時(shí)就延申出2個(gè)參數(shù),(應(yīng)該還記得前面講的 set的 nx 和 xx參數(shù)吧,沒錯(cuò) zadd也有) nx: (不存在才更新(添加), 存在則更新(添加) 失敗) R: zadd zset nx 1000 Tom P: redis.zadd('zset',{'Tom': 1000}, nx=True) 注: 如果Tom這個(gè)值之前存在,則這個(gè)1000就不會(huì)被更新了 若不存在,則就會(huì)新創(chuàng)建,并把這個(gè)1000設(shè)置成功 nx:(存在才更新(添加), 不存在則更新(添加) 失敗) R: zadd zset xx 1000 Tom P:redis.zadd('zset',{'Tom': 1000}, xx=True) 注: 如果Tom這個(gè)值之前存在,則1000才會(huì)更新成功 如果不存在,比如 {'張三':500}, 張三本來就不存在,用了xx, 他不會(huì)被添加進(jìn)來,更何談更新
-
zrange (遍歷)
R: zrange zset 0 -1 P: print(redis.zrange('zset', 0, -1)) # 返回值為列表 withscores 參數(shù)(把權(quán)重也帶出來返回): R: zrange zset 0 -1 withscores # 注意, 返回時(shí) 奇數(shù)位 是值, 偶數(shù)位是權(quán)重 P: print(redis.zrange('zset', 0, -1, withscores=True)) # 返回列表嵌套元組,[(值,權(quán)重)]
-
zrevrange (逆序-降序,遍歷)
這條API就是多了 "rev" 三個(gè)字母, reversed單詞 熟悉把, python內(nèi)置逆序高階函數(shù)。。就是那個(gè)意思 操作同zrange,略
-
zrangebyscore (根據(jù)權(quán)重來遍歷)
R: zrangebyscore zset 40 99 limit 1 3 # 查出權(quán)重在40-99之內(nèi)的數(shù)據(jù),并從第1條開始,返回3條 # 40-99都是閉區(qū)間, 要想變成開區(qū)間這樣寫即可 (40 (99 P: print(redis.zrangebyscore('zset', 40, 99, start=1, num=3))
-
zrevrangebyscore (根據(jù)權(quán)重來 逆序遍歷)
操作同 zrangebyscore, 略 這API設(shè)計(jì)的,還不如,直接弄成一條命令,然后加一個(gè)逆序參數(shù),吐槽!!!!
-
zrem (刪除某值)
R: zrem zset Tom # 刪除Tom這個(gè)值 P: print(redis.zrem('zset','Tom'))
-
zremrangebyscore (刪除 權(quán)重 范圍內(nèi)的值)
R: zremrangebyscore zset 70 90 # 把權(quán)重在70-90分的所有數(shù)據(jù)刪除 P: redis.zremrangebyscore('zset', 70, 90)
-
zremrangebyrank (刪除 索引 范圍內(nèi)的值)
R: zremrangebyrank zset 0 -1 # 刪除所有值 ( 0到-1的索引就代表所有值啦!) P: redis.zremrangebyrank('zset', 0, -1) # redis的API風(fēng)格真的。。。沒辦法python也無奈同名
-
zcard (獲取有序集合的 所有 元素個(gè)數(shù))
R: zcard zset P: print(redis.zcard('zset'))
-
zcount (統(tǒng)計(jì)有序集合的 某權(quán)重范圍的 元素個(gè)數(shù))
R: zcount zset 10 69 # 同樣默認(rèn)閉區(qū)間, ( 可改為開區(qū)間 P: print(redis.zcount('zset',50, 69))
-
zrank (獲取某元素的索引)
R: zrank zset Jerry # 不用猜,索引肯定從0開始 P: print(redis.zrank('zset', 'Jerry'))
-
zrevrank (逆序 獲取某元素的索引)
逆序獲取索引,比如最后一個(gè),索引就是0 具體操作,同 zrank, 略
-
zscore (獲取某元素對(duì)應(yīng)的權(quán)重)
R: zscore zset Jerry P: print(redis.zscore('zset', 'Jerry'))
-
zscan (迭代方式和返回 所有元素及其權(quán)重)
""" 嗯?似曾相識(shí)燕歸來? 前面說過的 scan hsacn sscan 還有接下來要說的 zscan 都是一個(gè)樣子的,都是為了應(yīng)對(duì)大數(shù)據(jù)來迭代處理 python版的redis給了我們一個(gè)簡化函數(shù),那就是 _iter結(jié)尾的, eg: hscan_iter() 這種 _iter結(jié)尾的函數(shù),不用我們來傳游標(biāo)cursor參數(shù), 為啥呢?? 一. 因?yàn)閜ython有生成器-迭代器機(jī)制阿!(當(dāng)然 _iter等函數(shù)的源碼就是用yield為我們實(shí)現(xiàn)的) 二. cursor游標(biāo)不易于管理 """ R: zscan zset 0 match * count 5 P: zset_iter = redis.zscan_iter('zset', match='*', count=5) # 同理返回可迭代對(duì)象 注:還要說明一下: match參數(shù): 過濾查詢數(shù)據(jù)(其實(shí)過濾完了,數(shù)據(jù)量小了也沒必要用scan了,此參數(shù)主要用在"hscan"之類的) "因此match參數(shù)可不寫", "match='*' 和 不傳是一個(gè)效果的。" count參數(shù): Py源碼解釋 ``count`` allows for hint the minimum number of returns 意思就是: 這個(gè)參數(shù)是一次迭代"最少"取5個(gè)",但不管怎么說,最終還是會(huì)取出全部數(shù)據(jù)!!
-
zpopmax (彈出最大優(yōu)先級(jí)數(shù)據(jù)對(duì),redis5.+新增)
R: zpopmax zset1 2 # 2代表彈出最大的2對(duì)key:score,不寫,默認(rèn)只彈一對(duì)key:score P: data = redis.zpopmax(zset1, count=None) # 原理同上 zpopmax可等價(jià)于下面兩條命令的加起來的效果: data = redis.zrange(zset1, -1, -1) zrem(zset1, data) 注:無論count指定幾個(gè)或不指定,py返回值為 [(key, score)] 列表嵌元組這種格式。
-
zpopmin (彈出最小優(yōu)先級(jí)數(shù)據(jù)對(duì),redis5.+新增)
用法同zpopmax zpopmax可等價(jià)于下面兩條命令的加起來的效果: data = redis.zrange(zset1, 0, 0) # 就這里變了,默認(rèn)升序,故最小值需要從第0條開始彈 zrem(zset1, data) 注: zpopmax 和 zpopmin 這兩個(gè)方法是 redis5.+才有的。 前面也說了這種方法 = zrange + zrem 很明顯,由原來的多行操作。變成了原子操作。 我想,redis新增這兩條命令,應(yīng)該正是解決資源競爭的這一問題!!!!!!
Redis兩種持久化的方式
-
生成RDB文件 (三種方法)
"""RDB機(jī)制就是 觸發(fā)生成RDB文件,將Redis數(shù)據(jù)以二進(jìn)制形式寫入其中, 觸發(fā)方式有如下三種""" RDB基本配置: vi /etc/redis/redis.conf dbfilename dump.rdb # 配置RDB文件名 dir /var/lib/redis # 配置RDB文件存放目錄 (ll 命令查看 dump.rdb是否為最新時(shí)間) appendonly no # 若為yes, 會(huì)優(yōu)先按照aof文件來恢復(fù),或不恢復(fù) 上述配置,可在下面三種方法實(shí)現(xiàn)的時(shí)候,自動(dòng)觸發(fā)生成RDB文件。并在redis啟動(dòng)時(shí)恢復(fù)RDB文件
-
觸發(fā)方式1:save (阻塞)
R: save P: redis.save()
-
觸發(fā)方式2:bgsave (開fork進(jìn)程,異步,非阻塞)
R: bgsave P: redis.bgsave()
-
觸發(fā)方式3:自動(dòng)動(dòng)態(tài)生成RDB文件(配置文件)
在上面RDB基本配置基礎(chǔ)上,追加如下配置 vi /etc/redis/redis.conf save 100 10 # 100秒鐘改變10條數(shù)據(jù)就會(huì),自動(dòng)生成RDB文件
-
RDB缺點(diǎn)
大數(shù)據(jù)耗時(shí),RDB文件寫入影響IO性能。宕機(jī)數(shù)據(jù)不可控
-
生成AOF文件(三種方法)
"""AOF機(jī)制就是 每執(zhí)行一條命令,都會(huì)記錄到緩沖區(qū),在根據(jù)某種策略刷新到AOF文件中,策略有如下三種""" AOF基本配置: vi /etc/redis/redis.conf appendonly yes # 開關(guān),先要打開 appendfilename "appendonly.aof" # AOF文件名 dir /var/lib/redis # AOF文件目錄(和RDB是一樣的)
-
刷新策略1:always
always 即緩沖區(qū)有一條命令,就會(huì)刷新追加到AOF文件中 (安全可靠,耗IO)
-
刷新策略2:everysec (默認(rèn))
everysec 即每過1秒 就會(huì)把緩沖區(qū)的命令 刷新追加到AOF文件中 如果就在這一秒鐘宕機(jī),那么數(shù)據(jù)就丟失了。。。(1秒不可控)
-
刷新策略3:no
no 即 什么時(shí)候刷新,全聽操作系統(tǒng)自己的 (完全不可控)
-
AOF重寫機(jī)制 (兩種方法,異步)
-
重寫清潔過程:
如上可知,越來越多的命令會(huì)追加到AOF中,其中可能會(huì)有一些類似 一、鍵值覆蓋: set name tom set name jerry 二、超時(shí)時(shí)間過期 三、多條插入(可用一條命令代替) 如上無用命令,會(huì)讓AOF文件變得繁雜。 可通過 AOF重寫策略優(yōu)化來達(dá)到化簡,提高恢復(fù)速度等。
-
重寫原理(查找資料 + 個(gè)人理解):
一、 開fork子進(jìn)程 新弄一份AOF文件,它的任務(wù)就是把當(dāng)前redis中的數(shù)據(jù)重新按照上面的 ”重寫清潔過程“ 捋一遍,并記錄到這個(gè)新AOF文件中 二、 此時(shí)主進(jìn)程可以正常接受用戶的請(qǐng)求及修改,(這時(shí)可能子進(jìn)程AOF,和數(shù)據(jù)庫內(nèi)容不一致,往下看) 三、 其實(shí)---第一條開fork的時(shí)候,順便也開了一份內(nèi)存空間A(名為重寫緩沖區(qū)) 用來平行記錄 用戶新請(qǐng)求的命令 四、 當(dāng)子進(jìn)程AOF重寫完事后, 會(huì)把上面 空間A中 中的數(shù)據(jù)命令追加到 AOF中(類似斷點(diǎn)復(fù)制) 五、 新AOF替代 舊的AOF 打個(gè)比方(針對(duì)于 二、三、四): 就是,你給我一個(gè)任務(wù),我正做著,你又給我很多任務(wù),我當(dāng)然忙不過來 那這樣,你先拿個(gè)清單記錄下來,一會(huì)等我忙完了,咱們對(duì)接一下就好了)
-
重寫方式1:bgrewriteaof
R: bgrewriteaof P: redis.bgrewriteaof()
-
重寫方式2:配置文件實(shí)現(xiàn)自動(dòng)重寫
在上面AOF基本配置的基礎(chǔ)上,追加如下配置 vi /etc/redis/redis.conf appendfsync everysec # 就是上面說的三種策略,選一種 always no auto-aof-rewrite-min-size 64mb # 當(dāng)AOF文件超過64mb就會(huì)自動(dòng)重寫 auto-aof-rewrite-percentage 100 # 100為增長率, 每一次的限制大小是之前的100%,也就是二倍 no-appendfsync-on-rewrite yes # yes 就是不把 “重寫緩沖區(qū)” 的內(nèi)容 刷新到 磁盤 注意這個(gè)參數(shù): 這就是針對(duì)上面 ’重寫原理‘ 中的第三條 中的 內(nèi)存空間A(重寫緩沖區(qū)) 如果這個(gè) 重寫緩沖區(qū) 不刷新持久化到磁盤中, 要是宕機(jī)了,那么這個(gè)緩沖區(qū)的數(shù)據(jù)就會(huì)丟失。 丟失多少呢? 據(jù)悉(linux中 最多最多 會(huì)丟失 30秒的數(shù)據(jù)) 如果你將其 設(shè)置為 no,那么 重寫緩沖區(qū) 就會(huì)像 前面講的 原始AOF一樣地 刷新持久化到硬盤中。 但是你想想, 如果 重寫緩沖區(qū) 和 原始AOF 都做持久化刷新 那么 它們就會(huì) 競爭 IO,性能必定大打折扣,特殊情況下,還可能 堵塞。 so, 要性能(設(shè)為yes), 要數(shù)據(jù)完整安全(設(shè)為no), 自己選....
結(jié)束語
本文主要寫了關(guān)于 redis 以及 python操作redis的語法對(duì)比詳細(xì)解釋!!
python的redis API 也是非常夠意思了,函數(shù)名幾乎完全還原 原生Redis!!
語法部分印象比較深刻的就是 "redis的 scan家族函數(shù)" 以及 "python的 scan_iter"家族函數(shù):
上面陸陸續(xù)續(xù)講了那么多數(shù)據(jù)結(jié)構(gòu),都有它們各自的"遍歷所有數(shù)據(jù)的操作"
但對(duì)于大量數(shù)據(jù)的情況下, 這些遍歷函數(shù)就都變成渣渣了, 可能會(huì)造成"OOM(內(nèi)存溢出)等情況"
這時(shí) redis 機(jī)智的為我們 提供了一些列 "scan家族函數(shù)" , 當(dāng)然這些函數(shù)是都需要游標(biāo)控制的。
"游標(biāo)cursor"是比較頭疼的東西, 因此 python本著 人性化的思想:
將 "scan家族函數(shù)" 封裝為 "scan_iter家族函數(shù)", 讓我們省去了游標(biāo)的操作,可以愉快編程!
那我就列出全部大家族 以及 對(duì)應(yīng) 原始遍歷函數(shù):
原始遍歷 redis python
keys scan scan_iter
hgetall hscan hscan_iter
smembers sscan sscan_iter
zrange zscan zscan_iter
沿著這個(gè)對(duì)應(yīng)規(guī)律,之前我發(fā)現(xiàn)一件事情:
為什么 "list 的 lrange 沒有對(duì)應(yīng)的 lscan?"
我像zz一樣還去ov查了一遍, 居然還看到一位外國朋友和我有一樣的疑問。。。
解答者的一句話,我直接就清醒了, "Instead, you should use LRANGE to iterate the list"
由于順著規(guī)律,思維定勢,卻忘記了 "lrange本身就可以帶索引來迭代 " lrange list1 0 n
這時(shí)我突然又想起 zrange不也是和 lrange語法一樣么???
為何 zrange單獨(dú)設(shè)立了一個(gè) zscan, 而 list卻沒???
(查了一下好像是list底層性能之類的原因,我也沒愿意繼續(xù)看了。。。)
scan 與 iter家族函數(shù),各自的數(shù)據(jù)結(jié)構(gòu)章節(jié)都有寫, 并且在"zset"那節(jié)的 "zscan"那里做出了詳細(xì)的分析
END
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長非常感激您!手機(jī)微信長按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
