1. 程式人生 > >Redis 入門到分散式實踐

Redis 入門到分散式實踐

課程簡介

這是一門 Redis 從零基礎開始逐步成為 Redis 專家的進階教程,主要包括認識 Redis、基礎 API 的理解和使用、使用 Redis 客戶端、Redis 高階功能、Redis 持久化和開發運維常用問題探討、Redis 複製的原理和優化策略、Redis 分散式解決方案、叢集和故障轉移等核心內容,系統而全面地剖析 Redis 的應用。

經過此達人課的學習,你將獲得 Redis 至少三年的開發經驗。如果你是程式設計師,在大資料時代下,我們需要有一個大資料的概念,一個好的程式設計師必須要理解大和小的概念,使用 Redis 的專案均具有龐大的資料量和訪問量,這就要求我們不僅需要有良好的程式碼意識,還需要在未來大資料時代中對專案有更好的擴充套件能力。

作者介紹

陳寵,現任某汽車IT公司資深 Java 高階工程師、IT寫作者。精通多門程式語言,主攻 Java 後臺開發,具有 8 年 Java 開發經驗和資料庫開發經驗,特別有著三年的 Redis 研發經驗,對大型高併發快取架構有深刻的認識。做過大型電商系統,大型企業售後系統等億級流量的專案,經歷了多個從小型專案發展到大型專案的全過程,同時也致力於在 IT 領域幫助更多初學的程式設計師,給他們帶來更多的啟發和認識。

課程內容

第01課:為什麼我們要使用 Redis

導言

如果你從來沒使用過 Redis 資料庫,那你肯定會問,為什麼我們要學 Redis資料庫,我只使用 MySQL 或 Oracle 就夠了。其實 Redis 雖叫資料庫,可又不是傳統意義上的關係型資料庫,Redis 是一個高效能的 Key-value 資料庫。

首先我們先來講一下 Redis 的歷史。Redis 其實是作者 Salvatore Sanfilippo 為了解決實際問題而創造出來的。當時作者 Salvatore 有這麼一個需求,就是多個網站不斷向伺服器傳送頁面,而伺服器需要為每個網站儲存一定數量的最新頁面記錄,同時通過網頁將資料實時給使用者看到。但是無論 Salvatore 如何優化,都很難在關係資料庫裡讓小虛擬機器處理大負荷的負載。最終他打算自己寫一個記憶體資料庫,能對列表的兩端執行常數時間複雜度的彈出和推入操作,並加上子程序的持久化操作,於是 Redis 就誕生了。

到了今天,Redis 已經進入了成熟期。數以千計的開發者都在開發和使用這個資料庫,Redis 擁有非常完善的文件。我記得第一次使用 Redis,是為了在儲存有數十百萬使用者的關係資料庫裡對某個條件進行查詢。大家知道,要想在幾百萬使用者中找到某條資料,是很難通過關係資料庫在十幾秒查詢到的。於是我選擇了 Redis,在不斷優化後每次操作可以控制在 1 秒鐘甚至更短,帶給我相當大的震撼。

本教程不但教給你一些基本的使用,同時也會根據我多年總結的技巧解決日常生產環境上優化和排錯的問題。特別是後期的資料庫優化和叢集的講解,希望對各位進行 Redis 開發有一定幫助。

認識 Redis

在 Redis 之前,很多網際網路公司會使用 MySql + Memcached 架構,這個架構雖然適合於海量資料儲存,但隨著業務的增加,會出現很多問題,例如,MySQL 資料庫經常拆表,導致 Memcached 也不斷擴容;同步問題;命中率低,導致直接穿透 Memcached 進入 DB 查詢,DB資源池是有限的,進而宕機。這些問題都會導致Memcached其實並不好用。

Redis 就在這種時代背景中產生,你會發現 Memcached 遇到的問題都被 Redis 給解決了。如果你用過 Memcached,你就會感受到 Redis 絕對不是簡單的 Key-value 資料,還有 list、set、雜湊等各種資料型別的儲存,同時支援冷熱備份和主從複製,不但解決了資料庫的容錯,還能輕易地將資料分佈到多個 Redis 例項中。

那麼 Redis 有哪些具體特性呢?大致可分為如下八大特性。

