日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

《Redis开发与运维》- 核心知识整理二(Lua脚本、发布订阅、客户端等)

發(fā)布時(shí)間:2023/12/10 数据库 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 《Redis开发与运维》- 核心知识整理二(Lua脚本、发布订阅、客户端等) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

目錄

  • 1 事物
  • 2 Lua腳本
    • 2.1 Lua腳本的好處
    • 2.2 Lua腳本的使用
    • 2.3 script kill
  • 3 Bitmaps
    • 3.1 數(shù)據(jù)結(jié)構(gòu)模型
    • 3.2 Bitmaps的指令
    • 3.3 Bitmaps分析
  • 4 發(fā)布訂閱
    • 4.1 基本概念
    • 4.2 命令
    • 4.3 使用場(chǎng)景
  • 5 客戶端通信協(xié)議
  • 6 Java客戶端Jedis
    • 6.1 Jedis的基本使用方法
    • 6.2 Jedis連接池的使用方法
  • 7 客戶端API
    • 7.1 client list
    • 7.2 monitor
    • 7.3 客戶端相關(guān)配置

1 事物

Redis提供了簡(jiǎn)單的事務(wù)功能,將一組需要一起執(zhí)行的命令放到multi和exec兩個(gè)命令之間。multi命令代表事務(wù)開始,exec命令代表事務(wù)結(jié)束,它們之間的命令是原子順序執(zhí)行的,例如下面操作實(shí)現(xiàn)了上述用戶關(guān)注問題。

127.0.0.1:6379> multi OK 127.0.0.1:6379> sadd user:a:follow user:b QUEUED 127.0.0.1:6379> sadd user:b:fans user:a QUEUED

可以看到sadd命令此時(shí)的返回結(jié)果是QUEUED,代表命令并沒有真正執(zhí)行,而是暫時(shí)保存在Redis中。如果此時(shí)另一個(gè)客戶端執(zhí)行sismember user:a:follow user:b返回結(jié)果應(yīng)該為0。

127.0.0.1:6379> sismember user:a:follow user:b (integer) 0

只有當(dāng)exec執(zhí)行后,用戶A關(guān)注用戶B的行為才算完成,如下所示返回的兩個(gè)結(jié)果對(duì)應(yīng)sadd命令。

127.0.0.1:6379> exec 1) (integer) 1 2) (integer) 1 127.0.0.1:6379> sismember user:a:follow user:b (integer) 1

如果要停止事務(wù)的執(zhí)行,可以使用discard命令代替exec命令即可。

127.0.0.1:6379> discard OK 127.0.0.1:6379> sismember user:a:follow user:b (integer) 0

如果事務(wù)中的命令出現(xiàn)錯(cuò)誤,Redis的處理機(jī)制也不盡相同。

1.命令錯(cuò)誤

例如下面操作錯(cuò)將set寫成了sett,屬于語法錯(cuò)誤,會(huì)造成整個(gè)事務(wù)無法執(zhí)行,key和counter的值未發(fā)生變化:

127.0.0.1:6388> mget key counter 1) "hello" 2) "100" 127.0.0.1:6388> multi OK 127.0.0.1:6388> sett key world (error) ERR unknown command 'sett' 127.0.0.1:6388> incr counter QUEUED 127.0.0.1:6388> exec (error) EXECABORT Transaction discarded because of previous errors. 127.0.0.1:6388> mget key counter 1) "hello" 2) "100"

2.運(yùn)行時(shí)錯(cuò)誤

例如用戶B在添加粉絲列表時(shí),誤把sadd命令寫成了zadd命令,這種就是運(yùn)行時(shí)命令,因?yàn)檎Z法是正確的:

127.0.0.1:6379> multi OK 127.0.0.1:6379> sadd user:a:follow user:b QUEUED 127.0.0.1:6379> zadd user:b:fans 1 user:a QUEUED 127.0.0.1:6379> exec 1) (integer) 1 2) (error) WRONGTYPE Operation against a key holding the wrong kind of value 127.0.0.1:6379> sismember user:a:follow user:b (integer) 1

可以看到Redis并不支持回滾功能,sadd user:a:follow user:b命令已經(jīng)執(zhí)行成功,開發(fā)人員需要自己修復(fù)這類問題。 有些應(yīng)用場(chǎng)景需要在事務(wù)之前,確保事務(wù)中的key沒有被其他客戶端修改過,才執(zhí)行事務(wù),否則不執(zhí)行(類似樂觀鎖)。Redis提供了watch命令來解決這類問題,下表展示了兩個(gè)客戶端執(zhí)行命令的時(shí)序。

事務(wù)中watch命令演示時(shí)序

可以看到“客戶端-1”在執(zhí)行multi之前執(zhí)行了watch命令,“客戶端-2”在“客戶端-1”執(zhí)行exec之前修改了key值,造成事務(wù)沒有執(zhí)行(exec結(jié)果為nil),整個(gè)代碼如下所示:

#T1:客戶端1 127.0.0.1:6379> set key "java" OK #T2:客戶端1 127.0.0.1:6379> watch key OK #T3:客戶端1 127.0.0.1:6379> multi OK #T4:客戶端2 127.0.0.1:6379> append key python (integer) 11 #T5:客戶端1 127.0.0.1:6379> append key jedis QUEUED #T6:客戶端1 127.0.0.1:6379> exec (nil) #T7:客戶端1 127.0.0.1:6379> get key "javapython"

Redis提供了簡(jiǎn)單的事務(wù),之所以說它簡(jiǎn)單,主要是因?yàn)樗恢С质聞?wù)中的回滾特性,同時(shí)無法實(shí)現(xiàn)命令之間的邏輯關(guān)系計(jì)算,當(dāng)然也體現(xiàn)了Redis的“keep it simple”的特性,Lua腳本同樣可以實(shí)現(xiàn)事務(wù)的相關(guān)功能,但是功能要強(qiáng)大很多。

2 Lua腳本

2.1 Lua腳本的好處

Lua腳本功能為Redis開發(fā)和運(yùn)維人員帶來如下三個(gè)好處:
·Lua腳本在Redis中是原子執(zhí)行的,執(zhí)行過程中間不會(huì)插入其他命令。
·Lua腳本可以幫助開發(fā)和運(yùn)維人員創(chuàng)造出自己定制的命令,并可以將這些命令常駐在Redis內(nèi)存中,實(shí)現(xiàn)復(fù)用的效果。
·Lua腳本可以將多條命令一次性打包,有效地減少網(wǎng)絡(luò)開銷。

2.2 Lua腳本的使用

下面以一個(gè)例子說明Lua腳本的使用,當(dāng)前列表記錄著熱門用戶的id,假設(shè)這個(gè)列表有5個(gè)元素,如下所示:

127.0.0.1:6379> lrange hot:user:list 0 -1 1) "user:1:ratio" 2) "user:8:ratio" 3) "user:3:ratio" 4) "user:99:ratio" 5) "user:72:ratio"

user:{id}:ratio代表用戶的熱度,它本身又是一個(gè)字符串類型的鍵:

127.0.0.1:6379> mget user:1:ratio user:8:ratio user:3:ratio user:99:ratio user:72:ratio 1) "986" 2) "762" 3) "556" 4) "400" 5) "101"

現(xiàn)要求將列表內(nèi)所有的鍵對(duì)應(yīng)熱度做加1操作,并且保證是原子執(zhí)行,此功能可以利用Lua腳本來實(shí)現(xiàn)。

1)將列表中所有元素取出,賦值給mylist:

local mylist = redis.call("lrange", KEYS[1], 0, -1)

2)定義局部變量count=0,這個(gè)count就是最后incr的總次數(shù):

local count = 0

3)遍歷mylist中所有元素,每次做完count自增,最后返回count:

for index,key in ipairs(mylist) do redis.call("incr",key) count = count + 1 end return count

將上述腳本寫入lrange_and_mincr.lua文件中,并執(zhí)行如下操作,返回結(jié)果為5。

redis-cli --eval lrange_and_mincr.lua hot:user:list (integer) 5

執(zhí)行后所有用戶的熱度自增1:

127.0.0.1:6379> mget user:1:ratio user:8:ratio user:3:ratio user:99:ratio user:72:ratio 1) "987" 2) "763" 3) "557" 4) "401" 5) "102"

本節(jié)給出的只是一個(gè)簡(jiǎn)單的例子,在實(shí)際開發(fā)中,開發(fā)人員可以發(fā)揮自己的想象力創(chuàng)造出更多新的命令。

2.3 script kill

此命令用于殺掉正在執(zhí)行的Lua腳本。如果Lua腳本比較耗時(shí),甚至Lua腳本存在問題,那么此時(shí)Lua腳本的執(zhí)行會(huì)阻塞Redis,直到腳本執(zhí)行完畢或者外部進(jìn)行干預(yù)將其結(jié)束。下面我們模擬一個(gè)Lua腳本阻塞的情況進(jìn)行說明。下面的代碼會(huì)使Lua進(jìn)入死循環(huán):

while 1 == 1 do end

執(zhí)行Lua腳本,當(dāng)前客戶端會(huì)阻塞:

127.0.0.1:6379> eval 'while 1==1 do end' 0

Redis提供了一個(gè)lua-time-limit參數(shù),默認(rèn)是5秒,它是Lua腳本的“超時(shí)時(shí)間”,但這個(gè)超時(shí)時(shí)間僅僅是當(dāng)Lua腳本時(shí)間超過lua-time-limit后,向其他命令調(diào)用發(fā)送BUSY的信號(hào),但是并不會(huì)停止掉服務(wù)端和客戶端的腳本執(zhí)行,所以當(dāng)達(dá)到lua-time-limit值之后,其他客戶端在執(zhí)行正常的命令時(shí),將會(huì)收到“Busy Redis is busy running a script”錯(cuò)誤,并且提示使用script kill或shutdown nosave命令來殺掉這個(gè)busy的腳本:

127.0.0.1:6379> get hello (error) BUSY Redis is busy running a script. You can only call SCRIPT KILL or SHUTDOWN NOSAVE.

此時(shí)Redis已經(jīng)阻塞,無法處理正常的調(diào)用,這時(shí)可以選擇繼續(xù)等待,但更多時(shí)候需要快速將腳本殺掉。使用shutdown save顯然不太合適,所以選擇script kill,當(dāng)script kill執(zhí)行之后,客戶端調(diào)用會(huì)恢復(fù):

127.0.0.1:6379> script kill OK 127.0.0.1:6379> get hello "world"

但是有一點(diǎn)需要注意,如果當(dāng)前Lua腳本正在執(zhí)行寫操作,那么script kill將不會(huì)生效。例如,我們模擬一個(gè)不停的寫操作:

