client list 詳解

節選自《redis開發與運維》

先來看一段client list的執行結果

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

輸出結果的每一行代表一個客戶端的信息,可以看到每行包含了十幾個屬性,它們是每個客戶端的一些執行狀態,理解這些屬性對于Redis的開發和運維人員非常有幫助。下面將選擇幾個重要的屬性進行說明,其余通過表格的形式進行展示。

(1)標識:id、addr、fd、name

這四個屬性屬于客戶端的標識:

·id:客戶端連接的唯一標識,這個id是隨著Redis的連接自增的,重啟Redis后會重置為0。

·addr:客戶端連接的ip和端口。

·fd:socket的文件描述符,與lsof命令結果中的fd是同一個,如果fd=-1代表當前客戶端不是外部客戶端,而是Redis內部的偽裝客戶端。

·name:客戶端的名字,后面的client setName和client getName兩個命令會對其進行說明。

(2)輸入緩沖區:qbuf、qbuf-free

Redis為每個客戶端分配了輸入緩沖區,它的作用是將客戶端發送的命令臨時保存,同時Redis從會輸入緩沖區拉取命令并執行,輸入緩沖區為客戶端發送命令到Redis執行命令提供了緩沖功能,如圖4-5所示。

client list中qbuf和qbuf-free分別代表這個緩沖區的總容量和剩余容量,Redis沒有提供相應的配置來規定每個緩沖區的大小,輸入緩沖區會根據輸入內容大小的不同動態調整,只是要求每個客戶端緩沖區的大小不能超過1G,超過后客戶端將被關閉。下面是Redis源碼中對于輸入緩沖區的硬編碼:
[圖片上傳失敗...(image-e1b72f-1571740556050)]
/* Protocol and I/O related defines */

#define REDIS_MAX_QUERYBUF_LEN (102410241024) /* 1GB max query buffer. */

輸入緩沖使用不當會產生兩個問題:

·一旦某個客戶端的輸入緩沖區超過1G,客戶端將會被關閉。

·輸入緩沖區不受maxmemory控制,假設一個Redis實例設置了maxmemory為4G,已經存儲了2G數據,但是如果此時輸入緩沖區使用了3G,已經超過maxmemory限制,可能會產生數據丟失、鍵值淘汰、OOM等情況(如圖4-6所示)。
[圖片上傳失敗...(image-79c38d-1571740556050)]
執行效果如下:

127.0.0.1:6390> info memory

# Memory

used_memory_human:5.00G

...

maxmemory_human:4.00G

....

上面已經看到,輸入緩沖區使用不當造成的危害非常大,那么造成輸入緩沖區過大的原因有哪些?輸入緩沖區過大主要是因為Redis的處理速度跟不上輸入緩沖區的輸入速度,并且每次進入輸入緩沖區的命令包含了大量bigkey,從而造成了輸入緩沖區過大的情況。還有一種情況就是Redis發生了阻塞,短期內不能處理命令,造成客戶端輸入的命令積壓在了輸入緩沖區,造成了輸入緩沖區過大。

那么如何快速發現和監控呢?監控輸入緩沖區異常的方法有兩種:

·通過定期執行client list命令,收集qbuf和qbuf-free找到異常的連接記錄并分析,最終找到可能出問題的客戶端。

·通過info命令的info clients模塊,找到最大的輸入緩沖區,例如下面命令中的其中client_biggest_input_buf代表最大的輸入緩沖區,例如可以設置超過10M就進行報警:

127.0.0.1:6379> info clients

# Clients

connected_clients:1414

client_longest_output_list:0

client_biggest_input_buf:2097152

blocked_clients:0

這兩種方法各有自己的優劣勢,表4-3對兩種方法進行了對比。

表4-3 對比client list和info clients監控輸入緩沖區的優劣勢
[圖片上傳失敗...(image-dcc3de-1571740556050)]
輸入緩沖區問題出現概率比較低,但是也要做好防范,在開發中要減少bigkey、減少Redis阻塞、合理的監控報警。

(3)輸出緩沖區:obl、oll、omem

Redis為每個客戶端分配了輸出緩沖區,它的作用是保存命令執行的結果返回給客戶端,為Redis和客戶端交互返回結果提供緩沖,如圖4-7所示。

與輸入緩沖區不同的是,輸出緩沖區的容量可以通過參數client-output-buffer-limit來進行設置,并且輸出緩沖區做得更加細致,按照客戶端的不同分為三種:普通客戶端、發布訂閱客戶端、slave客戶端,如圖4-8所示。
[圖片上傳失敗...(image-5b93ed-1571740556050)]
[圖片上傳失敗...(image-320e63-1571740556050)]

