介紹
Redis
是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息中間件。 它支持多種類型的數據結構,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 與範圍查詢, bitmaps, hyperloglogs 和 地理空間(geospatial) 索引半徑查詢。 Redis 內置了 複製(replication),LUA腳本(Lua scripting), LRU驅動事件(LRU eviction),事務(transactions) 和不同級別的 磁盤持久化(persistence), 並通過 Redis哨兵(Sentinel)和自動 分區(Cluster)提供高可用性(high availability)。
版本
官方版本
目前官方版本支持Linux
系統和Ubuntu
系統。官方下載地址:http://redis.io/download
由於我們的開發項目以Windows爲主,所以在此不對官方版本做詳細介紹,有興趣的可以到官網查看。
非官方版本(Windows 版本)
官方沒有Redis
的Windows版本,但是微軟開源技術團隊(Microsoft Open Tech group)自行開發和維護了一個 Win64 的版本。
- 微軟團隊只提供了官方64位版本,而32位版本,需要自己從源代碼構建。
- Released版本中提供了msi文件,Redis
可以作爲Windows服務安裝
安裝服務
- 下載Win64的壓縮文件到一個指定文件夾
- 打開一個 cmd 窗口 使用cd命令切換目錄到解壓縮的文件夾下運行
redis-server.exe redis.windows.conf
redis-server.exe
啓動Redis服務redis.windows.conf
Redis服務的一些配置,不寫則會調用默認設置- 端口號默認
6379
可以通過修改配置文件redis.windows-service.conf
修改或CONFIG set
命令修改
運行客戶端
- 打開一個 cmd 窗口 使用cd命令切換目錄到解壓縮的文件夾運行
redis-cli.exe -h 127.0.0.1 -p 6379
redis-cli.exe
啓動Redis客戶端-h 127.0.0.1
服務器IP地址-p 6379
服務器端口號
優點
- 速度快,因爲數據存在內存中,類似於HashMap,HashMap的優勢就是查找和操作的時間複雜度都是O(1)
- 支持豐富數據類型,支持string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
- 支持事務,操作都是原子性,所謂的原子性就是對數據的更改要麼全部執行,要麼全部不執行
- 豐富的特性,可用於緩存,消息,按key設置過期時間,過期後將會自動刪除
缺點
- redis存儲成本高(純使用內存,單臺機器,存儲的數據量,跟機器本身的內存大小有關),所以不能當做海量數據庫來用。雖然redis本身有key過期策略,但是還是需要提前預估和節約內存。如果內存增長過快,需要定期刪除數據。
- 如果進行完整重同步,由於需要生成rdb文件,並進行傳輸,會佔用主機的CPU,並會消耗現網的帶寬。不過redis2.8版本,已經有部分重同步的功能,但是還是有可能有完整重同步。比如,新上線的備機。
- 修改配置文件,進行重啓,將硬盤中的數據加載進內存,時間比較久。在這個過程中,redis不能提供服務。
適合應用場景
redis是一種k/v的內存數據庫,適合小數據量的存儲以及實時要求高的地方,用來存儲一些需要頻繁調取的數據,這樣可以大大節省系統直接讀取磁盤來獲得數據的I/O開銷,更重要的是可以極大提升速度,但是不適合做完整數據庫,完整數據庫基本上都有一套詳細解決方案。
Java 使用 Redis
安裝
- 安裝 Redis 服務
- 配置 Java 運行環境,確保能正常使用Java
- 安裝 Java Redis 驅動
jedis.jar
連接到 redis 服務
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());
}
}
存取String類型的數據
import redis.clients.jedis.Jedis;
public class RedisStringJava {
public static void main(String[] args) {
//連接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
//設置 redis 字符串數據
jedis.set("runoobkey", "www.runoob.com");
// 獲取存儲的數據並輸出
System.out.println("redis 存儲的字符串爲: "+ jedis.get("runoobkey"));
}
}
編譯結果:
連接成功
redis 存儲的字符串爲: www.runoob.com
存取List類型的數據
import java.util.List;
import redis.clients.jedis.Jedis;
public class RedisListJava {
public static void main(String[] args) {
//連接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
//存儲數據到列表中
jedis.lpush("site-list", "Runoob");
jedis.lpush("site-list", "Google");
jedis.lpush("site-list", "Taobao");
// 獲取存儲的數據並輸出
List<String> list = jedis.lrange("site-list", 0 ,2);
for(int i=0; i<list.size(); i++) {
System.out.println("列表項爲: "+list.get(i));
}
}
}
編譯結果:
連接成功
列表項爲: Taobao
列表項爲: Google
列表項爲: Runoob
存取的Keys
import java.util.Iterator;
import java.util.Set;
import redis.clients.jedis.Jedis;
public class RedisKeyJava {
public static void main(String[] args) {
//連接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
// 獲取數據並輸出
Set<String> keys = jedis.keys("*");
Iterator<String> it=keys.iterator() ;
while(it.hasNext()){
String key = it.next();
System.out.println(key);
}
}
}
編譯結果:
連接成功
runoobkey
site-list
Redis發佈與訂閱
Redis 發佈訂閱(pub/sub)是一種消息通信模式:發送者(pub)發送消息,訂閱者(sub)接收消息。
訂閱頻道
通過SUBSCRIBE
命令客戶端可以訂閱指定的頻道,當這個頻道有其他客戶端推送的消息時,當前客戶端就會收到。
例:訂閱first和second頻道
SUBSCRIBE first second
消息推送
通過PUBLISH
命令客戶端可以向指定頻道推送消息,訂閱這個頻道的客戶端都會收到一條message類型的消息。
例:推送消息”Hello”到first頻道
PUBLISH first "Hello"
退訂頻道
通過UNSUBSCRIBE
命令客戶端可以推定指定頻道。如果沒有頻道被指定,即一個無參數的 UNSUBSCRIBE 調用被執行,那麼客戶端使用SUBSCRIBE
命令訂閱的所有頻道都會被退訂。在這種情況下,命令會返回一個信息,告知客戶端所有被退訂的頻道。
例:退訂second頻道
UNSUBSCRIBE second
模式匹配
Redis
的Pub/Sub實現支持模式匹配。客戶端可以訂閱全風格的模式以便接收所有來自能匹配到給定模式的頻道的消息。
- 模式匹配訂閱命令PSUBSCRIBE
- 模式匹配退訂命令UNPSUBSCRIBE
- 接收消息爲pmessage類型
SUBSCRIBE first
PSUBSCRIBE f*
PSUBSCRIBE news.*
注意:如果它訂閱的多個模式匹配了同一個發佈的消息,客戶端可能多次接收一個消息。
JAVA實現Redis消息推送
- 創建一個頻道的監聽類繼承Redis的抽象類
JedisPubSub
,並實現其抽象方法。訂閱頻道,取消訂閱,收到消息等狀態會對應調用相關的方法。 - 訂閱頻道
public class TestSubscribe {
public static void main(String[] args) {
//連接本地的 Redis 服務
Jedis jedis = new Jedis("localhost");
System.out.println("連接成功");
// 創建頻道監聽對象
RedisMsgPubSubListener listener = new RedisMsgPubSubListener();
// 訂閱頻道,綁定監聽
jedis.subscribe(listener, "redisChatTest");
}
}
注意:subscribe
是一個阻塞的方法,在取消訂閱該頻道前,會一直阻塞在這,只有當取消了訂閱纔會執行之後的代碼。
- 發送消息
Public class TestPublish {
public static void main(String[] args) {
Jedis jedis = new Jedis("localhost");
jedis.publish("redisChatTest", "Hello");
Thread.sleep(5000);
jedis.publish("redisChatTest", "Redis");
Thread.sleep(5000);
jedis.publish("redisChatTest", "Message publish");
}
}
- 退訂頻道
import redis.clients.jedis.JedisPubSub;
public class RedisMsgPubSubListener extends JedisPubSub {
...
@Override
public void onMessage(String channel, String message) {
System.out.println("channel:" + channel + "receives message :" + message);
// 退訂
this.unsubscribe();
}
...
}
參考:
http://www.redis.cn/documentation.html
http://blog.csdn.net/u013322876/article/details/53817757
http://blog.csdn.net/canot/article/details/51938955