while 1==1 do redis.call("set","k","v") end

此時(shí)如果執(zhí)行script kill,會(huì)收到如下異常信息:

(error) UNKILLABLE Sorry the script already executed write commands against the dataset. You can either wait the script termination or kill the server in a hard way using the SHUTDOWN NOSAVE command.

上面提示Lua腳本正在向Redis執(zhí)行寫命令,要么等待腳本執(zhí)行結(jié)束要么使用shutdown save停掉Redis服務(wù)。可見Lua腳本雖然好用,但是使用不當(dāng)破壞性也是難以想象的。

3 Bitmaps

3.1 數(shù)據(jù)結(jié)構(gòu)模型

許多開發(fā)語言都提供了操作位的功能,合理地使用位能夠有效地提高內(nèi)存使用率和開發(fā)效率。Redis提供了Bitmaps這個(gè)“數(shù)據(jù)結(jié)構(gòu)”可以實(shí)現(xiàn)對(duì)位的操作。把數(shù)據(jù)結(jié)構(gòu)加上引號(hào)主要因?yàn)?#xff1a;
·Bitmaps本身不是一種數(shù)據(jù)結(jié)構(gòu),實(shí)際上它就是字符串(如下圖所示),但是它可以對(duì)字符串的位進(jìn)行操作。
·Bitmaps單獨(dú)提供了一套命令,所以在Redis中使用Bitmaps和使用字符串的方法不太相同。可以把Bitmaps想象成一個(gè)以位為單位的數(shù)組,數(shù)組的每個(gè)單元只能存儲(chǔ)0和1,數(shù)組的下標(biāo)在Bitmaps中叫做偏移量。

字符串"big"用二進(jìn)制表示

3.2 Bitmaps的指令

本節(jié)將每個(gè)獨(dú)立用戶是否訪問過網(wǎng)站存放在Bitmaps中,將訪問的用戶記做1,沒有訪問的用戶記做0,用偏移量作為用戶的id。

1.設(shè)置值

setbit key offset value

設(shè)置鍵的第offset個(gè)位的值(從0算起),假設(shè)現(xiàn)在有20個(gè)用戶, userid=0,5,11,15,19的用戶對(duì)網(wǎng)站進(jìn)行了訪問,那么當(dāng)前Bitmaps初始化結(jié)果如圖所示。

setbit使用

具體操作過程如下,unique:users:2016-04-05代表2016-04-05這天的獨(dú)立訪問用戶的Bitmaps:

127.0.0.1:6379> setbit unique:users:2016-04-05 0 1 (integer) 0 127.0.0.1:6379> setbit unique:users:2016-04-05 5 1 (integer) 0 127.0.0.1:6379> setbit unique:users:2016-04-05 11 1 (integer) 0 127.0.0.1:6379> setbit unique:users:2016-04-05 15 1 (integer) 0 127.0.0.1:6379> setbit unique:users:2016-04-05 19 1 (integer) 0

如果此時(shí)有一個(gè)userid=50的用戶訪問了網(wǎng)站,那么Bitmaps的結(jié)構(gòu)變成了下圖所示,第20位~49位都是0。

userid=50用戶訪問

很多應(yīng)用的用戶id以一個(gè)指定數(shù)字(例如10000)開頭,直接將用戶id和Bitmaps的偏移量對(duì)應(yīng)勢(shì)必會(huì)造成一定的浪費(fèi),通常的做法是每次做setbit操作時(shí)將用戶id減去這個(gè)指定數(shù)字。在第一次初始化Bitmaps時(shí),假如偏移量非常大,那么整個(gè)初始化過程執(zhí)行會(huì)比較慢,可能會(huì)造成Redis的阻塞。

2.獲取值

getbit key offset

獲取鍵的第offset位的值(從0開始算),下面操作獲取id=8的用戶是否在2016-04-05這天訪問過,返回0說明沒有訪問過:

127.0.0.1:6379> getbit unique:users:2016-04-05 8 (integer) 0

由于offset=1000000根本就不存在,所以返回結(jié)果也是0:

127.0.0.1:6379> getbit unique:users:2016-04-05 1000000 (integer) 0

3.獲取Bitmaps指定范圍值為1的個(gè)數(shù)

bitcount [start][end]

下面操作計(jì)算2016-04-05這天的獨(dú)立訪問用戶數(shù)量:

127.0.0.1:6379> bitcount unique:users:2016-04-05 (integer) 5

[start]和[end]代表起始和結(jié)束字節(jié)數(shù),下面操作計(jì)算用戶id在第1個(gè)字節(jié)到第3個(gè)字節(jié)之間的獨(dú)立訪問用戶數(shù),對(duì)應(yīng)的用戶id是11,15,19。

127.0.0.1:6379> bitcount unique:users:2016-04-05 1 3 (integer) 3

4.Bitmaps間的運(yùn)算

bitop op destkey key[key....]

bitop是一個(gè)復(fù)合操作,它可以做多個(gè)Bitmaps的and(交集)、or(并集)、not(非)、xor(異或)操作并將結(jié)果保存在destkey中。假設(shè)2016-04-04訪問網(wǎng)站的userid=1,2,5,9,如圖所示。

2016-04-04訪問網(wǎng)站的用戶Bitmaps

下面操作計(jì)算出2016-04-04和2016-04-03兩天都訪問過網(wǎng)站的用戶數(shù)量,如圖所示。

127.0.0.1:6379> bitop and unique:users:and:2016-04-04_03 unique: users:2016-04-03 unique:users:2016-04-03 (integer) 2 127.0.0.1:6379> bitcount unique:users:and:2016-04-04_03 (integer) 2

如果想算出2016-04-04和2016-04-03任意一天都訪問過網(wǎng)站的用戶數(shù)量(例如月活躍就是類似這種),可以使用or求并集,具體命令如下:

127.0.0.1:6379> bitop or unique:users:or:2016-04-04_03 unique: users:2016-04-03 unique:users:2016-04-03 (integer) 2 127.0.0.1:6379> bitcount unique:users:or:2016-04-04_03 (integer) 6


利用bitop and命令計(jì)算兩天都訪問網(wǎng)站的用戶

3.3 Bitmaps分析

假設(shè)網(wǎng)站有1億用戶,每天獨(dú)立訪問的用戶有5千萬,如果每天用集合類型和Bitmaps分別存儲(chǔ)活躍用戶可以得到下表:

set和Bitmaps存儲(chǔ)一天活躍用戶的對(duì)比

很明顯,這種情況下使用Bitmaps能節(jié)省很多的內(nèi)存空間。但Bitmaps并不是萬金油,假如該網(wǎng)站每天的獨(dú)立訪問用戶很少,例如只有10萬(大量的僵尸用戶),那么兩者的對(duì)比如下表所示,很顯然,這時(shí)候使用Bitmaps就不太合適了,因?yàn)榛旧洗蟛糠治欢际?。

set和Bitmaps存儲(chǔ)一天活躍用戶的對(duì)比(獨(dú)立用戶比較少)

4 發(fā)布訂閱

4.1 基本概念

Redis提供了基于“發(fā)布/訂閱”模式的消息機(jī)制,此種模式下,消息發(fā)布者和訂閱者不進(jìn)行直接通信,發(fā)布者客戶端向指定的頻道(channel)發(fā)布消息,訂閱該頻道的每個(gè)客戶端都可以收到該消息,如圖所示。Redis提供了若干命令支持該功能,在實(shí)際應(yīng)用開發(fā)時(shí),能夠?yàn)榇祟悊栴}提供實(shí)現(xiàn)方法。

Redis發(fā)布訂閱模型

4.2 命令

Redis主要提供了發(fā)布消息、訂閱頻道、取消訂閱以及按照模式訂閱和取消訂閱等命令。

1.發(fā)布消息

publish channel message

下面操作會(huì)向channel:sports頻道發(fā)布一條消息“Tim won the championship”,返回結(jié)果為訂閱者個(gè)數(shù),因?yàn)榇藭r(shí)沒有訂閱,所以返回結(jié)果為0:

127.0.0.1:6379> publish channel:sports "Tim won the championship" (integer) 0

2.訂閱消息

subscribe channel [channel ...]

訂閱者可以訂閱一個(gè)或多個(gè)頻道,下面操作為當(dāng)前客戶端訂閱了 channel:sports頻道:

127.0.0.1:6379> subscribe channel:sports Reading messages... (press Ctrl-C to quit) 1) "subscribe" 2) "channel:sports" 3) (integer) 1

此時(shí)另一個(gè)客戶端發(fā)布一條消息:

127.0.0.1:6379> publish channel:sports "James lost the championship" (integer) 1

當(dāng)前訂閱者客戶端會(huì)收到如下消息:

127.0.0.1:6379> subscribe channel:sports Reading messages... (press Ctrl-C to quit) ... 1) "message" 2) "channel:sports" 3) "James lost the championship"

如果有多個(gè)客戶端同時(shí)訂閱了channel:sports,整個(gè)過程如圖3-17所示。有關(guān)訂閱命令有兩點(diǎn)需要注意:
·客戶端在執(zhí)行訂閱命令之后進(jìn)入了訂閱狀態(tài),只能接收subscribe、psubscribe、unsubscribe、punsubscribe的四個(gè)命令。
·新開啟的訂閱客戶端,無法收到該頻道之前的消息,因?yàn)镽edis不會(huì)對(duì)發(fā)布的消息進(jìn)行持久化。

多個(gè)客戶端同時(shí)訂閱頻道channel:sports

開發(fā)提示
和很多專業(yè)的消息隊(duì)列系統(tǒng)(例如Kafka、RocketMQ)相比,Redis的發(fā)布訂閱略顯粗糙,例如無法實(shí)現(xiàn)消息堆積和回溯。但勝在足夠簡(jiǎn)單,如果當(dāng)前場(chǎng)景可以容忍的這些缺點(diǎn),也不失為一個(gè)不錯(cuò)的選擇。

3.取消訂閱

unsubscribe [channel [channel ...]]

客戶端可以通過unsubscribe命令取消對(duì)指定頻道的訂閱,取消成功后,不會(huì)再收到該頻道的發(fā)布消息:

127.0.0.1:6379> unsubscribe channel:sports 1) "unsubscribe" 2) "channel:sports" 3) (integer) 0

4.3 使用場(chǎng)景

聊天室、公告牌、服務(wù)之間利用消息解耦都可以使用發(fā)布訂閱模式,下面以簡(jiǎn)單的服務(wù)解耦進(jìn)行說明。如圖所示,圖中有兩套業(yè)務(wù),上面為視頻管理系統(tǒng),負(fù)責(zé)管理視頻信息;下面為視頻服務(wù)面向客戶,用戶可以通過各種客戶端(手機(jī)、瀏覽器、接口)獲取到視頻信息。

