整理了以前學習 redis 的筆記,強烈建議看最後總結。html
在大型系統數據讀請求中,基本上90%均可以經過分佈式緩存集羣來抗下來,而 Redis 又是分佈式緩存集羣的主要踐行者,所以瞭解 Redis 是必不可少的技能。java
在 javaWeb 中實現對 Redis 的操做,主要有兩種方式:Jedis、RedisTemplate。redis
Jedis 是 Redis 官方推薦的面向 Java 的操做Redis 的客戶端,經過jedis咱們能夠實現鏈接Redis,以及操做 Redis 。spring
RedisTemplate 是 SpringDataRedis 中對JedisAp i的高度封裝。SpringDataRedis 相對於 Jedis 來講能夠方便地更換 Redis 的 Java客戶端,比 Jedis 多了自動管理鏈接池的特性,方便與其餘 Spring 框架進行搭配使用如:SpringCache數據庫
就像在學習 springmvc 框架以前學習 servlet 同樣,瞭解 jedis 的使用,看一下單機中 Jedis 的使用,首先要導入相關架包,
jedis.jar數組
import redis.clients.jedis.Jedis;
public class RedisJava {
public static void main(String[] args) {
//鏈接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("鏈接成功");
//查看服務是否運行
System.out.println("服務正在運行: "+jedis.ping());
}
}
編譯以上 Java 程序,確保驅動包的路徑是正確的,打印以下:緩存
鏈接成功
服務正在運行: PONG
redis 中最主要的就是讀寫數據。Redis 操做5大基本類型:String、List、Hash、Set、SortedSe。t
菜鳥教程中關於 Redis 操做 String 、List 等:http://www.runoob.com/redis/redis-java.html安全
首先咱們若是每次使用緩存都生成一個 Jedis 對象的話,這樣意味着會創建不少 socket 鏈接,形成系統資源被不可控調用,甚至會致使奇怪錯誤的發生。微信
若是使用單例模式,在線程安全模式下適應不了高併發的需求,非線程安全模式又可能會出現與時間相關的錯誤。網絡
所以,爲了不這些問題,引入了池的概念 JedisPool。JedissPool 是一個線程安全的網絡鏈接池,咱們能夠經過 JedisPool 建立和管理 Jedis 實例,這樣能夠有效的解決以上問題以實現系統的高性能。
咱們能夠理解成項目中的數據庫鏈接池,例如:阿里巴巴的 druid~
優勢 | 缺點 | |
---|---|---|
直連 | 簡單方便適用於少許長期鏈接的場景 | 存在每次新建/關閉TCP開銷,資源沒法控制,存在鏈接泄露的可能,Jedis對象線程不安全 |
鏈接池 | Jedis預先生成,下降開銷,鏈接池的形式保護和控制資源的使用 | 相對於直連,使用相對麻煩,尤爲在資源管理上須要不少參數來保證,一旦規劃不合理也會出現問題。 |
private static JedisPool pool = null;
if( pool == null ){
JedisPoolConfig config = new JedisPoolConfig();
控制一個pool可分配多少個jedis實例,經過pool.getResource()來獲取;
若是賦值爲-1,則表示不限制;若是pool已經分配了maxActive個jedis實例,則此時pool的狀態爲exhausted(耗盡)。
config.setMaxTotal(50);
控制一個pool最多有多少個狀態爲idle(空閒的)的jedis實例。
config.setMaxIdle(5);
表示當borrow(引入)一個jedis實例時,最大的等待時間,若是超過等待時間,則直接拋出JedisConnectionException;單位毫秒
小於零:阻塞不肯定的時間, 默認-1
config.setMaxWaitMillis(1000*100);
在borrow(引入)一個jedis實例時,是否提早進行validate操做;若是爲true,則獲得的jedis實例均是可用的;
config.setTestOnBorrow(true);
return 一個jedis實例給pool時,是否檢查鏈接可用性(ping())
config.setTestOnReturn(true);
connectionTimeout 鏈接超時(默認2000ms)
soTimeout 響應超時(默認2000ms)
}
獲取實例
public static Jedis getJedis() {
return pool.getResource();
}
釋放 redis
public static void returnResource(Jedis jedis) {
if(jedis != null) {
jedis.close();
}
}
JedisPool的配置參數大部分是由JedisPoolConfig的對應項來賦值的。
經過最開始的簡單概述,咱們瞭解到 SpringDataRedis(RedisTemplate) 相對於 Jedis 來講能夠方便地更換 Redis 的 Java 客戶端,比 Jedis 多了自動管理鏈接池的特性,方便與其餘 Spring 框架進行搭配使用如:SpringCache;
或者能夠理解成,redisTemplate 是對 Jedis 的對 redis 操做的擴展,有更多的操做, 封裝使操做更便捷。
首先說一下,序列化,由於 redis 存儲的數據必需要通過序列化處理。
那麼你要知道 SDK 默認採用的序列化策略有兩種,一種是 String 的序列化策略,一種是 JDK 的序列化策略。
在說如何使用以前再引伸出來個 StringRedisTemplate….
經過上邊咱們清楚了 RedisTemplate ,可是這個 StringRedisTemplate 又是個啥呢?
其實做用是同樣的? what???
其實他們二者之間的區別主要在於他們使用的序列化類。
RedisTemplate 使用的是 JdkSerializationRedisSerializer (JDK 序列化)
StringRedisTemplate 使用的是 StringRedisSerializer(String 序列化)
RedisTemplate :
RedisTemplate 使用的序列類在在操做數據的時候,好比說存入數據會將數據先序列化成字節數組,而後在存入 Redis 數據庫,這個時候打開 Redis 查看的時候,你會看到你的數據不是以可讀的形式展示的,而是以字節數組顯示,相似下面:
StringRedisTemplate
當Redis當中的數據值是以可讀的形式顯示出來的時候,只能使用StringRedisTemplate才能獲取到裏面的數據。
因此當你使用RedisTemplate獲取不到數據的時候請檢查一下是否是Redis裏面的數據是可讀形式而非字節數組。
序列化總結
當你的 redis 數據庫裏面原本存的是字符串數據或者你要存取的數據就是字符串類型數據的時候,那麼你就使用 StringRedisTemplate 便可,可是若是你的數據是複雜的對象類型,而取出的時候又不想作任何的數據轉換,直接從 Redis 裏面取出一個對象,那麼使用RedisTemplate 是更好的選擇。
不太喜歡寫長篇文章,總感受太長的篇幅本身都不喜歡看下去,因此就此總結一下,實戰就放下一篇吧。
Jedis 是 Redis 官方推薦的面向 Java 操做 Redis 的客戶端,但在項目中使用 Jedis jedis = new Jedis("xxx"); 的操做有失大雅,就比如還在用 servlet…,同時用 JedisPool 來得到鏈接進行 get、set、del 等操做也相對簡單,可是須要注意的是,存入 Redis 是須要序列化的,至於選擇哪一種序列化須要本身抉擇;
再說到 RedisTemplate,Spring 針對 Redis 的使用,封裝了一個比較強大的 Template ,在沒有這個 Template 以前,是使用 Jedis 直連進行相應的交互操做,值得一提的是,作這個封裝的是 SpringData,簡單瞭解一下 SpringData:
Spring Data: Spring 的一個子項目。用於簡化數據庫訪問,支持NoSQL和關係數據庫存儲。其主要目標是使數據庫的訪問變得方便快捷。
Spring Data 項目所支持 NoSQL 存儲:
- - MongoDB(文檔數據庫)
- - Neo4j (圖形數據庫)
- - Redis(鍵/值存儲)
- - Hbase(列族數據庫)
Spring Data 項目所支持的關係數據存儲技術:
- - JDBC
- - JPA
從以前瞭解的 SpringDataJpa,咱們不難想象,RedisTemplate 的使用也必定是很是簡單的,下一篇看一下項目中的應用。
最後:來都來了,左上角不關注一下嗎。
若是文章有錯的地方歡迎指正,你們互相留言交流。習慣在微信看技術文章,想要獲取更多的Java資源的同窗,能夠關注微信公衆號:niceyoo