redis是乙個使用客戶機-伺服器模型和所謂的請求/響應協議的tcp伺服器。這意味著請求通常通過以下步驟完成:
客戶端和伺服器通過網路連線。這樣的鏈結可以是非常快(環迴介面)或非常慢(在internet上建立的連線,兩台主機之間有許多跳)。無論網路延遲是什麼,資料報都有一段時間從客戶機傳輸到伺服器,然後從伺服器返回到客戶機以攜帶應答。
這個時間叫做rtt(往返時間)。當客戶機需要在一行中執行多個請求時(例如向同一列表中新增多個元素,或用多個鍵填充資料庫),很容易看出這會如何影響效能。例如,如果rtt時間是250毫秒(在internet上的鏈結非常慢的情況下),即使伺服器能夠每秒處理10萬個請求,我們也將能夠每秒最多處理四個請求。
一、什麼是redis管道
redis提供了一種區別於上述響應模式的方式,客戶端無需等待單個請求響應再進行下一次請求,而是可以一次傳送多個命令給伺服器,伺服器處理完後一次性將結果返回給客戶端,這種工作方式在redis中被稱作管道。可以可出,通過管道的方式,能夠明顯的減少請求的次數,在於網路狀況不好的環境中,能明顯的提生處理的速度。
二、jedis中的管道實現
在jedis中,客戶端通過與伺服器建立socket長連線來進行通訊,主要通過乙個connection物件進行維護,可以看下這個類的定義:
public class connection implements closeable
public connection(final string host)
public connection(final string host, final int port)
//...
}
connection物件通過outputstream傳送redis命令,通過inputstream讀取伺服器的響應,對與傳送redis命令,jedis中分為兩個動作:
我們通過乙個檢視set命令的原始碼驗證一下:
@override
public string set(final string key, final string value)
進入client.set方法:
@override
public void set(final string key, final string value)
//...
public void set(final byte key, final byte value)
//...
public void sendcommand(final protocolcommand cmd, final byte... args) catch (jedisconnectionexception ex)
} catch (exception e)
// any other exceptions related to connection?
broken = true;
throw ex;
}}
再看下protocol.sendcommand:
public static void sendcommand(final redisoutputstream os, final protocolcommand command,
final byte... args)
private static void sendcommand(final redisoutputstream os, final byte command,
final byte... args)
} catch (ioexception e)
}
到這一步,客戶端的set命令就完成了,但是這只是命令寫入到了outputstream緩衝區中,還沒有向redis伺服器實際的傳送redis命令,
我們再來看一下 client.getstatuscodereply():
public string getstatuscodereply() else
}
該方法會觸發flush,outputstream緩衝區中的redis命令會真正的傳送到redis伺服器上,我們理解上述過程之後,再回過頭來看下管道。
在redis客戶端中,客戶端只能處於一種模式下,要麼是普通的模式,一次傳送乙個請求,要麼處於管道模式,二者不能混用。在普通模式下,命令寫入到outputstream緩衝區後會立即觸發flush,而在管道模式模式下,flush的觸發需要顯示呼叫pipeline.sync()函式,因此可以實現一次傳送多個命令。
public void sync()
}}public listgetmany(final int count) catch (jedisdataexception e)
}return responses;
}
三、jedis管道的資料接收
jedis中通過一次性將outputstream中的命令傳送到redis中來實現管道的特性,但這裡有乙個問題需要解決,客戶端如何接收伺服器響應。在普通模式下,客戶端傳送請求,然後同步的接收響應。在管道模式下,需要批量的接收響應,然後分發的對應的請求中去,jedis通過builder介面實現這個過程:
public abstract class builder
在jedis的builde***ctory中,對builder介面進行多種實現,主要包括將data轉換為string,int,long,float,double和boolean型別。
在通過pipeline傳送命令命令時,pipeline會返回乙個response物件代表乙個伺服器響應,可以看下這個類的實現:
public class response
public void set(object data)
public t get()
if (!set)
if (!built)
if (exception != null)
return response;
} //...
}
可以看到,response物件的建立需要乙個builder, 表示如何構造響應資料。
我們還是以set命令為例子:
@override
public responseset(final string key, final string value)
//...
protected responsegetresponse(builderbuilder)
可以看到,呼叫set命令時,pipeline會將命令的實現委託給client物件,並返回乙個指定builder的response,表示將來有資料了,通過指定的builder去構造資料。並且也會將response加入到管道維護的乙個佇列中。這個主要是為了呼叫sync()方法時,將伺服器的響應分發到每乙個response中。
public void sync()
}}protected response<?> generateresponse(object data)
return response;
}
這個時候 response中就有了資料data,此時就可以呼叫builder去獲取實際型別的資料了。
本人對redis的管道做了簡單介紹,也簡單說了一下jedis的管道實現,假如有不對的地方,歡迎前來指正。
redis簡單介紹
多次查詢讓你懷疑人生 冗餘欄位過多會讓你看起來很傻 為啥不試試redis 大大減少了查詢數量,提高了效率 redis的api更加人性化,再也不需要構建sql語句,節省了sql的解析時間 redis 是完全開源免費的,遵守bsd協議,是乙個高效能的key value資料庫。redis 與其他 key ...
redis簡單介紹
特點 速度快,多種資料結構,簡單穩定,客戶端支援語言多,持久化,主從,高可用和分布式 速度快 基於鍵值對的nosql資料庫,將資料都放入記憶體中,使用c語言,單執行緒架構 資料結構 字串,雜湊,列表,集合,有序集合 鍵過期功能,實現快取,簡單穩定不依賴作業系統中的類庫,使用單執行緒 持久化 rdb和...
redis 簡單介紹
了解redis的資料結構有助於了解每種資料結構的優劣勢,方便設計合理的cache結構。1.string 可以儲存字串 浮點型 整型,如果是字串可以執行字串操作,如果是浮點型 整型也可以執行加減操作。redis會識別出它的具體型別。2.list 鍊錶,鍊錶中的每個node包含乙個字串。可以對鍊錶進行兩...