應的配置規則是:

client-output-buffer-limit

·<class>:客戶端類型,分為三種。a)normal:普通客戶端;b)slave:slave客戶端,用于復制;c)pubsub:發布訂閱客戶端。

·<hard limit>:如果客戶端使用的輸出緩沖區大于<hard limit>,客戶端會被立即關閉。

·<soft limit>和<soft seconds>:如果客戶端使用的輸出緩沖區超過了<soft limit>并且持續了<soft limit>秒,客戶端會被立即關閉。

Redis的默認配置是:

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

和輸入緩沖區相同的是,輸出緩沖區也不會受到maxmemory的限制,如果使用不當同樣會造成maxmemory用滿產生的數據丟失、鍵值淘汰、OOM等情況。

實際上輸出緩沖區由兩部分組成:固定緩沖區(16KB)和動態緩沖區,其中固定緩沖區返回比較小的執行結果,而動態緩沖區返回比較大的結果,例如大的字符串、hgetall、smembers命令的結果等,通過Redis源碼中redis.h的redisClient結構體(Redis3.2版本變為Client)可以看到兩個緩沖區的實現細節:

typedef struct redisClient {

// 動態緩沖區列表 list *reply;

// 動態緩沖區列表的長度(對象個數)

unsigned long reply_bytes;

// 固定緩沖區已經使用的字節數 int bufpos;

// 字節數組作為固定緩沖區 char buf[REDIS_REPLY_CHUNK_BYTES];

} redisClient;

固定緩沖區使用的是字節數組,動態緩沖區使用的是列表。當固定緩沖區存滿后會將Redis新的返回結果存放在動態緩沖區的隊列中,隊列中的每個對象就是每個返回結果,如圖4-9所示。
[圖片上傳失敗...(image-24b35c-1571740556050)]
client list中的obl代表固定緩沖區的長度,oll代表動態緩沖區列表的長度,omem代表使用的字節數。例如下面代表當前客戶端的固定緩沖區的長度為0,動態緩沖區有4869個對象,兩個部分共使用了133081288字節=126M內存:

id=7 addr=127.0.0.1:56358 fd=6 name= age=91 idle=0 flags=O db=0 sub=0 psub=0 multi=-1

qbuf=0 qbuf-free=0 obl=0 oll=4869 omem=133081288 events=rw cmd=monitor

監控輸出緩沖區的方法依然有兩種:

·通過定期執行client list命令,收集obl、oll、omem找到異常的連接記錄并分析,最終找到可能出問題的客戶端。

·通過info命令的info clients模塊,找到輸出緩沖區列表最大對象數,例如:

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代表輸出緩沖區列表最大對象數,這兩種統計方法的優劣勢和輸入緩沖區是一樣的,這里就不再贅述了。相比于輸入緩沖區,輸出緩沖區出現異常的概率相對會比較大,那么如何預防呢?方法如下:

·進行上述監控,設置閥值,超過閥值及時處理。

·限制普通客戶端輸出緩沖區的,把錯誤扼殺在搖籃中,例如可以進行如下設置:

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

·適當增大slave的輸出緩沖區的,如果master節點寫入較大,slave客戶端的輸出緩沖區可能會比較大,一旦slave客戶端連接因為輸出緩沖區溢出被kill,會造成復制重連。

·限制容易讓輸出緩沖區增大的命令,例如,高并發下的monitor命令就是一個危險的命令。

及時監控內存,一旦發現內存抖動頻繁,可能就是輸出緩沖區過大。

(4)客戶端的存活狀態

client list中的age和idle分別代表當前客戶端已經連接的時間和最近一次的空閑時間:

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

例如上面這條記錄代表當期客戶端連接Redis的時間為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

例如上面這條記錄代表當期客戶端連接Redis的時間為8888581秒,其中空閑了8888581秒,實際上這種就屬于不太正常的情況,當age等于idle時,說明連接一直處于空閑狀態。

為了更加直觀地描述age和idle,下面用一個例子進行說明:

String key = "hello";
// 1) 生成jedis,并執行get操作 Jedis jedis = new Jedis("127.0.0.1", 6379);

System.out.println(jedis.get(key));

// 2) 休息10秒 TimeUnit.SECONDS.sleep(10);

// 3) 執行新的操作ping

System.out.println(jedis.ping());

// 4) 休息5秒 TimeUnit.SECONDS.sleep(5);

// 5) 關閉jedis連接 jedis.close();

下面對代碼中的每一步進行分析,用client list命令來觀察age和idle參數的相應變化。

