Redis 程式設計(Idea 安裝加配置)
阿新 • • 發佈:2019-01-05
Redis 的特點
- 速度快,執行在記憶體中,執行速度非常快。
- 資料型別豐富:
- String,上限512MB
- List
- set
- sorted set,每個元素關聯一個 score,以提供排序依據
- hash,字串與字串之間的對映
- 操作原子性,所有的 Redis 操作都是原子的,保證多個客戶端併發訪問時獲取到 Redis 伺服器的值為最新值。
- 持久化,與 Memcache 不同的是,Redis 提供了資料持久化的功能,提供 AOF 和 RDB 兩種持久化模式。
- AOF,只追加資料到檔案,記錄所有的寫指令。
- RDB,先將資料寫到臨時檔案,再用臨時檔案替換上次持久化好的檔案,會單獨 fork 一個程序進行持久化,而主程序不進行任何 IO 操作。
- 應用場景豐富:快取、訊息、佇列(Redis 原生支援訂閱/釋出)、資料庫等。
Pub/Sub功能(means Publish, Subscribe)即釋出及訂閱功能。基於事件的系統中,Pub/Sub是目前廣泛使用的通訊模型,它採用事件作為基本的通訊機制,提供大規模系統所要求的鬆散耦合的互動模式:訂閱者(如客戶端)以事件訂閱的方式表達出它有興趣接收的一個事件或一類事件;釋出者(如伺服器)可將訂閱者感興趣的事件隨時通知相關訂閱者。
Redis 的主從複製
Redis 的主從同步是非同步執行的,因此主從同步並不會減少 Redis 的執行效能。給 Redis 主伺服器新增一個伺服器,只需要在從伺服器的 redis.conf 中新增 slaveof masterip masterpot 命令,先啟動主伺服器,再啟動從伺服器,從伺服器會根據配置中的主伺服器的 IP 埠對主伺服器發出同步命令,然後進行資料同步。
多組主從同步及主從切換可以通過 Redis Sentinel 進行管理,Sentinel 能對 Redis 叢集中的主伺服器及從伺服器進行管理,當主節點宕機時,Sentinel 能自動切換到從伺服器。
Redis 安裝配置
- Mac
- 下載:https://redis.io/download
- 解壓:tar zxvf redis-5.0.2.tar.gz
- 移動到: mv redis-5.0.2 /usr/local/
- 切換到:cd /usr/local/redis-5.0.2/
- 編譯測試 sudo make test
- 編譯安裝 sudo make install
- 啟動:redis-server
- For idea:Iedis
- Ubuntu Mac破解:https://blog.csdn.net/qq_40261822/article/details/83058608
- Windows 破解:https://blog.csdn.net/qq_15071263/article/details/79759973
- Redis 命令參考:http://redisdoc.com/index.html
Redis 示例
Redis 工具類封裝
import org.apache.commons.beanutils.BeanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Tuple;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
/**
* Mac
* 下載:https://redis.io/download
* 解壓:tar zxvf redis-5.0.2.tar.gz
* 移動到: mv redis-5.0.2 /usr/local/
* 切換到:cd /usr/local/redis-5.0.2/
* 編譯測試 sudo make test
* 編譯安裝 sudo make install
* 啟動:redis-server
* <p>
* For idea:Iedis
* <p>
* Redis 命令參考:http://redisdoc.com/index.html
*/
public class Redis {
private static Redis instance;
public static Logger log = LoggerFactory.getLogger(Redis.class);
public static final int DB = 0;// 預設資料庫
public static Redis getInstance() {
if (instance == null) {
instance = new Redis();
instance.init();
}
return instance;
}
private JedisPool pool;
public String host;
public int port;
private void init() {
host = "127.0.0.1";
port = 6379;
log.info("Redis at {}:{}", host, port);
pool = new JedisPool(host, port);
}
public static void destroy() {
getInstance().pool.destroy();
}
// hash 與 object 之間的相互轉換
public static Map<String, String> objectToHash(Object obj)
throws IntrospectionException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException {
Map<String, String> map = new HashMap<>();
BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
for (PropertyDescriptor property : propertyDescriptors) {
if (!property.getName().equals("class")) {
map.put(property.getName(), ""
+ property.getReadMethod().invoke(obj));
}
}
return map;
}
public static void hashToObject(Map<?, ?> map, Object obj)
throws IllegalAccessException, InvocationTargetException {
for (Map.Entry<?, ?> entry : map.entrySet()) {
if (entry.getValue().equals("null")) {
entry.setValue(null);
}
}
BeanUtils.populate(obj, map);
}
@SuppressWarnings("unchecked")
public static <T> T hashToObject(Map<?, ?> map, Class c)
throws IllegalAccessException, InvocationTargetException,
InstantiationException {
Object obj;
try {
obj = c.getDeclaredConstructor().newInstance();
hashToObject(map, obj);
return (T) obj;
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
// Redis 雜湊操作:hmget,hmset,hexist,hdel,hgetAll,hget,hset
public List<String> hmget(int db, String key, String... fields) {
Jedis redis = this.pool.getResource();
redis.select(db);
List<String> ret = redis.hmget(key, fields);
redis.select(db);
redis.close();
return ret;
}
public String hmset(int db, String key, Object object)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, IntrospectionException {
Jedis redis = this.pool.getResource();
redis.select(db);
String ret = redis.hmset(key, objectToHash(object));
redis.close();
return ret;
}
public String hmset(int db, String key, Map<String, String> fields)
throws IllegalAccessException, IllegalArgumentException,
InvocationTargetException, IntrospectionException {
Jedis redis = this.pool.getResource();
redis.select(db);
String ret = redis.hmset(key, fields);
redis.close();
return ret;
}
public boolean hexist(int db, String key, String field) {
if (key == null) {
return false;
}
Jedis redis = this.pool.getResource();
redis.select(db);
boolean ret = redis.hexists(key, field);
redis.close();
return ret;
}
public Long hdel(int db, String key, String... fields) {
Jedis redis = this.pool.getResource();
redis.select(db);
Long cnt = redis.hdel(key, fields);
redis.close();
return cnt;
}
public Map<String, String> hgetAll(int db, String key) {
if (key == null) {
return null;
}
Jedis redis = this.pool.getResource();
redis.select(db);
Map<String, String> ret = redis.hgetAll(key);
redis.close();
return ret;
}
public String hget(int db, String key, String field) {
if (key == null) {
return null;
}
Jedis redis = this.pool.getResource();
redis.select(db);
String ret = redis.hget(key, field);
redis.close();
return ret;
}
public void hset(int db, String key, String field, String value) {
if (field == null || field.length() == 0) {
return;
}
if (value == null || value.length() == 0) {
return;
}
Jedis redis = this.pool.getResource();
redis.select(db);
redis.hset(key, field, value);
redis.close();
}
// Redis 字串操作:set,get
public void set(int db, String key, String value) {
if (value == null || key == null) {
return;
}
Jedis redis = this.pool.getResource();
redis.select(db);
redis.set(key, value);
redis.close();
}
public String get(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
String ret = redis.get(key);
redis.close();
return ret;
}
// Redis 集合操作:sadd,smove,sremove,sget,scard,sismember
/**
* 新增元素到集合中
*
* @param key
* @param element
*/
public boolean sadd(int db, String key, String... element) {
if (element == null || element.length == 0) {
return false;
}
Jedis redis = this.pool.getResource();
redis.select(db);
boolean success = redis.sadd(key, element) == 1;
redis.close();
return success;
}
public boolean smove(int db, String oldKey, String newKey, String element) {
if (element == null) {
return false;
}
Jedis redis = this.pool.getResource();
redis.select(db);
boolean success = (redis.smove(oldKey, newKey, element) == 1);
redis.close();
return success;
}
/**
* 刪除指定set內的元素
*/
public boolean sremove(int db, String key, String... element) {
if (element == null) {
return false;
}
Jedis redis = this.pool.getResource();
redis.select(db);
boolean success = (redis.srem(key, element) == 1);
redis.close();
return success;
}
public Set<String> sget(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> m = redis.smembers(key);
redis.close();
return m;
}
/**
* 返回set的的元素個數
*
* @param key
* @return
* @Title: scard
*/
public long scard(int db, String key) {
Jedis redis = this.pool.getResource();
long size = redis.scard(key);
redis.close();
return size;
}
/**
* 測試元素是否存在
*
* @param key
* @param element
* @return
*/
public boolean sismember(int db, String key, String element) {
Jedis redis = this.pool.getResource();
redis.select(db);
boolean ret = redis.sismember(key, element);
redis.close();
return ret;
}
// Redis 列表操作:laddList,lpush,rpush,lrange,lgetList,(lexist),lpop,lrem
public void laddList(int db, String key, String... elements) {
if (elements == null || elements.length == 0) {
return;
}
Jedis redis = this.pool.getResource();
redis.select(db);
redis.lpush(key, elements);
redis.close();
}
/**
* 依次插入表頭
*
* @param key
* @param elements
* @Title: lpush
*/
public void lpush(int db, String key, String... elements) {
Jedis redis = this.pool.getResource();
redis.select(db);
redis.lpush(key, elements);
redis.close();
}
/**
* 依次插入表尾
*
* @param db
* @param key
* @param elements
*/
public void rpush(int db, String key, String... elements) {
Jedis redis = this.pool.getResource();
redis.select(db);
redis.rpush(key, elements);
redis.close();
}
/**
* 返回指定區間內的元素
*
* @param key
* @param start
* @param end
* @return
* @Title: lrange
*/
public List<String> lrange(int db, String key, int start, int end) {
Jedis redis = this.pool.getResource();
redis.select(db);
List<String> list = redis.lrange(key, start, end);
redis.close();
return list;
}
public List<String> lgetList(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
long len = redis.llen(key);
List<String> ret = redis.lrange(key, 0, len - 1);
redis.close();
return ret;
}
/**
* 列表list中是否包含value
*
* @param key
* @param value
* @return
*/
public boolean lexist(int db, String key, String value) {
List<String> list = lgetList(db, key);
return list.contains(value);
}
public List<String> lgetList(int db, String key, long len) {
Jedis redis = this.pool.getResource();
redis.select(db);
long max = redis.llen(key);
long l = max > len ? len : max;
List<String> ret = redis.lrange(key, 0, l - 1);
redis.close();
return ret;
}
public String lpop(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
String value = redis.lpop(key);
redis.close();
return value;
}
/**
* count > 0 : 從表頭開始向表尾搜尋,移除與 value 相等的元素,數量為 count。
* count < 0 : 從表尾開始向表頭搜尋,移除與 value 相等的元素,數量為 count 的絕對值。
* count = 0 : 移除表中所有與 value 相等的值。
*
* @param db
* @param key
* @param count
* @param value
*/
public void lrem(int db, String key, int count, String value) {
Jedis redis = this.pool.getResource();
redis.select(db);
redis.lrem(key, count, value);
redis.close();
}
// Redis 鍵操作:del,keys(delKeyLikes),exists
public Long del(int db, String... keys) {
Jedis redis = this.pool.getResource();
redis.select(db);
Long cnt = redis.del(keys);
redis.close();
return cnt;
}
/**
* 模糊刪除
*
* @param key
* @return
*/
public Long delKeyLikes(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> keys = redis.keys(key);
Long cnt = redis.del(keys.toArray(new String[keys.size()]));
redis.close();
return cnt;
}
/**
* 判斷某一個key值的儲存結構是否存在
*
* @param key
* @return
* @Title: exists
*/
public boolean exists(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
boolean yes = redis.exists(key);
redis.close();
return yes;
}
// Redis 有序集合操作:zadd,zincrby,zscore,zrevrank。。。
public long zadd(int db, String key, int score, String member) {
Jedis redis = this.pool.getResource();
redis.select(db);
long ret = 0;
try {
ret = redis.zadd(key, score, member);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
redis.close();
}
return ret;
}
/**
* 新增 分數,並返回修改後的值
*
* @param key
* @param update
* @param member
* @return
*/
public double zincrby(int db, String key, int update, String member) {
Jedis redis = this.pool.getResource();
redis.select(db);
double ret = redis.zincrby(key, update, member);
redis.close();
return ret;
}
/**
* 返回有序集 key 中,成員 member 的 score 值,存在返回score,不存在返回-1
*
* @param key
* @param member
* @return
*/
public double zscore(int db, String key, String member) {
Jedis redis = this.pool.getResource();
redis.select(db);
Double ret = redis.zscore(key, member);
redis.close();
if (ret == null) {
return -1;
}
return ret;
}
/**
* 按從大到小的排名,獲取 member的排名,最大排名為 0
*
* @param key
* @param member
* @return
*/
public long zrevrank(int db, String key, String member) {
Jedis redis = this.pool.getResource();
redis.select(db);
long ret = redis.zrevrank(key, member);
redis.close();
return ret;
}
/**
* 按照score的值從小到大排序,返回member的排名,最小排名為 0
*
* @param key
* @param member
* @return 設定為名次從1開始。返回為-1,表示member無記錄
* @Title: zrank
*/
public long zrank(int db, String key, String member) {
Jedis redis = this.pool.getResource();
redis.select(db);
long ret = -1;
Long vv = redis.zrank(key, member);
if (vv != null) {
ret = vv.longValue();
}
redis.close();
if (ret != -1) {
ret += 1;
}
return ret;
}
/**
* 【min, max】從小到大排序
*
* @param key
* @param min
* @param max
* @return
* @Title: zrangebyscore
*/
public Set<String> zrangebyscore(int db, String key, long min, long max) {
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> ss = redis.zrangeByScore(key, min, max);
redis.close();
return ss;
}
public Set<String> zrange(int db, String key, long min, long max) {
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> ss = redis.zrange(key, min, max);
redis.close();
return ss;
}
/**
* min 和 max 都是score的值,獲得一個包含了score的元組集合。元組(Tuple)
* 笛卡爾積中每一個元素(d1,d2,…,dn)叫作一個n元組(n-tuple)或簡稱元組
*
* @param key
* @param min
* @param max
* @return
* @Title: zrangebyscorewithscores
*/
public Set<Tuple> zrangebyscorewithscores(int db, String key, long min, long max) {
Jedis redis = this.pool.getResource();
if (redis == null) {
return null;
}
redis.select(db);
Set<Tuple> result = null;
try {
result = redis.zrangeByScoreWithScores(key, min, max);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
redis.close();
}
return result;
}
/**
* zrevrangeWithScores : 從大到小排序 zrangeWithScores : 從小到大排序
*
* @param key
* @param start : (排名)0表示第一個元素,-x:表示倒數第x個元素
* @param end : (排名)-1表示最後一個元素(最大值)
* @return 返回 排名在start 、end之間帶score元素
* @Title: zrangeWithScores
*/
public Map<String, Double> zrevrangeWithScores(int db, String key, long start, long end) {
Jedis redis = this.pool.getResource();
if (redis == null) {
return null;
}
redis.select(db);
Set<Tuple> result = null;
try {
result = redis.zrevrangeWithScores(key, start, end);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
redis.close();
}
return tupleToMap(result);
}
public Map<String, Double> tupleToMap(Set<Tuple> tupleSet) {
if (tupleSet == null)
return null;
Map<String, Double> map = new LinkedHashMap<>();
for (Tuple tup : tupleSet) {
map.put(tup.getElement(), tup.getScore());
}
return map;
}
/**
* 刪除key中的member
*
* @param key
* @param member
* @return
* @Title: zrem
*/
public long zrem(int db, String key, String member) {
Jedis redis = this.pool.getResource();
if (redis == null) {
return -1;
}
redis.select(db);
long result = -1;
try {
result = redis.zrem(key, member);
} catch (Exception e) {
log.error(e.getMessage(), e);
} finally {
redis.close();
}
return result;
}
/**
* 從高到低排名,返回前 num 個score和member
*
* @param key
* @param num
* @return
*/
public Set<Tuple> ztopWithScore(int db, String key, int num) {
if (num <= 0) {
return null;
}
Jedis redis = this.pool.getResource();
redis.select(db);
Set<Tuple> ret = redis.zrevrangeWithScores(key, 0, num - 1);
redis.close();
return ret;
}
/**
* 返回score區間的member
*
* @param key
* @param max
* @param min
* @return
*/
public Set<String> zrevrangeByScore(int db, String key, int max, int min) {
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> ret = redis.zrevrangeByScore(key, max, min);
redis.close();
return ret;
}
/**
* 從高到低排名,返回前 num 個
*
* @param key
* @param num
* @return
*/
public Set<String> ztop(int db, String key, int num) {
if (num <= 0) {
return null;
}
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> ret = redis.zrevrange(key, 0, num - 1);
redis.close();
return ret;
}
/**
* 從高到低排名,返回start到end的前 num 個
*/
public Set<String> ztop(int db, String key, int start, int end) {
if (end <= start) {
return null;
}
Jedis redis = this.pool.getResource();
redis.select(db);
Set<String> ret = redis.zrevrange(key, start, end - 1);
redis.close();
return ret;
}
/**
* 返回zset的的元素個數
*
* @param key
* @return
* @Title: zcard_
*/
public long zcard(int db, String key) {
Jedis redis = this.pool.getResource();
redis.select(db);
long size = redis.zcard(key);
redis.close();
return size;
}
// 釋出,訂閱
/**
* 將資訊 message 傳送到指定的頻道 channel。
*
* @param db
* @param channel
* @param message
*/
public void publish(int db, String channel, String message) {
if (channel == null || message == null) {
return;
}
Jedis redis = this.pool.getResource();
redis.select(db);
redis.publish(channel, message);
redis.close();
}
}
Redis 使用
import java.util.List;
import java.util.Map;
import java.util.Set;
public class RedisDemo {
public static void main(String[] args) {
RedisDemo demo = new RedisDemo();
demo.run();
}
public void run() {
Redis redis = Redis.getInstance();
/** redis save **/
System.out.println("=============redis save==============");
// string save
System.out.println("string save:呼叫set時,若key不存在則新增key,否則為修改key對應的值");
redis.set(Redis.DB, "testKey1", "test string val1");
// set save
System.out.println("set save:set中的元素不允許出現重複且無序");
redis.sadd(Redis.DB, "testKey2", "test set val1");
redis.sadd(Redis.DB, "testKey2", "test set val2");
redis.sadd(Redis.DB, "testKey2", "test set val3");
// hash save
System.out.println("hash save:呼叫hset時,若key不存在則建立key,若hash中存在這個hashkey,則修改其值,不存在則新增一條hash資料");
redis.hset(Redis.DB, "testKey3", "hashKey1", "hashVal1");
redis.hset(Redis.DB, "testKey3", "hashKey2", "hashVal2");
redis.hset(Redis.DB, "testKey3", "hashKey3", "hashVal3");
redis.hset(Redis.DB, "testKey3", "hashKey4", "hashVal4");
// list save
System.out.println("list save:資料在連結串列中是有序的,並可以重複新增資料");
redis.lpush(Redis.DB, "testKey4", "test list val1");
redis.lpush(Redis.DB, "testKey4", "test list val2");
redis.lpush(Redis.DB, "testKey4", "test list val3");
// sorted set save
System.out.println("sorted set save:有序set中的元素是有序的");
redis.zadd(Redis.DB, "testKey5", 1, "test zset val1");
redis.zadd(Redis.DB, "testKey5", 2, "test zset val2");
redis.zadd(Redis.DB, "testKey5", 3, "test zset val3");
redis.zadd(Redis.DB, "testKey5", 4, "test zset val4");
/** redis get **/
System.out.println("=============redis get==============");
// string get
String stringRet = redis.get(Redis.DB, "testKey1");
System.out.println("string get:" + stringRet);
// set get
Set<String> setRet = redis.sget(Redis.DB, "testKey2");
System.out.print("set get:");
for (String string : setRet) {
System.out.print(string + ",");
}
System.out.println();
// hash get
String hashKeyRet = redis.hget(Redis.DB, "testKey3", "hashKey2");
System.out.println("hash key get:" + hashKeyRet);
Map<String, String> hashRet = redis.hgetAll(Redis.DB, "testKey3");
System.out.print("hash get:");
for (String string : hashRet.keySet()) {
System.out.print("key[" + string + "]" + "value[" + hashRet.get(string) + "],");
}
System.out.println();
// list get
List<String> listRet = redis.lgetList(Redis.DB, "testKey4");
System.out.print("list get:");
for (String string : listRet) {
System.out.println(string + ",");
}
// zset get
long val2Rank = redis.zrank(Redis.DB, "testKey5", "test zset val2");
System.out.println("zset get val2 rank:" + val2Rank);
Set<String> zsetRet = redis.zrange(Redis.DB, "testKey5", 0, 3);
System.out.print("zset get range:");
for (String string : zsetRet) {
System.out.println(string + ",");
}
/** redis delete **/
System.out.println("=============redis delete==============");
// string delete
System.out.println("string delete:呼叫Redis的del方法,可直接刪除key,對於所有的資料型別來說,都可以通過這種方式直接刪除整個key");
redis.del(Redis.DB, "testKey1");
// set delete
System.out.println("set delete:刪除set中的val3");
redis.sremove(Redis.DB, "testKey2", "test set val3");
// hash delete
System.out.println("hash delete:刪除hash中key為hashKey4的元素");
redis.hdel(Redis.DB, "testKey3", "hashKey4");
// list delete
System.out.println("list delete:刪除list中值為test list val3的元素,其中count引數,0代表刪除全部,正數代表正向刪除count個此元素,負數代表負向刪除count個此元素");
redis.lrem(Redis.DB, "testKey4", 0, "test list val3");
// zset delete
System.out.println("zset delete:同set刪除元素的方式相同");
redis.zrem(Redis.DB, "testKey5", "test zset val4");
System.out.println("除了以上常用api之外,還有更多api,在Redis類中都有列出,請參考Redis類,或直接參照Jedis的官方文件");
}
}