特性一,速度極快。官方給出的資料是 10 萬次 ops 的讀寫,這主要歸功於這些資料都存在於記憶體中。由於 Redis 是開源的,當你開啟原始碼,就會發現 Redis 都是用 C 語言寫的,C 語言是最接近計算機語言的程式碼,而且只有區區 5 萬行,保證了 Redis 的速度。同時一個 Redis 只是一個單執行緒,其真正的原因還是因為單執行緒在記憶體中是效率最高的。

特性二,持久化。Redis 的持久化可以保證將記憶體中的資料每隔一段時間就保存於磁碟中,重啟的時候會再次載入到記憶體。持久化方式是 RDB 和 AOF。

特性三,支援多種資料結構。分別支援雜湊、集合、BitMaps,還有點陣圖(多用於活躍使用者數等統計)、HyperLogLog(超小記憶體唯一值計數,由於只有 12K,是有一定誤差範圍的)、GEO(地理資訊定位)。

特性四,支援多種程式語言。支援Java、PHP、Python、Ruby、Lua、Nodejs。

特性五,功能豐富。如釋出訂閱、Lua 指令碼、事務、Pipeline(管道,即當指令到達一定數量後,客戶端才會執行)。

特性六,簡單。不依賴外部庫、單執行緒、只有 23000 行 Code。

特性七,主從複製。主節點的資料做副本,這是做高可用的基石。

特性八,高可用和分散式。Redis-Sentinel(v2.8)支援高可用,Redis-Cluster(v3.0)支援分散式。

那麼 Redis 用在哪些場景呢?

Redis 最大的作用是增加你原來的訪問效能問題,試想如果專案已經搭建好,這個專案一般是不太可能更換的。但是 Redis 獨特的存在是隻需要增加一層,把常用的資料存放在 Redis 即可。你在開發環境中使用 Redis 功能,但卻不需要轉到 Redis。

無論是什麼架構,你都可以將 Redis 融入專案中來,這可以解決很多關係資料庫無法解決的問題。比如,現有資料庫處理緩慢的任務,或者在原有的基礎上開發新的功能,都可以使用 Redis。接下來,我們一起看看 Redis 的典型使用場景。

1.快取系統。這是 Redis 使用最多的場景。Redis 能夠替代 Memcached,讓你的快取從只能儲存資料變得能夠更新資料,因此你不再需要每次都重新生成資料。毫無疑問,Redis 快取使用的方式與 Memcache 相同。網路中總是能夠看到這個技術更新換代,Redis 的原生命令,儘管簡單卻功能強大,把它們加以組合,能完成的功能是無法想象的。當然,你可以專門編寫程式碼來完成所有這些操作,但 Redis 實現起來顯然更為輕鬆。

enter image description here

2.計數器。如轉發數、評論數,有了原子遞增(Atomic Increment),你可以放心的加上各種計數,用GETSET重置,或者是讓它們過期。目前新浪是號稱史上最大的 Redis 叢集。

比如,你想計算出最近使用者在頁面間停頓不超過 30 秒的頁面瀏覽量,當計數達到比如 10 時,就可以顯示提示。再比如,如果想知道什麼時候封鎖一個 IP 地址,INCRBY命令讓這些變得很容易,通過原子遞增保持計數;GETSET用來重置計數器;過期屬性用來確認一個關鍵字什麼時候應該刪除。

3.訊息佇列系統。雖然 Kafka 更強,但是簡單的可以使用 Redis。執行穩定並且快速,支援模式匹配,能夠實時訂閱與取消頻道。

Redis 還有阻塞佇列的命令,能夠讓一個程式在執行時被另一個程式新增到佇列。你也可以做些更有趣的事情,比如一個旋轉更新的 RSS Feed 佇列。

4.排行榜及相關問題。實際就是一種有序集合。對於 Redis 來說,如果你要在幾百萬個使用者中找到排名,其他資料庫查詢是非常慢的,因為每過幾分鐘,就會有幾百萬個不同的資料產生變化,但是 Redis 卻可以輕鬆解決。