為了與redis-cli的客戶端區分,本次測試客戶端IP地址:10.7.40.98。

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

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生成了一個新的連接,并執行get操作,可以看到IP地址為10.7.40.98的客戶端,最后執行的命令是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秒,此時Jedis客戶端并沒有關閉,所以age和idle一直在遞增:
27.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)執行新的操作ping,發現執行后age依然在增加,而idle從0計算,也就是不再閑置:

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)關閉Jedis,Jedis連接已經消失:

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

(5)客戶端的限制maxclients和timeout

Redis提供了maxclients參數來限制最大客戶端連接數,一旦連接數超過maxclients,新的連接將被拒絕。maxclients默認值是10000,可以通過info clients來查詢當前Redis的連接數:

127.0.0.1:6379> info clients

Clients

connected_clients:1414
...

可以通過config set maxclients對最大客戶端連接數進行動態設置:

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在大部分場景下已經絕對夠用,但是某些情況由于業務方使用不當(例如沒有主動關閉連接)可能存在大量idle連接,無論是從網絡連接的成本還是超過maxclients的后果來說都不是什么好事,因此Redis提供了timeout(單位為秒)參數來限制連接的最大空閑時間,一旦客戶端連接的idle時間超過了timeout,連接將會被關閉,例如設置timeout為30秒:

Redis默認的timeout是0,也就是不會檢測客戶端的空閑 127.0.0.1:6379> config set timeout 30

OK

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

String key = "hello";
// 1) 生成jedis,并執行get操作 Jedis jedis = new Jedis("127.0.0.1", 6379);

System.out.println(jedis.get(key));

// 2) 休息31秒 TimeUnit.SECONDS.sleep(31);

// 3) 執行get操作 System.out.println(jedis.get(key));

// 4) 休息5秒 TimeUnit.SECONDS.sleep(5);

// 5) 關閉jedis連接 jedis.close();

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

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連接被關閉 redis-cli client list | grep “10.7.40.98”為空

同時可以看到,在Jedis代碼中的第3)步拋出了異常,因為此時客戶端已經被關閉,所以拋出的異常是JedisConnectionException,并且提示Unexpected end of stream:

stream: world

Exception in thread "main" redis.clients.jedis.exceptions.JedisConnectionException:

Unexpected end of stream.

如果將Redis的loglevel設置成debug級別,可以看到如下日志,也就是客戶端被Redis關閉的日志:

12885:M 26 Aug 08:46:40.085 - Closing idle client
Redis源碼中redis.c文件中clientsCronHandleTimeout函數就是針對timeout參數進行檢驗的,只不過在源碼中timeout被賦值給了server.maxidletime:

int clientsCronHandleTimeout(redisClient *c) {

// 當前時間 time_t now = server.unixtime;

// server.maxidletime就是參數timeout

if (server.maxidletime &&

// 很多客戶端驗證,這里就不占用篇幅,最重要的驗證是下面空閑時間超過了maxidletime就會 // 被關閉掉客戶端 (now - c->lastinteraction > server.maxidletime))

{

redisLog(REDIS_VERBOSE,"Closing idle client");

// 關閉客戶端 freeClient(c);

}

}

Redis的默認配置給出的timeout=0,在這種情況下客戶端基本不會出現上面的異常,這是基于對客戶端開發的一種保護。例如很多開發人員在使用JedisPool時不會對連接池對象做空閑檢測和驗證,如果設置了timeout>0,可能就會出現上面的異常,對應用業務造成一定影響,但是如果Redis的客戶端使用不當或者客戶端本身的一些問題,造成沒有及時釋放客戶端連接,可能會造成大量的idle連接占據著很多連接資源,一旦超過maxclients;后果也是不堪設想。所在在實際開發和運維中,需要將timeout設置成大于0,例如可以設置為300秒,同時在客戶端使用上添加空閑檢測和驗證等等措施,例如JedisPool使用common-pool提供的三個屬性:minEvictableIdleTimeMillis、testWhileIdle、timeBetweenEvictionRunsMillis,4.2節已經進行了說明,這里就不再贅述。

(6)客戶端類型

client list中的flag是用于標識當前客戶端的類型,例如flag=S代表當前客戶端是slave客戶端、flag=N代表當前是普通客戶端,flag=O代表當前客戶端正在執行monitor命令,表4-4列出了11種客戶端類型。

[圖片上傳失敗...(image-d18643-1571740556050)]
(7)其他

上面已經將client list中重要的屬性進行了說明,表4-5列出之前介紹過以及一些比較簡單或者不太重要的屬性。

表4-5 client list命令結果的全部屬性
[圖片上傳失敗...(image-bcff52-1571740556050)]
[圖片上傳失敗...(image-4a93ae-1571740556050)]

2.client setName和client getName

client setName xx

client getName

client setName用于給客戶端設置名字,這樣比較容易標識出客戶端的來源,例如將當前客戶端命名為test_client,可以執行如下操作:

127.0.0.1:6379> client setName test_client

OK

此時再執行client list命令,就可以看到當前客戶端的name屬性為test_client:

127.0.0.1:6379> client list

id=55 addr=127.0.0.1:55604 fd=7 name=test_client age=23 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

如果想直接查看當前客戶端的name,可以使用client getName命令,例如下面的操作:

127.0.0.1:6379> client getName

"test_client"

client getName和setName命令可以做為標識客戶端來源的一種方式,但是通常來講,在Redis只有一個應用方使用的情況下,IP和端口作為標識會更加清晰。當多個應用方共同使用一個Redis,那么此時client setName可以作為標識客戶端的一個依據。

3.client kill

client kill ip:port

此命令用于殺掉指定IP地址和端口的客戶端,例如當前客戶端列表為:

127.0.0.1:6379> client list
id=49 addr=127.0.0.1:55593 fd=6 name= age=9 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

id=50 addr=127.0.0.1:52343 fd=7 name= age=4 idle=4 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

如果想殺掉127.0.0.1:52343的客戶端,可以執行:

127.0.0.1:6379> client kill 127.0.0.1:52343

OK

執行命令后,client list結果只剩下了127.0.0.1:55593這個客戶端:

127.0.0.1:6379> client list

id=49 addr=127.0.0.1:55593 fd=6 name= age=9 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
由于一些原因(例如設置timeout=0時產生的長時間idle的客戶端),需要手動殺掉客戶端連接時,可以使用client kill命令。

4.client pause

client pause timeout(毫秒)

如圖4-10所示,client pause命令用于阻塞客戶端timeout毫秒數,在此期間客戶端連接將被阻塞。
[圖片上傳失敗...(image-8e7472-1571740556050)]

例如在一個客戶端執行:

127.0.0.1:6379> client pause 10000

OK

在另一個客戶端執行ping命令,發現整個ping命令執行了9.72秒(手動執行redis-cli,只為了演示,不代表真實執行時間):

127.0.0.1:6379> ping

PONG

(9.72s)

該命令可以在如下場景起到作用:

·client pause只對普通和發布訂閱客戶端有效,對于主從復制(從節點內部偽裝了一個客戶端)是無效的,也就是此期間主從復制是正常進行的,所以此命令可以用來讓主從復制保持一致。

·client pause可以用一種可控的方式將客戶端連接從一個Redis節點切換到另一個Redis節點。

需要注意的是在生產環境中,暫停客戶端成本非常高。

5.monitor

monitor命令用于監控Redis正在執行的命令,如圖4-11所示,我們打開了兩個redis-cli,一個執行set get ping命令,另一個執行monitor命令。可以看到monitor命令能夠監聽其他客戶端正在執行的命令,并記錄了詳細的時間戳。
[圖片上傳失敗...(image-c63b7-1571740556050)]
monitor的作用很明顯,如果開發和運維人員想監聽Redis正在執行的命令,就可以用monitor命令,但事實并非如此美好,每個客戶端都有自己的輸出緩沖區,既然monitor能監聽到所有的命令,一旦Redis的并發量過大,monitor客戶端的輸出緩沖會暴漲,可能瞬間會占用大量內存,圖4-12展示了monitor命令造成大量內存使用。
[圖片上傳失敗...(image-c88e14-1571740556050)]

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,702評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,615評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,606評論 0 376
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,044評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,826評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,227評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,307評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,447評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,992評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,807評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,001評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,550評論 5 361
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,243評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,667評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,930評論 1 287
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,709評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,996評論 2 374

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • 1 Redis介紹1.1 什么是NoSql為了解決高并發、高可擴展、高可用、大數據存儲問題而產生的數據庫解決方...
    克魯德李閱讀 5,330評論 0 36
  • NOSQL類型簡介鍵值對:會使用到一個哈希表,表中有一個特定的鍵和一個指針指向特定的數據,如redis,volde...
    MicoCube閱讀 4,038評論 2 27
  • 前言 Redis的作者antirez(Salvatore Sanfilippo)曾經發表了一篇名為Redis宣言(...
    OzanShareing閱讀 1,469評論 0 20
  • 彼此依賴 才是最深的相愛
    如泉涌閱讀 186評論 0 0