發(fā)布訂閱用于視頻信息變化通知

假如視頻管理員在視頻管理系統(tǒng)中對(duì)視頻信息進(jìn)行了變更,希望及時(shí)通知給視頻服務(wù)端,就可以采用發(fā)布訂閱的模式,發(fā)布視頻信息變化的消息到指定頻道,視頻服務(wù)訂閱這個(gè)頻道及時(shí)更新視頻信息,通過這種方式可以有效解決兩個(gè)業(yè)務(wù)的耦合性。
·視頻服務(wù)訂閱video:changes頻道如下:

subscribe video:changes

·視頻管理系統(tǒng)發(fā)布消息到video:changes頻道如下:

publish video:changes "video1,video3,video5"

·當(dāng)視頻服務(wù)收到消息,對(duì)視頻信息進(jìn)行更新,如下所示:

for video in video1,video3,video5 update {video}

5 客戶端通信協(xié)議

幾乎所有的主流編程語言都有Redis的客戶端, 不考慮Redis非常流行的原因,如果站在技術(shù)的角度看原因還有兩個(gè):
第一,客戶端與服務(wù)端之間的通信協(xié)議是在TCP協(xié)議之上構(gòu)建的。
第二,Redis制定了RESP(REdis Serialization Protocol,Redis序列化協(xié)議)實(shí)現(xiàn)客戶端與服務(wù)端的正常交互,這種協(xié)議簡(jiǎn)單高效,既能夠被機(jī)器解析,又容易被人類識(shí)別。例如客戶端發(fā)送一條set hello world命令給服務(wù)端,按照RESP的標(biāo)準(zhǔn),客戶端需要將其封裝為如下格式(每行用\r\n分隔):

*3 $3 SET $5 hello $5 world

這樣Redis服務(wù)端能夠按照RESP將其解析為set hello world命令,執(zhí)行后回復(fù)的格式如下:

+OK

可以看到除了命令(set hello world)和返回結(jié)果(OK)本身還包含了一些特殊字符以及數(shù)字,下面將對(duì)這些格式進(jìn)行說明。

1.發(fā)送命令格式
RESP的規(guī)定一條命令的格式如下,CRLF代表"\r\n"。

*<參數(shù)數(shù)量> CRLF $<參數(shù)1的字節(jié)數(shù)量> CRLF <參數(shù)1> CRLF ... $<參數(shù)N的字節(jié)數(shù)量> CRLF <參數(shù)N> CRLF

依然以set hell world這條命令進(jìn)行說明。 參數(shù)數(shù)量為3個(gè),因此第一行為:

*3

參數(shù)字節(jié)數(shù)分別是355,因此后面幾行為:

$3 SET $5 hello $5 world

有一點(diǎn)要注意的是,上面只是格式化顯示的結(jié)果,實(shí)際傳輸格式為如下代碼,整個(gè)過程如圖所示:

*3\r\n$3\r\nSET\r\n$5\r\nhello\r\n$5\r\nworld\r\n

2.返回結(jié)果格式
Redis的返回結(jié)果類型分為以下五種,如下圖所示:
·狀態(tài)回復(fù):在RESP中第一個(gè)字節(jié)為"+“。
·錯(cuò)誤回復(fù):在RESP中第一個(gè)字節(jié)為”-“。
·整數(shù)回復(fù):在RESP中第一個(gè)字節(jié)為”:“。
·字符串回復(fù):在RESP中第一個(gè)字節(jié)為”$“。
·多條字符串回復(fù):在RESP中第一個(gè)字節(jié)為”*"。

客戶端和服務(wù)端使用RESP標(biāo)準(zhǔn)進(jìn)行數(shù)據(jù)交互

Redis五種回復(fù)類型在RESP下的編碼

6 Java客戶端Jedis

Java有很多優(yōu)秀的Redis客戶端(詳見:http://redis.io/clients#java),這里介紹使用較為廣泛的客戶端Jedis。

6.1 Jedis的基本使用方法

Jedis的使用方法非常簡(jiǎn)單,只要下面三行代碼就可以實(shí)現(xiàn)get功能:

# 1. 生成一個(gè)Jedis對(duì)象,這個(gè)對(duì)象負(fù)責(zé)和指定Redis實(shí)例進(jìn)行通信 Jedis jedis = new Jedis("127.0.0.1", 6379); # 2. jedis執(zhí)行set操作 jedis.set("hello", "world"); # 3. jedis執(zhí)行g(shù)et操作, value="world" String value = jedis.get("hello");

可以看到初始化Jedis需要兩個(gè)參數(shù):Redis實(shí)例的IP和端口,除了這兩個(gè)參數(shù)外,還有一個(gè)包含了四個(gè)參數(shù)的構(gòu)造函數(shù)是比較常用的:

Jedis(final String host, final int port, final int connectionTimeout, final int soTimeout)

參數(shù)說明:
·host:Redis實(shí)例的所在機(jī)器的IP。
·port:Redis實(shí)例的端口。
·connectionTimeout:客戶端連接超時(shí)。
·soTimeout:客戶端讀寫超時(shí)。

如果想看一下執(zhí)行結(jié)果:

String setResult = jedis.set("hello", "world"); String getResult = jedis.get("hello"); System.out.println(setResult); System.out.println(getResult);

輸出結(jié)果為:

OK world

可以看到j(luò)edis.set的返回結(jié)果是OK,和redis-cli的執(zhí)行效果是一樣的,只不過結(jié)果類型變?yōu)榱薐ava的數(shù)據(jù)類型。上面的這種寫法只是為了演示使用,在實(shí)際項(xiàng)目中比較推薦使用try catch finally的形式來進(jìn)行代碼的書寫:一方面可以在Jedis出現(xiàn)異常的時(shí)候(本身是網(wǎng)絡(luò)操作),將異常進(jìn)行捕獲或者拋出;另一個(gè)方面無論執(zhí)行成功或者失敗,將Jedis連接關(guān)閉掉,在開發(fā)中關(guān)閉不用的連接資源是一種好的習(xí)慣,代碼類似如下:

Jedis jedis = null; try {jedis = new Jedis("127.0.0.1", 6379); jedis.get("hello"); } catch (Exception e) { logger.error(e.getMessage(),e); } finally { if (jedis != null) { jedis.close(); } }

下面用一個(gè)例子說明Jedis對(duì)于Redis五種數(shù)據(jù)結(jié)構(gòu)的操作,為了節(jié)省篇幅,所有返回結(jié)果放在注釋中。

// 1.string // 輸出結(jié)果:OK jedis.set("hello", "world"); // 輸出結(jié)果:world jedis.get("hello"); // 輸出結(jié)果:1 jedis.incr("counter"); // 2.hash jedis.hset("myhash", "f1", "v1"); jedis.hset("myhash", "f2", "v2"); // 輸出結(jié)果:{f1=v1, f2=v2} jedis.hgetAll("myhash"); // 3.list jedis.rpush("mylist", "1"); jedis.rpush("mylist", "2"); jedis.rpush("mylist", "3"); // 輸出結(jié)果:[1, 2, 3] jedis.lrange("mylist", 0, -1); // 4.set jedis.sadd("myset", "a"); jedis.sadd("myset", "b"); jedis.sadd("myset", "a"); // 輸出結(jié)果:[b, a] jedis.smembers("myset"); // 5.zset jedis.zadd("myzset", 99, "tom"); jedis.zadd("myzset", 66, "peter"); jedis.zadd("myzset", 33, "james"); // 輸出結(jié)果:[[["james"],33.0], [["peter"],66.0], [["tom"],99.0]] jedis.zrangeWithScores("myzset", 0, -1);

參數(shù)除了可以是字符串,Jedis還提供了字節(jié)數(shù)組的參數(shù),例如:

public String set(final String key, String value) public String set(final byte[] key, final byte[] value) public byte[] get(final byte[] key) public String get(final String key)

有了這些API的支持,就可以將Java對(duì)象序列化為二進(jìn)制,當(dāng)應(yīng)用需要獲取Java對(duì)象時(shí),使用get(final byte[]key)函數(shù)將字節(jié)數(shù)組取出,然后反序列化為Java對(duì)象即可。和很多NoSQL數(shù)據(jù)庫(例如Memcache、Ehcache)的客戶端不同,Jedis本身沒有提供序列化的工具,也就是說開發(fā)者需要自己引入序列化的工具。序列化的工具有很多,例如XML、Json、谷歌的Protobuf、Facebook的Thrift等等,對(duì)于序列化工具的選擇開發(fā)者可以根據(jù)自身需求決定。

6.2 Jedis連接池的使用方法

之前介紹的是Jedis的直連方式,所謂直連是指Jedis每次都會(huì)新建TCP連接,使用后再斷開連接,對(duì)于頻繁訪問Redis的場(chǎng)景顯然不是高效的使用方式,如圖所示。

Jedis直連Redis

因此生產(chǎn)環(huán)境中一般使用連接池的方式對(duì)Jedis連接進(jìn)行管理,如圖所示,所有Jedis對(duì)象預(yù)先放在池子中(JedisPool),每次要連接Redis,只需要在池子中借,用完了在歸還給池子。

Jedis連接池使用方式

客戶端連接Redis使用的是TCP協(xié)議,直連的方式每次需要建立TCP連接,而連接池的方式是可以預(yù)先初始化好Jedis連接,所以每次只需要從Jedis連接池借用即可,而借用和歸還操作是在本地進(jìn)行的,只有少量的并發(fā)同步開銷,遠(yuǎn)遠(yuǎn)小于新建TCP連接的開銷。另外直連的方式無法限制Jedis對(duì)象的個(gè)數(shù),在極端情況下可能會(huì)造成連接泄露,而連接池的形式可以有效的保護(hù)和控制資源的使用。但是直連的方式也并不是一無是處,下表給出兩種方式各自的優(yōu)劣勢(shì)。

Jedis直連方式和連接池方式對(duì)比

Jedis提供了JedisPool這個(gè)類作為對(duì)Jedis的連接池,同時(shí)使用了Apache的通用對(duì)象池工具common-pool作為資源的管理工具,下面是使用JedisPool操作Redis的代碼示例:
1)Jedis連接池(通常JedisPool是單例的):

// common-pool連接池配置,這里使用默認(rèn)配置,后面小節(jié)會(huì)介紹具體配置說明 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // 初始化Jedis連接池 JedisPool jedisPool = new JedisPool(poolConfig, "127.0.0.1", 6379);

2)獲取Jedis對(duì)象不再是直接生成一個(gè)Jedis對(duì)象進(jìn)行直連,而是從連接池直接獲取,代碼如下:

Jedis jedis = null; try {// 1. 從連接池獲取jedis對(duì)象 jedis = jedisPool.getResource(); // 2. 執(zhí)行操作 jedis.get("hello"); } catch (Exception e) { logger.error(e.getMessage(),e); } finally { if (jedis != null) { // 如果使用JedisPool,close操作不是關(guān)閉連接,代表歸還連接池 jedis.close(); } }

這里可以看到在finally中依然是jedis.close()操作,為什么會(huì)把連接關(guān)閉呢,這不和連接池的原則違背了嗎?但實(shí)際上Jedis的close()實(shí)現(xiàn)方式如下:

public void close() { // 使用Jedis連接池 if (dataSource != null) { if (client.isBroken()) { this.dataSource.returnBrokenResource(this); } else { this.dataSource.returnResource(this); } // 直連 } else { client.close(); } }

參數(shù)說明:
·dataSource!=null代表使用的是連接池,所以jedis.close()代表歸還連接給連接池,而且Jedis會(huì)判斷當(dāng)前連接是否已經(jīng)斷開。
·dataSource=null代表直連,jedis.close()代表關(guān)閉連接。
前面GenericObjectPoolConfig使用的是默認(rèn)配置,實(shí)際它提供有很多參數(shù),例如池子中最大連接數(shù)、最大空閑連接數(shù)、最小空閑連接數(shù)、連接活性檢測(cè),等等,例如下面代碼:

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); // 設(shè)置最大連接數(shù)為默認(rèn)值的5倍 poolConfig.setMaxTotal(GenericObjectPoolConfig.DEFAULT_MAX_TOTAL * 5); // 設(shè)置最大空閑連接數(shù)為默認(rèn)值的3倍 poolConfig.setMaxIdle(GenericObjectPoolConfig.DEFAULT_MAX_IDLE * 3); // 設(shè)置最小空閑連接數(shù)為默認(rèn)值的2倍 poolConfig.setMinIdle(GenericObjectPoolConfig.DEFAULT_MIN_IDLE * 2); // 設(shè)置開啟jmx功能 poolConfig.setJmxEnabled(true); // 設(shè)置連接池沒有連接后客戶端的最大等待時(shí)間(單位為毫秒) poolConfig.setMaxWaitMillis(3000);

上面幾個(gè)是GenericObjectPoolConfig幾個(gè)比較常用的屬性,下表給出了Generic-ObjectPoolConfig其他屬性及其含義解釋。

GenericObjectPoolConfig的重要屬性

7 客戶端API

7.1 client list

client list命令能列出與Redis服務(wù)端相連的所有客戶端連接信息,例如下面代碼是在一個(gè)Redis實(shí)例上執(zhí)行client list的結(jié)果:

127.0.0.1:6379> client list id=254487 addr=10.2.xx.234:60240 fd=1311 name= age=8888581 idle=8888581 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get id=300210 addr=10.2.xx.215:61972 fd=3342 name= age=8054103 idle=8054103 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get id=5448879 addr=10.16.xx.105:51157 fd=233 name= age=411281 idle=331077 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ttl id=2232080 addr=10.16.xx.55:32886 fd=946 name= age=603382 idle=331060 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get id=7125108 addr=10.10.xx.103:33403 fd=139 name= age=241 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=del id=7125109 addr=10.10.xx.101:58658 fd=140 name= age=241 idle=1 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=del ...

輸出結(jié)果的每一行代表一個(gè)客戶端的信息,可以看到每行包含了十幾個(gè)屬性,它們是每個(gè)客戶端的一些執(zhí)行狀態(tài),理解這些屬性對(duì)于Redis的開發(fā)和運(yùn)維人員非常有幫助。下面將選擇幾個(gè)重要的屬性進(jìn)行說明,其余通過表格的形式進(jìn)行展示。
(1)標(biāo)識(shí):id、addr、fd、name
這四個(gè)屬性屬于客戶端的標(biāo)識(shí):
·id:客戶端連接的唯一標(biāo)識(shí),這個(gè)id是隨著Redis的連接自增的,重啟Redis后會(huì)重置為0。
·addr:客戶端連接的ip和端口。
·fd:socket的文件描述符,與lsof命令結(jié)果中的fd是同一個(gè),如果fd=-1 代表當(dāng)前客戶端不是外部客戶端,而是Redis內(nèi)部的偽裝客戶端。
·name:客戶端的名字,后面的client setName和client getName兩個(gè)命令會(huì)對(duì)其進(jìn)行說明。
(2)輸入緩沖區(qū):qbuf、qbuf-free
Redis為每個(gè)客戶端分配了輸入緩沖區(qū),它的作用是將客戶端發(fā)送的命令臨時(shí)保存,同時(shí)Redis從會(huì)輸入緩沖區(qū)拉取命令并執(zhí)行,輸入緩沖區(qū)為客戶端發(fā)送命令到Redis執(zhí)行命令提供了緩沖功能,如圖所示。
client list中qbuf和qbuf-free分別代表這個(gè)緩沖區(qū)的總?cè)萘亢褪S嗳萘?#xff0c;Redis沒有提供相應(yīng)的配置來規(guī)定每個(gè)緩沖區(qū)的大小,輸入緩沖區(qū)會(huì)根據(jù)輸入內(nèi)容大小的不同動(dòng)態(tài)調(diào)整,只是要求每個(gè)客戶端緩沖區(qū)的大小不能超過1G,超過后客戶端將被關(guān)閉。下面是Redis源碼中對(duì)于輸入緩沖區(qū)的硬編碼:

輸入緩沖區(qū)基本模型

/* Protocol and I/O related defines */ #define REDIS_MAX_QUERYBUF_LEN (1024*1024*1024) /* 1GB max query buffer. */

輸入緩沖使用不當(dāng)會(huì)產(chǎn)生兩個(gè)問題:
·一旦某個(gè)客戶端的輸入緩沖區(qū)超過1G,客戶端將會(huì)被關(guān)閉。
·輸入緩沖區(qū)不受maxmemory控制,假設(shè)一個(gè)Redis實(shí)例設(shè)置了 maxmemory為4G,已經(jīng)存儲(chǔ)了2G數(shù)據(jù),但是如果此時(shí)輸入緩沖區(qū)使用了3G,已經(jīng)超過maxmemory限制,可能會(huì)產(chǎn)生數(shù)據(jù)丟失、鍵值淘汰、OOM等情況(如圖所示)。

輸入緩沖區(qū)超過了maxmemory

執(zhí)行效果如下:

127.0.0.1:6390> info memory # Memory used_memory_human:5.00G ... maxmemory_human:4.00G ....

上面已經(jīng)看到,輸入緩沖區(qū)使用不當(dāng)造成的危害非常大,那么造成輸入緩沖區(qū)過大的原因有哪些?輸入緩沖區(qū)過大主要是因?yàn)镽edis的處理速度跟不上輸入緩沖區(qū)的輸入速度,并且每次進(jìn)入輸入緩沖區(qū)的命令包含了大量bigkey,從而造成了輸入緩沖區(qū)過大的情況。還有一種情況就是Redis發(fā)生了阻塞,短期內(nèi)不能處理命令,造成客戶端輸入的命令積壓在了輸入緩沖區(qū), 造成了輸入緩沖區(qū)過大。那么如何快速發(fā)現(xiàn)和監(jiān)控呢?監(jiān)控輸入緩沖區(qū)異常的方法有兩種:
·通過定期執(zhí)行client list命令,收集qbuf和qbuf-free找到異常的連接記錄并分析,最終找到可能出問題的客戶端。
·通過info命令的info clients模塊,找到最大的輸入緩沖區(qū),例如下面命令中的其中client_biggest_input_buf代表最大的輸入緩沖區(qū),例如可以設(shè)置超過10M就進(jìn)行報(bào)警:

127.0.0.1:6379> info clients # Clients connected_clients:1414 client_longest_output_list:0 client_biggest_input_buf:2097152 blocked_clients:0

這兩種方法各有自己的優(yōu)劣勢(shì),下表對(duì)兩種方法進(jìn)行了對(duì)比。

對(duì)比client list和info clients監(jiān)控輸入緩沖區(qū)的優(yōu)劣勢(shì)

運(yùn)維提示
輸入緩沖區(qū)問題出現(xiàn)概率比較低,但是也要做好防范,在開發(fā)中要減少bigkey、減少Redis阻塞、合理的監(jiān)控報(bào)警。

(3)輸出緩沖區(qū):obl、oll、omem
Redis為每個(gè)客戶端分配了輸出緩沖區(qū),它的作用是保存命令執(zhí)行的結(jié)果返回給客戶端,為Redis和客戶端交互返回結(jié)果提供緩沖,如圖所示。與輸入緩沖區(qū)不同的是,輸出緩沖區(qū)的容量可以通過參數(shù)client-output-buffer-limit來進(jìn)行設(shè)置,并且輸出緩沖區(qū)做得更加細(xì)致,按照客戶端的不同分為三種:普通客戶端、發(fā)布訂閱客戶端、slave客戶端,如圖所示。

客戶端輸出緩沖區(qū)模型


三種不同類型客戶端的輸出緩沖區(qū)

對(duì)應(yīng)的配置規(guī)則是:

client-output-buffer-limit <class> <hard limit> <soft limit> <soft seconds>

·class:客戶端類型,分為三種。a)normal:普通客戶端;b) slave:slave客戶端,用于復(fù)制;c)pubsub:發(fā)布訂閱客戶端。
·hard limit:如果客戶端使用的輸出緩沖區(qū)大于,客戶端會(huì)被立即關(guān)閉。
·soft limit和soft seconds:如果客戶端使用的輸出緩沖區(qū)超過了并且持續(xù)了秒,客戶端會(huì)被立即關(guān)閉。

Redis的默認(rèn)配置是:

client-output-buffer-limit normal 0 0 0 client-output-buffer-limit slave 256mb 64mb 60 client-output-buffer-limit pubsub 32mb 8mb 60

和輸入緩沖區(qū)相同的是,輸出緩沖區(qū)也不會(huì)受到maxmemory的限制,如果使用不當(dāng)同樣會(huì)造成maxmemory用滿產(chǎn)生的數(shù)據(jù)丟失、鍵值淘汰、OOM等情況。

監(jiān)控輸出緩沖區(qū)的方法依然有兩種:
·通過定期執(zhí)行client list命令,收集obl、oll、omem找到異常的連接記錄并分析,最終找到可能出問題的客戶端。
·通過info命令的info clients模塊,找到輸出緩沖區(qū)列表最大對(duì)象數(shù),例如:

127.0.0.1:6379> info clients # Clients connected_clients:502 client_longest_output_list:4869 client_biggest_input_buf:0 blocked_clients:0

其中,client_longest_output_list代表輸出緩沖區(qū)列表最大對(duì)象數(shù),這兩種統(tǒng)計(jì)方法的優(yōu)劣勢(shì)和輸入緩沖區(qū)是一樣的,這里就不再贅述了。相比于輸入緩沖區(qū),輸出緩沖區(qū)出現(xiàn)異常的概率相對(duì)會(huì)比較大,那么如何預(yù)防呢?方法如下:
·進(jìn)行上述監(jiān)控,設(shè)置閥值,超過閥值及時(shí)處理。
·限制普通客戶端輸出緩沖區(qū)的,把錯(cuò)誤扼殺在搖籃中,例如可以進(jìn)行如下設(shè)置:

client-output-buffer-limit normal 20mb 10mb 120

·適當(dāng)增大slave的輸出緩沖區(qū)的,如果master節(jié)點(diǎn)寫入較大,slave客戶端的輸出緩沖區(qū)可能會(huì)比較大,一旦slave客戶端連接因?yàn)檩敵鼍彌_區(qū)溢出被kill,會(huì)造成復(fù)制重連。
·限制容易讓輸出緩沖區(qū)增大的命令,例如,高并發(fā)下的monitor命令就是一個(gè)危險(xiǎn)的命令。
·及時(shí)監(jiān)控內(nèi)存,一旦發(fā)現(xiàn)內(nèi)存抖動(dòng)頻繁,可能就是輸出緩沖區(qū)過大。

(4)客戶端的存活狀態(tài)
client list中的age和idle分別代表當(dāng)前客戶端已經(jīng)連接的時(shí)間和最近一次的空閑時(shí)間:

id=2232080 addr=10.16.xx.55:32886 fd=946 name= age=603382 idle=331060 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get

例如上面這條記錄代表當(dāng)期客戶端連接Redis的時(shí)間為603382秒,其中空閑了331060秒:

id=254487 addr=10.2.xx.234:60240 fd=1311 name= age=8888581 idle=8888581 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get

例如上面這條記錄代表當(dāng)期客戶端連接Redis的時(shí)間為8888581秒,其中空閑了8888581秒,實(shí)際上這種就屬于不太正常的情況,當(dāng)age等于idle時(shí),說明連接一直處于空閑狀態(tài)。 為了更加直觀地描述age和idle,下面用一個(gè)例子進(jìn)行說明:

String key = "hello"; // 1) 生成jedis,并執(zhí)行g(shù)et操作 Jedis jedis = new Jedis("127.0.0.1", 6379); System.out.println(jedis.get(key)); // 2) 休息10秒 TimeUnit.SECONDS.sleep(10); // 3) 執(zhí)行新的操作ping System.out.println(jedis.ping()); // 4) 休息5秒 TimeUnit.SECONDS.sleep(5); // 5) 關(guān)閉jedis連接 jedis.close();

下面對(duì)代碼中的每一步進(jìn)行分析,用client list命令來觀察age和idle參數(shù)的相應(yīng)變化。

注意
為了與redis-cli的客戶端區(qū)分,本次測(cè)試客戶端IP地址:10.7.40.98。

1)在執(zhí)行代碼之前,client list只有一個(gè)客戶端,也就是當(dāng)前的redis-cli,下面為了節(jié)省篇幅忽略掉這個(gè)客戶端。

127.0.0.1:6379> client list id=45 addr=127.0.0.1:55171 fd=6 name= age=2 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client

2)使用Jedis生成了一個(gè)新的連接,并執(zhí)行g(shù)et操作,可以看到IP地址為10.7.40.98的客戶端,最后執(zhí)行的命令是get,age和idle分別是1秒和0秒:

127.0.0.1:6379> client list id=46 addr=10.7.40.98:62908 fd=7 name= age=1 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get

3)休息10秒,此時(shí)Jedis客戶端并沒有關(guān)閉,所以age和idle一直在遞增:

127.0.0.1:6379> client list id=46 addr=10.7.40.98:62908 fd=7 name= age=9 idle=9 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get

4)執(zhí)行新的操作ping,發(fā)現(xiàn)執(zhí)行后age依然在增加,而idle從0計(jì)算,也就是不再閑置:

127.0.0.1:6379> client list id=46 addr=10.7.40.98:62908 fd=7 name= age=11 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping

5)休息5秒,觀察age和idle增加:

127.0.0.1:6379> client list id=46 addr=10.7.40.98:62908 fd=7 name= age=15 idle=5 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=ping

6)關(guān)閉Jedis,Jedis連接已經(jīng)消失:

redis-cli client list | grep "10.7.40.98”為空

(5)客戶端的限制maxclients和timeout
Redis提供了maxclients參數(shù)來限制最大客戶端連接數(shù),一旦連接數(shù)超過maxclients,新的連接將被拒絕。maxclients默認(rèn)值是10000,可以通過info clients來查詢當(dāng)前Redis的連接數(shù):

127.0.0.1:6379> info clients # Clients connected_clients:1414 ...

可以通過config set maxclients對(duì)最大客戶端連接數(shù)進(jìn)行動(dòng)態(tài)設(shè)置:

127.0.0.1:6379> config get maxclients 1) "maxclients" 2) "10000" 127.0.0.1:6379> config set maxclients 50 OK 127.0.0.1:6379> config get maxclients 1) "maxclients" 2) "50"

一般來說maxclients=10000在大部分場(chǎng)景下已經(jīng)絕對(duì)夠用,但是某些情況由于業(yè)務(wù)方使用不當(dāng)(例如沒有主動(dòng)關(guān)閉連接)可能存在大量idle連接, 無論是從網(wǎng)絡(luò)連接的成本還是超過maxclients的后果來說都不是什么好事,因此Redis提供了timeout(單位為秒)參數(shù)來限制連接的最大空閑時(shí)間,一旦客戶端連接的idle時(shí)間超過了timeout,連接將會(huì)被關(guān)閉,例如設(shè)置timeout為30秒:

#Redis默認(rèn)的timeout是0,也就是不會(huì)檢測(cè)客戶端的空閑 127.0.0.1:6379> config set timeout 30 OK

下面繼續(xù)使用Jedis進(jìn)行模擬,整個(gè)代碼和上面是一樣的,只不過第2)步驟休息了31秒:

String key = "hello"; // 1) 生成jedis,并執(zhí)行g(shù)et操作 Jedis jedis = new Jedis("127.0.0.1", 6379); System.out.println(jedis.get(key)); // 2) 休息31秒 TimeUnit.SECONDS.sleep(31); // 3) 執(zhí)行g(shù)et操作 System.out.println(jedis.get(key)); // 4) 休息5秒 TimeUnit.SECONDS.sleep(5); // 5) 關(guān)閉jedis連接 jedis.close();

執(zhí)行上述代碼可以發(fā)現(xiàn)在執(zhí)行完第2)步之后,client list中已經(jīng)沒有了Jedis的連接,也就是說timeout已經(jīng)生效,將超過30秒空閑的連接關(guān)閉掉:

127.0.0.1:6379> client list id=16 addr=10.7.40.98:63892 fd=6 name= age=19 idle=19 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=0 obl=0 oll=0 omem=0 events=r cmd=get # 超過timeout后,Jedis連接被關(guān)閉 redis-cli client list | grep “10.7.40.98”為空

同時(shí)可以看到,在Jedis代碼中的第3)步拋出了異常,因?yàn)榇藭r(shí)客戶端已經(jīng)被關(guān)閉,所以拋出的異常是JedisConnectionException,并且提示Unexpected end of stream:

stream: world Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException: Unexpected end of stream.

如果將Redis的loglevel設(shè)置成debug級(jí)別,可以看到如下日志,也就是客戶端被Redis關(guān)閉的日志:

12885:M 26 Aug 08:46:40.085 - Closing idle client

Redis的默認(rèn)配置給出的timeout=0,在這種情況下客戶端基本不會(huì)出現(xiàn)上面的異常,這是基于對(duì)客戶端開發(fā)的一種保護(hù)。例如很多開發(fā)人員在使用JedisPool時(shí)不會(huì)對(duì)連接池對(duì)象做空閑檢測(cè)和驗(yàn)證,如果設(shè)置了timeout>0,可能就會(huì)出現(xiàn)上面的異常,對(duì)應(yīng)用業(yè)務(wù)造成一定影響,但是如果Redis的客戶端使用不當(dāng)或者客戶端本身的一些問題,造成沒有及時(shí)釋放客戶端連接,可能會(huì)造成大量的idle連接占據(jù)著很多連接資源,一旦超過maxclients;后果也是不堪設(shè)想。所在在實(shí)際開發(fā)和運(yùn)維中,需要將timeout設(shè)置成大于0,例如可以設(shè)置為300秒,同時(shí)在客戶端使用上添加空閑檢測(cè)和驗(yàn)證等等措施,例如JedisPool使用common-pool提供的三個(gè)屬性:minEvictableIdleTimeMillis、
testWhileIdle、timeBetweenEvictionRunsMillis。

(6)客戶端類型
client list中的flag是用于標(biāo)識(shí)當(dāng)前客戶端的類型,例如flag=S代表當(dāng)前客戶端是slave客戶端、flag=N代表當(dāng)前是普通客戶端,flag=O代表當(dāng)前客戶端正在執(zhí)行monitor命令,下表列出了11種客戶端類型。

(7)其他
上面已經(jīng)將client list中重要的屬性進(jìn)行了說明,下表列出之前介紹過以及一些比較簡(jiǎn)單或者不太重要的屬性。

client list命令結(jié)果的全部屬性

7.2 monitor

monitor命令用于監(jiān)控Redis正在執(zhí)行的命令,如圖4-11所示,我們打開了兩個(gè)redis-cli,一個(gè)執(zhí)行set get ping命令,另一個(gè)執(zhí)行monitor命令。可以看到monitor命令能夠監(jiān)聽其他客戶端正在執(zhí)行的命令,并記錄了詳細(xì)的時(shí)間戳。

monitor命令演示

monitor的作用很明顯,如果開發(fā)和運(yùn)維人員想監(jiān)聽Redis正在執(zhí)行的命令,就可以用monitor命令,但事實(shí)并非如此美好,每個(gè)客戶端都有自己的輸出緩沖區(qū),既然monitor能監(jiān)聽到所有的命令,一旦Redis的并發(fā)量過大,monitor客戶端的輸出緩沖會(huì)暴漲,可能瞬間會(huì)占用大量?jī)?nèi)存,下圖展示了monitor命令造成大量?jī)?nèi)存使用。

高并發(fā)下monitor命令使用大量輸出緩沖區(qū)