排行榜(Leader Board)按照得分進行排序。ZADD 命令可以直接實現這個功能,而 ZREVRANGE 命令可以用來按照得分獲取前 100 名的使用者,ZRANK 可以用來獲取使用者排名,非常直接而且操作容易。

5.社交網路。Redis 可以非常好地與社交網路相結合,如新浪微博、Twiter等,比如QQ和使用者互動的時候,使用者和狀態訊息將會聚焦很多有用的資訊,很多互動如實時聊天就是通過 Redis 來實現的。

6.按照使用者投票和時間排序。Reddit 的排行榜,得分會隨著時間變化。LPUSH 和 LTRIM 命令結合運用,把文章新增到一個列表中。一項後臺任務用來獲取列表,並重新計算列表的排序,ZADD 命令用來按照新的順序填充生成列表。列表可以實現非常快速的檢索,即使是負載很重的站點。

7.過期專案處理。通過 Unix 時間作為關鍵字,用來保持列表能夠按時間排序。對 currenttime 和 timeto_live 進行檢索,完成查詢過期專案的艱鉅任務。另一項後臺任務使用 ZRANGE...WITHSCORES 進行查詢,刪除過期的條目。

8.實時系統。使用點陣圖來做布隆過濾器,例如實現垃圾郵件過濾系統的開發變的非常容易。

綜上所述, Redis 的應用是非常廣泛的,而且在實際使用中是非常有價值的。你可以讓網站向 100 萬用戶推薦新聞、可以實時顯示最新的專案列表、在遊戲中實時獲得排名、獲得全球排名等等。Redis 的出現,解決了傳統關係資料庫的短板,讓開發變的更加簡單和高效,大大提高了開發效率,也在使用者體驗上獲得更加實時的體驗。隨著 Redis 的使用越來越廣泛,將會有更多的開發者加入 Redis 的使用和開發上來。

小結

最後我們回顧下本文所講述的內容。

首先,介紹了 Redis 主要是用於快取系統的,不同於一般關係資料庫。

其次,我們介紹了 Redis 的八大特性。通過這八大特性,我們可以把經常變化的資料放在 Redis 資料庫中,並設定過期時間,到達時間 Redis 就會自動刪除;還可以緩解伺服器壓力,如我們日常發微博,先會儲存在 Redis 資料庫中,然後等資料庫壓力比較小的時候儲存進關係資料庫中。

最後,我們介紹了 Redis 用在哪些場景下。相信通過這些介紹,你應該對 Redis 有個比較詳細的認識。接下去我們將實際使用 Redis。

第02課:API 的理解與使用

前面我們大致瞭解了 Redis 是什麼,接下來我們就來使用 Redis。

如何使用 Redis?首先我們需要根據 Redis 提供的 7 種資料型別來了解它,分別是字串 String、雜湊 Hash、列表 List、集合 Set、有序集合 Sorted Set、釋出訂閱 Pub/Sub、事務 Transactions。

我們先來講一下 Redis 的內部實現和執行機制。在使用 Redis 時,命令多使用就會很容易記住,這歸功於 Redis 的命令簡單。但是內部實現和它的單執行緒,你必須先了解原理,再瞭解 7 種資料型別,這樣才能在實際開發中遊刃有餘。

內部實現

接下來,我們簡單瞭解下 Redis 的內部實現。Redis 內部會封裝一個 redisObject 例項。由這個 redisObject 來表示所有的 key 和 value。redisObject 所包含的欄位中,最主要的是 type 和 encoding。

1.type 代表一個 value 物件具體是何種資料型別,包括 String、Hash、List、Set和Sorted set等資料型別。

2.encoding 則表示不同資料型別在 Redis 內部的儲存方式,包括 Raw、Int、Ziplist、LinkedList、HashMap 和 Intset 儲存方式。

上面說的比較抽象,為了幫助大家理解,我舉個例子,比如 type 為 String 代表的是 value 儲存了一個字串,那麼對應的 encoding 可以是 Int 或者 Raw。如果是 Int 則代表實際 Redis 內部是按數值型別儲存的,比如你要儲存“1234”、“2018”等字串。

還有一個特別的內部欄位,vm 欄位。這個欄位預設是關閉的,只有打開了 Redis 的虛擬記憶體功能,才能真正分配記憶體。有同學要問了,這個欄位有什麼用呢?因為 Redis 是 key/value 儲存,是非常浪費記憶體的,這些記憶體成本主要是為了給Redis 上面的 7 種資料型別提供統一管理介面。

單執行緒

我們再來看下為什麼 Redis 中單執行緒快。很多程式設計師應該深有體會,其實其他很多語言單執行緒是非常慢的,但是為什麼 Redis 的單執行緒快呢?

我覺得最大的原因是純記憶體儲存。正因為這個是主要原因,所以後面兩個原因顯得有點不太重要,即非阻塞 IO 和避免執行緒切換和競態消耗

你要清楚,首先 Redis 一次只執行一條命令。其次我們應該減少長命令,哪些是長命令呢?如 KEYS、FLUSHALL、FLUSHDB、Slow Lua Script、MULTI/EXEC、Operate Big Value(Collection)。最後說明一點,其實 Redis 不只是單執行緒,如果你去讀原始碼,你就會發現有些指令絕不是單執行緒能夠做的。如 Fysnc File Descriptor、Close File Descriptor等。

7 種資料型別的使用

字串 String

Redis 的 key 沒什麼好說,值得一提的就是 value 的五種資料型別。分別是字串型別、數字、二進位制、和 JSON 型別的資料。

那我們在實際生產環境中有哪些場景使用呢?如快取、計數器(每次加 1 的計數)、分散式鎖等場景都能看到。

接著我將列出與該資料型別相關的命令及使用說明。

1.GET、SET 和 DEL

這是 Redis 最簡單的命令,如果你要得到一個 value 的值,只需要 GET key,就 ok 了。如果你要設定某個 key 的值,那就 SET key value,搞定。

2.INCR、DECR、INCRBY、DECRBY

  • INCR key:就是 key 自增 1,不存在,自增後 get(key)=1;
  • DECR key:就是 key 自減 1,不存在,自減後返回 -1;
  • INCRBY key k:自增 k ,不存在,則返回 k;
  • DECRBY key k:自減 k 。
實際使用

如果你想訪問某個主頁的訪問量,那可以用 INCR id:pageview。

我們實際開發中,常常會使用下面的虛擬碼。