7.3 客戶端相關(guān)配置

·timeout:檢測(cè)客戶端空閑連接的超時(shí)時(shí)間,一旦idle時(shí)間達(dá)到了timeout,客戶端將會(huì)被關(guān)閉,如果設(shè)置為0就不進(jìn)行檢測(cè)。
·maxclients:客戶端最大連接數(shù),前面已進(jìn)行分析,這里不再贅述,但是這個(gè)參數(shù)會(huì)受到操作系統(tǒng)設(shè)置的限制。
·tcp-keepalive:檢測(cè)TCP連接活性的周期,默認(rèn)值為0,也就是不進(jìn)行檢測(cè),如果需要設(shè)置,建議為60,那么Redis會(huì)每隔60秒對(duì)它創(chuàng)建的TCP連接進(jìn)行活性檢測(cè),防止大量死連接占用系統(tǒng)資源。
·tcp-backlog:TCP三次握手后,會(huì)將接受的連接放入隊(duì)列中,tcp-
backlog就是隊(duì)列的大小,它在Redis中的默認(rèn)值是511。通常來講這個(gè)參數(shù)不需要調(diào)整,但是這個(gè)參數(shù)會(huì)受到操作系統(tǒng)的影響,例如在Linux操作系統(tǒng)中,如果/proc/sys/net/core/somaxconn小于tcp-backlog,那么在Redis啟動(dòng)時(shí)會(huì)看到如下日志,并建議將/proc/sys/net/core/somaxconn設(shè)置更大。

# WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/ sys/net/core/somaxconn is set to the lower value of 128.

修改方法也非常簡(jiǎn)單,只需要執(zhí)行如下命令:

echo 511 > /proc/sys/net/core/somaxconn

總結(jié)

以上是生活随笔為你收集整理的《Redis开发与运维》- 核心知识整理二(Lua脚本、发布订阅、客户端等)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。