public VideoInfo get(long id){    String redisKey = redisPrefix + id;    VideoInfo videoInfo = redis.get(redisKey);    if(videoInfo == null){        videoInfo = mysql.get(id);        if(videoInfo != null){            // 序列化            redis.set(redisKey, serialize(videoInfo));        }    }    return videoInfo;}

3.SET、SETNX、SET xx

  • SET key value:不管 key 是否存在,都設定;
  • SETNX key value:key 不存在,才設定(相當於 add);
  • SET key value xx:key 存在,才設定(相當於 update)。

實際操作,見如下程式碼。

exists php --> 0set php good -->OKsetnx php bad -->0set php best xx -->okexists lua --> 0set lua hehe xx -->(nil)

4.MGET、MSET

  • MGET key1 key2 key3 ...:批量獲取 key,原子操作;
  • MSET key1 val2 key2 val2 key3 val3:批量設定 key-value。

實際開發的過程中,我們通常使用 MGET,因為 MGET 只有 1 次網路時間和 n 次命令時間。但是如果你使用 GET 的話,就是 n 次網路時間和 n 次命令時間。

使用 MGET 效率更高。

5.GETSET、APPEND、STRLEN

  • GETSET key newvalue:set key newvalue 並返回舊的 value,舊的 value 會被刪除;
  • APPEND key value:將 value 追加到舊的 value 上;
  • STRLEN key:返回字串的長度(注意中文)。

6.INCRBYFLOAT、GETRANGE、SETRANGE

  • INCRBYFLOAT key 3.5:在 key 上追加對應的值 3.5;
  • GETRANGE key start end:獲取字串指定下標所有的值;
  • SETRANGE key index value:設定指定下標所有對應的值。

雜湊 Hash

說到 Hash,就要說到為什麼我們要使用 Hash。我們在使用字串的資料型別的時候,如果我們儲存的是個物件,比如某個圖書館的會員,裡面儲存著會員的姓名、年齡、身份證資訊、地址、借閱書籍、借閱時間……一系列的屬性。

如果我們用 String 來儲存的話,那我們就需要每次都序列化這個字串,每次只要一修改某個屬性,我們就要把一串屬性都覆蓋一遍。這樣是不是非常麻煩?

這個時候,雜湊就應運而生了。Hash 相當於 value 是一個 Map,裡面的所有屬性我們都可以單獨新增、修改或者刪除,而不需要像字串那樣全部覆蓋操作。

常用的命令有HGET、HSET、HGETALL。

  • HGET key field:獲取儲存在雜湊表中指定欄位的值。
  • HSET key field value:將雜湊表 key 中的欄位 field 的值設為 value。
  • HGETALL key:獲取在雜湊表中指定 key 的所有欄位和值,生產環境不常用

列表 List

List 是一種簡單的字串的集合,是有順序的。在實際生產環境中,我們時常會使用它。比如當我們需要獲取某個資料的列表(例如粉絲列表)。

由於 Redis 的 List 是連結串列結構,我們可以非常輕鬆的實現訊息排行等功能,還能用於訊息佇列等功能。

常用的命令有LPUSH、RPUSH、LPOP、RPOP、LRANGE。

  • LPUSH key value1 [value2]:將一個或多個值插入到列表頭部;
  • RPUSH key value1 [value2]:在列表中新增一個或多個值;
  • LPOP key:移出並獲取列表的第一個元素;
  • RPOP key:移除並獲取列表最後一個元素;
  • LRANGE key start stop:獲取列表指定範圍內的元素。

集合 Set

Set 和 String 最大的不同是無序,Set 是沒有順序的。集合成員是唯一的,這就意味著集合中不能出現重複的資料。

常用命令有SADD、SCARD、SNENVERS、SPOP。

  • SADD key member1:向集合新增一個或多個成員;
  • SCARD key:獲取集合的成員數;
  • SMEMBERS key:返回集合中的所有成員;
  • SPOP key:移除並返回集合中的一個隨機元素。

Sorted Set 有序集合

Sorted Set 和 Set 最大的不同是前者是自動排序的,而後者是無序的。如果你需要一個有序的,但是不重複的資料結構的,就可以使用sorted set。

常用的命令有 ZADD、ZRANGE、ZREM、ZCARD。

  • ZADD key score1 member1:向有序集合新增一個或多個成員,或者更新已存在成員的分數;
  • ZRANGE key start stop:通過索引區間返回有序集合成指定區間內的成員;
  • ZREM key member:移除有序集合中的一個或多個成員;
  • ZCARD key:獲取有序集合的成員數。

Pub/Sub 釋出訂閱

即釋出(Publish)與訂閱(Subscribe)。在 Redis 中,你可以設定對某一個 key 值進行訊息釋出及訊息訂閱,當 key 的值進行了訊息釋出後,所有訂閱它的客戶端都會收到相應的訊息,這類似於 QQ、微信。

常用的命令有PSUBSCRIBE、PUBSUB、PUBLISH、SUBSCRIBE。

  • PSUBSCRIBE pattern:訂閱一個或多個符合給定模式的頻道;
  • PUBSUB subcommand:檢視訂閱與釋出系統狀態;
  • PUBLISH channel message:將資訊傳送到指定的頻道;
  • SUBSCRIBE channel:訂閱給定的一個或多個頻道的資訊;
  • UNSUBSCRIBE [channel [channel ...]]:指退訂給定的頻道。

Transactions 事務

我們一般認為 NoSQL 資料庫都沒有事務,恐怕要讓你失望了。Redis 就支援事務,但並不是我們一般意義上的事務,如果你執行 exec 命令,途中斷電或者伺服器掛掉了,我們還是會發現 Redis 裡一部分插入了,一部分未插入。

不過 Redis 提供了 WATCH 命令,我們可以對某個 key 來 watch 一下,然後再執行 Transactions。如果這個被Watch 的值進行了修改,那麼這個 Transactions 會發現並拒絕執行。

redis 127.0.0.1:6381> MULTIOKredis 127.0.0.1:6381> SET book-name "JAVA Programming Mastering Series"QUEUEDredis 127.0.0.1:6381> GET book-nameQUEUEDredis 127.0.0.1:6381> SADD tag "java" "Programming" "Mastering Series"QUEUEDredis 127.0.0.1:6381> SMEMBERS tagQUEUEDredis 127.0.0.1:6381> EXEC1) OK2) "JAVA Programming Mastering Series"3) (integer) 34) 1) "java"   2) "Programming"   3) "Mastering Series"

常用命令有 MULTI、EXEC、DISCARD。

  • MULTI:標記一個事務塊的開始;
  • EXEC:執行所有事務塊內的命令;
  • DISCARD:取消事務,放棄執行事務塊內的所有命令;
  • UNWATCH:取消 WATCH 命令對所有 key 的監視;
  • WATCH key:監視 key,如果在事務執行之前 key 被其他命令所改動,那麼事務將被打斷。

Redis 作為一個數據庫,很多開發者還可以單獨使用它。事實上,更多時候 Redis 是在資料庫和程式碼中間作為一箇中間件使用,如果你發現你目前的資料庫出現瓶頸,那麼你就可以通過 Redis 來優化。

第03課:如何使用 Redis客戶端

之前在學習 Redis 基礎的時候,我們都是使用 Redis 的命令列。但是除了命令列,還有主流的語言支援的客戶端。如果你開啟 Redis 的官網,裡面找到 Clients,就能找到你熟悉的語言對應的客戶端,如下圖所示。

enter image description here

本文我們將主要講解 redis-py(Python 客戶端)、Jedis(Java 客戶端),其他語言的客戶端也都差不多。當你選擇某個語言點進去後,你會發有笑臉和黃色五角星。五角星表示 Redis 推薦的,笑臉表示社群比較活躍。建議選擇有笑臉和五角星的客戶端。

Python 客戶端 redis-py

正確獲取 redis-py

首先我們必須安裝 Redis,注意不是安裝 redis-py。開啟你的命令列,如果你使用 CentOS 或者 Mac 系統,請直接使用 pip 工具安裝。如果沒有 pip,請先進行安裝。下面我們介紹下如何安裝它,已經安裝的可以直接忽略。

1.下載 pip。進入 https://pypi.python.org/pypi/pip,下載第二項。

2.解壓安裝。

解壓下載的檔案(Windows 下用解壓工具,如RAR,Linux 下終端輸入 tar -xf pip-9.0.1.tar.gz,即tar -xf 檔名),進入解壓後的資料夾中,調出命令列視窗或者終端。

在 Windows 下輸入:

python setup.py install

在Linux下輸入:

sudo python setup.py install

安裝成功後測試下,輸入以下命令,輸出 pip 版本號即表示安裝成功。

pip -v

然後選擇執行以下 pip 命令,安裝 Redis。

  • pip install redis,如果你使用的是 CentOS 系統,開啟命令列,使用該命令安裝;
  • easyinstall redis,如果使用 Ubuntu 系統,使用easyinstall 來安裝

當然你也可以使用原始碼安裝,如下。

 git clone https://github.com/andymccurdy/redis-py.git   cd redis-py  //進入redis-py目錄 python setup.py install //開始安裝

使用 redis-py 客戶端

要使用 redis-py 客戶端,我們需通過程式碼來連線。如何連線呢?開啟你的 Python 編輯器。

redis-py 提供了兩個類:StrictRedis 和 Redis,用於實現 Redis 的命令,這裡推薦使用 StrictRedis。StrictRedis 實現了絕大部分官方的命令,並且使用原生的語法和命令。比如,SET 命令對應著 StrictRedis.set 方法。下面是個簡單的例子。

//程式碼連線Redisimport redis // 匯入Redisclient = redis.StrictRedis(host='127.0.0.1',port=6379) // 通過 redis.StrictRedis 連線 Rediskey = "welcome"setResult = client.set(key, "redis-py") // SET命令print setResult //列印這個值value = client.get(key) //在 Redis 使用 GET 命令獲取 key 的值print "key = "+ key +" value="+value //列印

簡單的使用

上面我們講了如何連線 redis-py 客戶端,下面我們使用各種資料型別來設定和獲取資訊,後面都有註釋。每個序號表示一種資料型別。

1.String