操综合 | 五月天婷婷在线观看视频 | 久久美女免费视频 | 日韩av视屏 | 永久免费毛片 | 免费91在线 | 久久久久国产精品一区 | 国产一区二区免费 | 国产伦精品一区二区三区在线 | 综合网天天色 | 久操中文字幕在线观看 | 不卡av电影在线观看 | 欧美analxxxx| 日韩欧美亚州 | 成人午夜毛片 | 日本三级中文字幕在线观看 | a久久久久 | 又黄又爽的视频在线观看网站 | 天天色天天操天天爽 | 欧美日韩国产综合一区二区 | 欧美性精品 | 国产亚洲成人网 | 国产美女精品视频 | 日韩精品一区二区久久 | 91中文字幕一区 | 天堂在线视频免费观看 | 91亚洲精品乱码久久久久久蜜桃 | 日本精品视频在线观看 | 人人爽爽人人 | 99精品视频免费观看视频 | 在线观看岛国av | 激情久久久 | 久久夜色电影 | 久草精品资源 | 色诱亚洲精品久久久久久 | 亚洲精品视频在线播放 | 97看片 | 亚洲精品美女在线观看 | 日日日网| 免费精品国产va自在自线 | 三级av免费观看 | 国产99久久久国产精品 | 午夜精品久久久久久中宇69 | 国产精品黄色av | 中文视频在线看 | 亚洲视频 视频在线 | 日韩美一区二区三区 | 999久久久精品视频 日韩高清www | 国产免费三级在线观看 | 欧美一区三区四区 | 国产视频精品免费播放 | 亚洲午夜激情网 | 日韩av电影国产 | 婷婷亚洲五月 | 国产亚洲字幕 | 九草在线观看 | 2022国产精品视频 | 黄色一及电影 | 午夜.dj高清免费观看视频 | 91成人精品国产刺激国语对白 | 欧美另类老妇 | 久久久久免费观看 | 中文字幕 国产视频 | 中文日韩在线 | 97精品免费视频 | 少妇激情久久 | 国产女人18毛片水真多18精品 | 肉色欧美久久久久久久免费看 | 免费av在线网站 | 国产精品亚 | 亚洲在线高清 | 韩日视频在线 | 黄色小说视频网站 | 夜夜躁日日躁狠狠久久av | 欧美日韩视频免费看 | 五月天婷婷视频 | 久久午夜精品 | 69视频永久免费观看 | 欧美日韩免费网站 | 免费色网 | va视频在线观看 | 久久国产精品免费一区 | 日韩成人不卡 | 久久久久成人精品亚洲国产 | 夜夜澡人模人人添人人看 | 视频国产在线观看18 | 日韩电影在线观看一区二区 | 日本性视频 | 91精品久久久久久 | 国产无套精品久久久久久 | 国产精品久久久久久久久久久久午 | 国产香蕉在线 | 色网站在线免费观看 | 久久综合九色综合欧美狠狠 | 国产一区二区三精品久久久无广告 | 精品久久美女 | 色网站黄| 亚洲蜜桃在线 | 一区二区三区四区五区在线 | 日本黄色免费大片 | 中文字幕日韩免费视频 | 国产在线精品一区二区三区 | 免费观看完整版无人区 | 精品黄色在线 | 99精品欧美一区二区三区 | 亚洲欧美日韩精品一区二区 | 久久这里只有精品视频99 | 免费碰碰 | 日本亚洲国产 | 精品毛片一区二区免费看 | 国产成a人亚洲精v品在线观看 | 国产精品不卡在线播放 | 亚洲电影影音先锋 | 亚洲高清91 | 99精品视频播放 | 欧美在线一二 | 欧美伦理一区二区三区 | 亚洲成人在线免费 | 久久亚洲成人网 | 99在线看 | 福利视频入口 | 日本精品视频免费观看 | 欧美在线你懂的 | 成人国产精品一区二区 | 午夜影院先 | 日本精品中文字幕在线观看 | 国内外成人在线 | 国产污视频在线观看 | 午夜三级福利 | 中文一区在线观看 | 欧美男男激情videos | 亚洲乱亚洲乱亚洲 | 高清一区二区三区av | 欧美精品在线一区二区 | 国产高清专区 | 久久国产综合视频 | 狠狠操狠狠干天天操 | 一本一本久久a久久 | 精品综合久久 | 91精品视频网站 | 伊色综合久久之综合久久 | 国产精品99爱 | 一二区电影 | 国产美女精品视频免费观看 | 亚洲黄在线观看 | 久草视频免费在线播放 | 欧美性成人 | a视频免费在线观看 | 黄色影院在线免费观看 | 国产黄大片在线观看 | 国产一二区视频 | 国产成人精品一区二区三区福利 | 毛片随便看 | 日韩欧美99| 在线观看一级片 | 亚洲成av人片在线观看香蕉 | 国产精品成人在线观看 | 少妇搡bbbb搡bbb搡忠贞 | 中文字幕亚洲精品在线观看 | 中文字幕欧美日韩va免费视频 | 久久久国产精品亚洲一区 | 男女激情免费网站 | 一区二区不卡视频在线观看 | 成人毛片一区 | 99r在线视频 | 免费在线观看国产黄 | 韩日三级av | 久久男人影院 | 成人超碰在线 | 国产精品 视频 | 亚洲视频网站在线观看 | 国产精品理论片在线播放 | 91成人网在线观看 | 国产99一区视频免费 | 国产馆在线播放 | 免费精品视频在线观看 | 久久999久久 | 99夜色| 亚洲精品欧美精品 | 精品视频区 | 婷婷精品国产一区二区三区日韩 | 久久国产精品网站 | 国产97视频在线 | 国产成视频在线观看 | 亚洲美女精品视频 | 日韩高清一 | 国产91在线观看 | 麻豆传媒精品 | 久久久精品影视 | 亚洲国产欧洲综合997久久, | 美女视频黄网站 | 九月婷婷综合网 | 久久久午夜精品福利内容 | 国产精品福利午夜在线观看 | 丰满少妇麻豆av | 特级西西444www大精品视频免费看 | 久久久久久久久毛片 | 五月婷婷丁香 | 五月婷婷在线视频 | 亚洲国产欧美一区二区三区丁香婷 | 夜夜骑天天操 | 一区二区三区电影大全 | 亚洲国产午夜 | 丁香婷婷射 | 久久国产精品免费视频 | 91看片在线免费观看 | 精品亚洲午夜久久久久91 | 最近免费观看的电影完整版 | 亚洲作爱视频 | 国产精品99久久久久久武松影视 | 婷婷精品国产一区二区三区日韩 | 中文一区二区三区在线观看 | 国内久久久久 | 国产视频在线播放 | 1000部18岁以下禁看视频 | 91亚洲精品久久久蜜桃网站 | 欧美一级电影片 | 天海冀一区二区三区 | 免费观看国产成人 | 欧美色精品天天在线观看视频 | 亚洲视频 视频在线 | 奇米网444| 97超视频免费观看 | 99久久精品国产欧美主题曲 | 美女免费网视频 | 亚洲高清在线观看视频 | 天天操综合网站 | 一区二区三区动漫 | 国产专区欧美专区 | 久久99热精品| 丁香激情综合国产 | 亚洲国产精品一区二区久久hs | 日韩欧美91 | 色干综合 | 色婷婷视频在线观看 | 99re国产| 久久久久国产免费免费 | 精品国产一区二区三区蜜臀 | 久久精品久久99精品久久 | 91av在线免费 | 天天操天天操 | 欧美成人精品欧美一级乱黄 | 午夜精品久久 | 成年人免费看片 | 在线观看爱爱视频 | 精品视频区 | 国产精品中文字幕在线播放 | 日韩免费看 | 日韩中文字幕免费视频 | 久久精品国产免费看久久精品 | av一区二区三区在线观看 | 精品国内自产拍在线观看视频 | 最新色视频 | 午夜精品一区二区国产 | 特级西西444www大胆高清无视频 | 国产亚洲免费的视频看 | 丁香婷婷网 | 毛片网在线播放 | 五月婷婷一区二区三区 | 一级电影免费在线观看 | 91视频在线网址 | 成人综合婷婷国产精品久久免费 | 国产精品麻豆99久久久久久 | 久草干| 欧美亚洲一区二区在线 | 久久精品高清 | 免费国产在线精品 | 狠狠综合网 | 国产精品九九九九九九 | 婷婷综合影院 | 国内精品久久久久久久久久久 | 亚洲少妇久久 | 国产精品久久毛片 | 天天曰天天爽 | av电影一区二区 | 精品99在线观看 | 久久久国产高清 | 99视频在线观看一区三区 | 免费在线观看成人小视频 | 久久国产精品久久精品国产演员表 | 91视频链接 | 一区免费在线 | 一区二区中文字幕在线观看 | 99精品国产一区二区三区麻豆 | 精品视频免费播放 | 日韩视频 一区 | 日韩国产精品一区 | 久草在线官网 | 国产免费影院 | 色综合久久五月 | 91在线视频免费91 | 精品国产网址 | 久国产在线播放 | 国产精品久久免费看 | 中文字幕色播 | a午夜电影 | 日本在线中文 | 夜色成人网 | 亚洲欧美日韩精品久久久 | 五月婷香蕉久色在线看 | 人人藻人人澡人人爽 | 日韩精品 在线视频 | 欧美日本在线观看视频 | 91精品国产电影 | 久影院 | avhd高清在线谜片 | 国产精品嫩草55av | 涩涩网站在线观看 | 国模精品一区二区三区 | 久久成人在线视频 | 国产成人av福利 | 狠狠插天天干 | 亚洲乱亚洲乱妇 | 精品一区二区在线免费观看 | 精品一区二三区 | 中文字幕久久久精品 | 国产91在线 | 美洲 | 亚洲乱码精品 | 99国产在线视频 | 国产成人一区二区三区电影 | www.夜夜夜| 欧美日韩国内在线 | 日本精品视频网站 | 91私密视频 | 麻豆国产视频 | 99人久久精品视频最新地址 | 国内精品99 | 国产高清日韩 | 国产精品久久一 | 久久久精品小视频 | 不卡电影一区二区三区 | 日本护士三级少妇三级999 | 日韩久久影院 | 伊甸园av在线 | 久久免费99精品久久久久久 | 亚洲高清视频在线 | 色在线高清 | 国产91电影在线观看 | 色午夜影院 | 99久久精品费精品 | 日日操操操| 国产 在线 高清 精品 | 香蕉视频91 | 亚洲天天在线 | 日韩一区二区久久 | 97超碰中文字幕 | 色婷婷视频在线 | 午夜精品久久久久久久99 | 欧美日韩精品影院 | 国产黄色视 | 成人免费视频网站在线观看 | 五月亚洲| 五月天六月婷 | 国产手机在线视频 | 97操操操 | 中文字幕一区二区三区精华液 | 91视频成人免费 | 久久高清国产 | a黄色影院 | 国产99久久精品一区二区永久免费 | 91视频中文字幕 | 欧美日韩午夜爽爽 | 99精品福利 | 精品在线视频一区二区三区 | 国产高清视频免费最新在线 | 片黄色毛片黄色毛片 | 天天av在线播放 | 精品国精品自拍自在线 | 日韩中文在线视频 | 国产一级在线免费观看 | 欧美91视频 | 激情婷婷在线 | 免费黄色在线网址 | 在线观看免费高清视频大全追剧 | 欧美日韩国产三级 | 国产精品嫩草55av | 在线天堂8√ | 五月天综合色 | 超碰免费在线公开 | 天天色欧美 | 免费国产在线精品 | 精品视频免费 | 婷婷网址 | 91在线视频在线 | 69av免费视频 | 一级免费看视频 | 成人av在线网址 | 亚洲aaa毛片| 国产一级精品在线观看 | 999日韩| 免费在线观看成人小视频 | 国产精品 视频 | 一区二区三区电影在线播 | 99视频免费观看 | 亚洲成av人片在线观看无 | 日韩av看片| 91探花系列在线播放 | 伊人久久国产精品 | 在线一区二区三区 | 黄色大全免费观看 | 中文字幕日韩精品有码视频 | 777视频在线观看 | 久久精品一二三区白丝高潮 | 国产精品一二 | 国产精品欧美久久 | bbb搡bbb爽爽爽| 99精品国产亚洲 | 婷婷日韩| 亚洲婷婷在线 | 一级特黄av| www看片网站 | 欧美性性网 | 亚洲欧美日韩在线看 | 免费看三级黄色片 | 日本久草电影 | 亚洲第一区精品 | 亚洲国产精品日韩 | 97电影网站 | 91免费在线| 精品久久久久一区二区国产 | 精品视频免费观看 | 中文字幕影片免费在线观看 | 欧美在线视频第一页 | 国产亚洲人 | 狠色在线 | 国产精品区一区 | 久久男人视频 | 天天操天天干天天爱 | 国产精品久久久久久久午夜片 | 国产精品美女毛片真酒店 | 亚洲成a人片在线观看中文 中文字幕在线视频第一页 狠狠色丁香婷婷综合 | 五月天激情视频在线观看 | 视频在线99| 久久香蕉电影 | 美女视频黄,久久 | 在线看v片成人 | 国产亚洲精品久久久久久久久久 | 中文字幕一区二区三区在线视频 | 黄色的视频网站 | 美国人与动物xxxx | av爱干 | 欧美国产三区 | 日韩一区二区三区在线观看 | 亚洲视频在线观看 | 日韩精品视频免费看 | 免费a网址 | 亚洲国产一区二区精品专区 | 成人精品在线 | 久久人人添人人爽添人人88v | 亚洲日本国产精品 | 久久人人爽人人人人片 | 国内揄拍国内精品 | 欧美韩国在线 | 日韩免费高清在线 | 91av在线免费观看 | 欧美一二三区播放 | aaa毛片视频 | 91在线看 | 99精品视频免费在线观看 | 欧美日韩高清一区二区 | 日韩三区在线 | 在线视频观看成人 | 久久久久久久久久久精 | 日韩精品在线视频 | 97超级碰碰碰视频在线观看 | 亚洲国产精品电影在线观看 | 国产裸体bbb视频 | 成人av教育| 日韩成人看片 | 久草线 | 黄色国产在线观看 | 国产97碰免费视频 | 日韩电影久久久 | 日本资源中文字幕在线 | 天天艹天天 | 日韩在线观看影院 | 国产一二三在线视频 | av福利在线免费观看 | 久久中文字幕在线视频 | 麻豆一级视频 | 日韩精品一区二区免费视频 | 2018亚洲男人天堂 | 国产精品久久久久婷婷二区次 | 高清在线一区 | 久久99免费 | 国产精品一区二区免费在线观看 | 久久久久久久电影 | 国产精品日韩 | 美女视频久久久 | 99久久精品免费看国产麻豆 | 超碰97免费 | 久久久久久久国产精品视频 | 又黄又爽的免费高潮视频 | 婷婷五天天在线视频 | 免费看片色 | 四虎在线免费观看 | 国内精自线一二区永久 | 国产黄在线 | 婷婷丁香视频 | 国产又粗又硬又爽的视频 | 亚洲精品大片www | 久久在线视频精品 | 人人插人人玩 | 中文字幕文字幕一区二区 | 亚洲精品88欧美一区二区 | 96精品在线 | 精品一区久久 | 丁香视频五月 | 69视频永久免费观看 | 亚洲精品在线免费播放 | 99视频在线精品国自产拍免费观看 | wwwwww黄| 国产精品99久久久久的智能播放 | 国产一级h | 国产精品久久一卡二卡 | 国产玖玖精品视频 | 国产精品久久久久久久久久99 | 人人澡人人爽 | 91精品在线免费 | 免费在线观看一区 | 中文字幕 影院 | 亚洲干视频在线观看 | 国产手机视频精品 | 99久久99久久免费精品蜜臀 | 天天看天天干天天操 | 免费看麻豆 | 国产香蕉视频在线观看 | 亚洲区精品 | 999视频在线播放 | 欧美一区在线看 | 99久久夜色精品国产亚洲96 | 久久99精品久久久久久 | 综合色伊人| www在线免费观看 | 免费在线黄| 国产精品久久久久久久久久 | 国产精品一区二区62 | 久久久精品国产一区二区 | 97人人艹| 四虎成人免费影院 | 国产一区二区三区视频在线 | 91久久国产精品 | www视频免费在线观看 | 97成人精品 | 99精品在线| 国产日产精品一区二区三区四区的观看方式 | 欧美日韩一区久久 | 日韩精品一区二区三区外面 | 日韩高清免费电影 | 色吊丝av中文字幕 | 粉嫩av一区二区三区免费 | 久久综合九色综合欧美就去吻 | 成人教育av | 91成人精品一区在线播放69 | 69视频国产 | 99久久免费看 | 日韩在线首页 | 国产精品久久久久一区二区三区 | 国产永久免费高清在线观看视频 | 久草视频在线资源 | 色婷婷www | 深爱开心激情网 | 免费看片在线观看 | 久久资源在线 | 天天天天综合 | 成年人看片网站 | 五月综合激情婷婷 | 久草视频在线免费播放 | 黄色在线观看免费 | 天天天色综合 | 麻豆免费看片 | 综合久久综合久久 | 亚洲国产97在线精品一区 | 国产精品欧美久久久久无广告 | 日本中文字幕电影在线免费观看 | 狠狠狠的干| 97涩涩视频 | 精品久久视频 | 在线视频 影院 | 色多多视频在线 | 激情影音 | 五月婷婷操| 久久国产剧场电影 | 久久国产手机看片 | 国产精品va在线观看入 | 日韩毛片在线一区二区毛片 | 香蕉视频免费看 | 欧美日韩亚洲第一 | 麻豆视频网址 | 国产成人免费观看 | 九九爱免费视频在线观看 | 成人va视频 | 97在线观看免费高清 | 国内精品免费久久影院 | www.天天色 | 欧美极度另类性三渗透 | 免费观看9x视频网站在线观看 | 久久成人视屏 | 激情久久久久久久久久久久久久久久 | 亚洲不卡av一区二区三区 | 亚洲视频2| 日本久久精品 | 91九色porn在线资源 | 日韩精品一区二区三区视频播放 | 国产999精品久久久 免费a网站 | 黄色免费网战 | 999视频在线播放 | 在线午夜 | 99热精品久久 | 18久久久 | 区一区二区三区中文字幕 | 日本黄色免费电影网站 | 人人插人人草 | 久久大视频 | 久久精品视频中文字幕 | 在线影视 一区 二区 三区 | 欧洲一区精品 | 在线观看国产福利片 | www.av在线.com | 亚洲一区视频在线播放 | 国产99一区二区 | 久久99精品一区二区三区三区 | 免费高清在线一区 | 日b视频在线观看网址 | 8x8x在线观看视频 | 日韩视频在线观看免费 | 欧美日韩在线观看不卡 | 天天操天天色综合 | 国产字幕在线观看 | 99色在线视频 | 97免费公开视频 | 欧美日韩高清国产 | 欧美一级视频一区 | 国产精品美女久久久久久久 | 99色资源 | 国产精品久久久久久久久久久不卡 | 97超级碰碰碰碰久久久久 | 亚洲欧美日韩不卡 | 日日夜夜骑 | 在线观看久草 | 91久久人澡人人添人人爽欧美 | 亚洲精品国产自产拍在线观看 | 国产精品刺激对白麻豆99 | 国产精品 国内视频 | 狠狠干激情 | 国产在线色站 | 国产在线理论片 | 欧美一级欧美一级 | 在线免费观看视频一区 | 香蕉影视app | 久久午夜鲁丝片 | 日韩欧美观看 | 日韩久久久久久久久 | 国产精品久久久一区二区三区网站 | 国产日产精品一区二区三区四区 | 欧美日韩国语 | 99久久久国产精品美女 | 欧美 日韩精品 | 黄色的片子 | 韩国av免费观看 | 高清免费av在线 | 欧美日韩免费一区 | 久久久黄色 | 激情五月婷婷丁香 | 精品播放| 视频91| 欧美91视频 | 日韩欧美一区二区在线观看 | 亚洲va在线va天堂 | 久久综合成人 | 久久高清视频免费 | 成人免费观看大片 | av大全在线看 | 免费看国产a | 在线免费观看视频你懂的 | 色香蕉在线 | 亚洲一级特黄 | 国产精品欧美久久久久三级 | 97视频网站 | 有码中文字幕 | 欧美在线1| 在线观看国产区 | 五月天婷亚洲天综合网精品偷 | 婷婷av网站 | 国产精品国产三级在线专区 | 国产在线视频一区二区 | 久久a级片 | 91九色网址 | 国产免费久久av | 亚洲免费成人av电影 | 亚洲综合视频网 | 97在线观 | h文在线观看免费 | 九九激情视频 | 欧美国产在线看 | 久久不卡电影 | 国产色婷婷 | 欧美韩日在线 | 免费的国产精品 | 亚洲五月婷婷 | 色综合久久久 | 一区二区视频欧美 | 国产精品门事件 | 亚洲污视频 | 日本性动态图 | 欧美日韩高清一区二区 国产亚洲免费看 | 精品伦理一区二区三区 | 婷婷av资源| 337p欧美 | 中文字幕在线观看播放 | 国内精品久久久久影院优 | 在线免费黄色av | 日韩欧美高清免费 | 日本精a在线观看 | 午夜视频在线观看一区二区 | 天天摸天天干天天操天天射 | 久久久国产精品人人片99精片欧美一 | 国产高清在线一区 | 日韩国产高清在线 | 中文字幕一区二区三区四区视频 | 超碰免费公开 | 日韩av电影免费观看 | 欧美天天综合 | 五月天综合婷婷 | 国产一级高清 | 久久精品美女 | 99久热在线精品视频观看 | 久久五月天色综合 | 色偷偷人人澡久久超碰69 | 97超碰色| 久久久精品成人 | 亚洲一级免费观看 | 99免费观看视频 | 91尤物国产尤物福利在线播放 | 欧美成人精品欧美一级乱黄 | 日韩,精品电影 | 精品一区久久 | 激情喷水| 午夜视频导航 | 色婷婷精品大在线视频 | 91精品夜夜 | 精品一区 在线 | 久久精品视频网 | 91成人黄色| 日日日干| 黄网站色欧美视频 | 日韩高清不卡在线 | 欧美日韩破处 | 玖玖在线播放 | 99精品国产99久久久久久97 | 中文字幕美女免费在线 | 免费三及片 | 99免费精品 | 久久国产精品免费一区二区三区 | 天天综合中文 | 久草资源免费 | 插婷婷| 色婷婷综合成人av | 天天操天| 日本性久久 | av免费网页| 国产黄a三级三级三级三级三级 | 国产成人1区 | 久久九九久久精品 | 在线观看亚洲精品 | 黄色在线网站噜噜噜 | 国产专区在线 | 国产麻豆剧果冻传媒视频播放量 | 一级成人在线 | 国产福利中文字幕 | 深夜男人影院 | 狠狠色丁香婷婷综合久久片 | 日韩成人免费电影 | 国产特黄色片 | 亚洲国产伊人 | 97精品国产97久久久久久 | 久久国色夜色精品国产 | 国产黄色电影 | 日本三级吹潮在线 | 久久情爱 | 国产亚洲精品女人久久久久久 | 久草在线一免费新视频 | 亚洲精品福利在线 | 中文成人字幕 | 国产精品 欧美 日韩 | 99视频国产精品免费观看 | 91少妇精拍在线播放 | 中文字幕一区二区三区四区 | 久久国产精品视频观看 | 999一区二区三区 | 久久久精品电影 | 日韩在线视频二区 | 国产xx在线 | www五月| 中文在线a在线 | 亚洲综合色视频在线观看 | 成人精品一区二区三区中文字幕 | 国产精品一区二区三区观看 | 亚洲欧美乱综合图片区小说区 | 黄色大全免费观看 | 午夜av大片 | 国产五月天婷婷 | 亚洲国产精品资源 | 国产一区播放 | 午夜精品麻豆 | 国产精品大片免费观看 | 成人在线视| 国产日本高清 | 日韩欧美视频免费在线观看 | 国产又粗又猛又黄 | 三级性生活视频 | 欧美日韩亚洲在线 | 亚洲久在线 | 国产亚洲情侣一区二区无 | 高清av网站| 日韩美女黄色片 | 天天干天天插伊人网 | 国产中文字幕一区二区三区 | 日韩精品一区二区三区高清免费 | 久久久久亚洲最大xxxx | 久久黄色片 | 国产高清视频在线播放一区 | 午夜色大片在线观看 | 亚洲国产资源 | 国产精品美女免费看 | 97在线观看视频 | 日批视频在线观看免费 | 99超碰在线观看 | 91视频高清完整版 | 亚洲激情av | 91日韩在线| 一二三区视频在线 | 青青河边草免费直播 | 成x99人av在线www| 日韩午夜在线 | 国产美女在线精品免费观看 | 国产黄色精品在线 | japanesexxxhd奶水 91在线精品一区二区 | 91黄色免费看 | 国产黄色大全 | 日日日日| 亚洲 欧美 变态 国产 另类 | 国产手机在线观看视频 | 亚洲国产中文在线 | 91成人精品视频 | 日韩精品亚洲专区在线观看 | 午夜视频一区二区 | 久久97精品| 天天综合网 天天 | 欧美一区二区在线免费观看 | 亚洲精选在线 | 日日麻批40分钟视频免费观看 | 欧美人体xx| 成人h在线 | 在线 视频 一区二区 | 久久一区精品 | 96精品视频 | 精品久久美女 | 天堂网av 在线 | 深爱激情五月婷婷 | 欧美日韩伦理在线 | 国产亚洲精品久久久久久网站 | 免费看wwwwwwwwwww的视频 久久久久久99精品 91中文字幕视频 | 日本特黄特色aaa大片免费 | 成人中心免费视频 | 亚洲免费专区 | 中文字幕在线观看网站 | 中文字幕在线观看免费高清电影 | 日韩欧美国产精品 | 国产无套精品久久久久久 | 亚洲国产精品成人av | 日日爽日日操 | 国产精品久久久久久高潮 | 日韩av电影中文字幕在线观看 | 亚洲欧美日本一区二区三区 | 国产成人精品一区二区三区网站观看 | 国产日韩精品在线 | 国产高清永久免费 | 在线小视频你懂得 | 国产精品不卡在线观看 | 日韩有码网站 | 久艹在线播放 | 国产精品一区久久久久 | 精品91| 中文字幕在线视频一区二区 | 97电影网手机版 | 色视频在线观看 | 久久精品亚洲一区二区三区观看模式 | 亚洲男男gⅴgay双龙 | 久久精视频 | 亚洲一二区精品 | 青青河边草观看完整版高清 | 最新午夜电影 | 日韩精品偷拍 | 九色精品免费永久在线 | 久久黄色成人 | 在线免费av电影 | 色综合天天天天做夜夜夜夜做 | 又爽又黄在线观看 | 久草在线免费播放 | 2000xxx影视| 高清一区二区 | 久久亚洲私人国产精品 | 国产精品久久久一区二区 | 人人爽人人爽人人片av | 久草在线最新 | 91成年视频 | 国产一线二线三线性视频 | 91香蕉国产在线观看软件 | 天天干夜夜 | 婷婷五月情 | 亚洲欧美激情精品一区二区 | 国产日韩视频在线播放 | 久久综合桃花 | 成人黄色在线观看视频 | 国产aa精品| 日韩中文字幕a | 欧美做受高潮1 | 国产黄色片免费看 | 久草网视频 | 99中文在线| 国产午夜在线观看 | 日韩动态视频 | 国产欧美精品在线观看 | 69绿帽绿奴3pvideos | 91久久奴性调教 | 国产成人精品久久二区二区 | 99九九免费视频 | 久久精品一二三 | 成人午夜剧场在线观看 | 中文字幕成人 | 久久99电影 | 午夜精品一区二区三区在线观看 | 日韩一级理论片 | 高清不卡毛片 | 91成人精品在线 | 狠狠干2018| 97精品国产91久久久久久 | 久久天天拍 | 99精品视频网 | 国产美女精品视频 | 国产日韩精品在线观看 | 韩国一区二区av | 在线视频国产区 | 9999在线 | 亚洲精品无 | 欧美大片第1页 | 国产成人亚洲精品自产在线 | 97视频在线看| 亚洲免费小视频 | 操少妇视频 | 日本少妇视频 | 天天天天天天操 | 精品国产成人在线影院 | 91九色porn在线资源 | 中文字幕视频三区 | 精品久久久久久亚洲 | 美女国内精品自产拍在线播放 | 欧美做受xxx | 三级在线视频播放 | 日韩免费在线播放 | 99久久综合国产精品二区 | 中文字幕在线网址 | 91在线网站| 99久久夜色精品国产亚洲 | 青青草在久久免费久久免费 | 色婷婷九月 | 天天射天天干天天 | 五月激情五月激情 | 97免费在线观看 | 亚洲免费在线看 | 开心激情久久 | 精品一区二区综合 | 综合久久精品 | 欧美日韩综合在线 | 一区av在线播放 | www.888.av| 91传媒免费在线观看 | 国产精品久久视频 | av在线一 | 色综合婷婷 | 99re6热在线精品视频 | 在线午夜电影神马影院 | 欧美成人按摩 | 色播五月激情五月 | 亚洲专区中文字幕 | 亚洲精品女人 | 亚洲国产手机在线 | 91九色成人蝌蚪首页 | 国产精品久久久久久久久免费 | 国产精品va最新国产精品视频 | www178ccom视频在线 | 菠萝菠萝蜜在线播放 | 国产最新福利 | 亚洲三级网站 | 国产小视频在线观看免费 | 精品一区二区三区香蕉蜜桃 | 99视频精品 |