client.set("redis","helloworld") // redis返回Trueclient.get("redis") // redis返回helloworldclient.incr("counter") //自增+1

2.Hash

client.hset("hashvalue","a1","b1") // hash設定hashvalue的值1client.hset("hashvalue","a2","b2")// hash設定hashvalue的值2client.hgetall("hashvalue") // redis返回{a1:b1,a2:b2}

3.List

client.rpush("listvalue","a") // list設定是rpushclient.rpush("listvalue","b")client.rpush("listvalue","c")client.lrange("listvalue",0,-1) // redis返回['a','b','c']

4.Set

client.sadd("setvalue","a") // set設定是saddclient.sadd("setvalue","b")client.sadd("setvalue","c")client.smembers("setvalue") // setredis返回['a','b','c']

5.Zset

client.zadd("zsetvalue","1","book1") // zset設定是zaddclient.zadd("zsetvalue","2","book2")client.zadd("zsetvalue","3","book3")client.zrange("zsetvalue",0,-1,withscores=True) // withscores表示含索引值,redis返回[('book3',3.0),('book2',2.0),('book1',1.0)]

怎麼樣,這些方法簡單嗎?我們再來講一下使用 Java 客戶端。

Java客戶端 Jedis

正確獲取 Jedis

方式一,jar 包的獲取,相信很多剛學 Java 的朋友就是這麼找包的,這裡不推薦,推薦大家使用 Maven。關於如何使用 Maven,大家可以找度娘,實在搞不定也可以諮詢我。

當然如果你需要使用 Redis 連線池,那你還需要一個 jar 包(還是不推薦,建議用 Maven),點選這裡,獲取下載地址。

方式二,使用 Maven 管理,只有在 Maven 裡增加了 Jedis 客戶端的配置,才能執行下面的程式碼,否則報錯。

<dependency>    <groupId>redis.clients</groupId>    <artifactId>jedis</artifactId>    <version>2.9.0</version></dependency>

使用 Jedis 客戶端

使用 Jedis 也是非常簡單,只需要 new 一個 Jedis 物件,然後呼叫 SET 和 GET 就 OK 了,簡單吧。

    Jedis jedis = new Jedis("127.0.0.1",6379); // Ip, 埠,連線超時,讀寫超時    jedis.set("hello","world");    jedis.get("hello");    jedis.close(); // 記得要close掉,這是一個良好的習慣。

簡單的使用

連線完 Jedis,我們再介紹一下常用的三種資料型別,其他的參照 redis-py,都是大同小異。

1.String

jedis.set("hello","world"); //string是最常用的,用set設定jedis.get("hello"); // get獲取jedis.incr("counter"); //自增1

2.Hash

jedis.hset("hello","v1","f1"); //hash設定用hsetjedis.hset("hello","v2","f2");  jedis.hgetAll("hello"); // redis返回{v1=f1,v2=f2}

3.List

jedis.rpush("vss","1"); //list設定用rpushjedis.rpush("vss","2");jedis.rpush("vss","3");    jedis.lrange("vss",0,-1); //redis返回[1,2,3]

當然,我們不僅要使用 Redis,還會使用 Jedis 的連線池。為什麼要使用連線池呢?因為 Jedis 物件不是執行緒安全的,在多執行緒下會發生併發問題。為了避免這些問題,Jedis 提供了 JedisPool 連線池,示例程式碼如下。

GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); //JedisPool是單例的,需要new一個GenericObjectPoolConfig物件JedisPool jedisPool = new JedisPool(poolConfig,"127.0.0.1",6379); // 建立連線池的連線Jedis jedis = null; // 類似於new一個jedis物件try{    jedis = jedisPool.getResource(); // 從連線池獲取Jedis物件    jedis.set("hello","world"); // 設定}catch(Exception e){    e.printStackTrace();}finally{    if(jedis!=null){    jedis.close();// 注意不是關閉,而是歸還到連線池    }}

其他語言都可以參照上面的 Python 和 Java 的客戶端,內容方面都差不多,而且 Jedis 主要是掌握其原理和流程,操作其實是非常簡單的。如果你有什麼疑問,不妨給我留言。

如果你需要了解對應的 API,請點選這裡,從中選擇你要用的語言對應的客戶端。