#前言java
Java
緩存實現方案有不少,最基本的本身使用Map
去構建緩存,再高級點的使用Ehcache
或者Goolge
的guava
做爲內存緩存框架,Ehcache
能夠知足單機緩存的需求(Ehcache
的具體使用在我過往的文章中有所介紹),若是咱們是多臺機子共用緩存數據的話,Ehcache
可經過rmi
,jgroup
,jms
的方式實現,可是實用性與操做性不高且複雜,現時大部分應用僅用Ehcache
做爲單機緩存使用,這時候咱們能夠經過搭建緩存服務器解決多機使用的問題,常見的緩存服務器有Memcached
,Redis
等。node
現時業界主流大多使用Redis
。因此本文主要介紹在Java
中如何使用Redis
。至於如何搭建Redis
,我在過往的文章中已有所介紹,不知道如何搭建的同窗,能夠參考我過往的文章,下文所用到相關的Redis
信息均爲搭建教程中的信息。git
PS:文章中所用到的示例代碼,部分參考至開源項目iBase4J,特此聲明。正則表達式
本文同步發佈於簡書 :www.jianshu.com/p/5a9946870…redis
Java
鏈接Redis
官方推薦的是使用Jedis
和Redisson
進行鏈接操做,Spring
對Redis
有很好的支持,因此此文我結合Spring
中的Spring Data
對Redis
進行操做。spring
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>1.8.7.RELEASE</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.5.5</version>
</dependency>
複製代碼
在classpath
下創建Redis配置文件redis.properties
。數據庫
若是同窗們是搭建Redis
高可用架構,是經過向外提供VIP
虛擬IP的方式鏈接Redis
,則只需在配置文件中將redis.host=172.16.2.185
單機IP改成VIP
虛擬IPredis.host=172.16.2.250
便可實現Redis
高可用,而不須要使用Spring
提供的RedisSentinel
方案實現Redis
高可用。apache
#VIP
#redis.host=172.16.2.250
redis.host=172.16.2.185
redis.port=6379
redis.password=123456
#最小空閒數
redis.minIdle=2
#最大空閒數
redis.maxIdle=10
#最大鏈接數
redis.maxTotal=1000
#最大創建鏈接等待時間
redis.maxWaitMillis=3000
#客戶端超時時間單位是毫秒
redis.timeout=120000
#明是否在從池中取出鏈接前進行檢驗,若是檢驗失敗,則從池中去除鏈接並嘗試取出另外一個
redis.testOnBorrow=true
redis.expiration=600
複製代碼
在classpath
下創建文件夾spring
用於存放全部與spring
相關的配置文件。在spring
文件夾下創建spring-redis.xml
,主要用於注入Jedis
。api
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<context:property-placeholder location="classpath*:redis.properties" ignore-unresolvable="true"/>
<!-- jedis 配置-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" >
<!--最小空閒數-->
<property name="minIdle" value="${redis.minIdle}" />
<!--最大空閒數-->
<property name="maxIdle" value="${redis.maxIdle}" />
<!--最大鏈接數-->
<property name="maxTotal" value="${redis.maxTotal}" />
<!--最大創建鏈接等待時間-->
<property name="maxWaitMillis" value="${redis.maxWaitMillis}" />
<!--是否在從池中取出鏈接前進行檢驗,若是檢驗失敗,則從池中去除鏈接並嘗試取出另外一個-->
<property name="testOnBorrow" value="${redis.testOnBorrow}" />
</bean >
<!-- redis服務器中心 -->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="poolConfig" ref="jedisPoolConfig"/>
<property name="port" value="${redis.port}"/>
<property name="hostName" value="${redis.host}"/>
<property name="password" value="${redis.password}"/>
<property name="timeout" value="${redis.timeout}" />
</bean>
<!-- 緩存序列化方式 -->
<bean id="keySerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer" />
<bean id="valueSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer" />
<!-- 緩存 -->
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
<property name="connectionFactory" ref="jedisConnectionFactory" />
<property name="enableTransactionSupport" value="true" />
<property name="keySerializer" ref="keySerializer" />
<property name="valueSerializer" ref="valueSerializer" />
<property name="hashKeySerializer" ref="keySerializer" />
<property name="hashValueSerializer" ref="valueSerializer" />
</bean>
<bean class="com.easylink.mall.core.cache.redis.RedisHelper" >
<property name="redisTemplate" ref="redisTemplate" />
</bean>
<!-- 緩存管理 -->
<bean id="redisCacheManager" class="org.springframework.data.redis.cache.RedisCacheManager">
<constructor-arg index="0" ref="redisTemplate" />
<property name="transactionAware" value="true" />
<property name="defaultExpiration" value="${redis.expiration}" />
</bean>
</beans>
複製代碼
在spring
文件夾下創建spring-redisson.xml
,主要用於注入Redisson
緩存
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"
>
<context:property-placeholder location="classpath*:redis.properties" ignore-unresolvable="true"/>
<!-- redisson 配置-->
<bean id="redissonClient" class="com.easylink.mall.core.cache.redisson.Client" init-method="init">
<property name="password" value="${redis.password}" />
<!-- SingleServer -->
<property name="address" value="redis://${redis.host}:${redis.port}" />
<!-- ClusterServers -->
<!-- <property name="nodeAddresses" value="${redis.cluster}}" /> -->
<!-- MasterSlaveServers -->
<!-- <property name="masterAddress" value="${redis.master}" />
<property name="slaveAddresses" value="${redis.slave}" /> -->
</bean>
<!-- redisson 工具類 -->
<bean class="com.easylink.mall.core.cache.redisson.RedissonHelper">
<property name="redissonClient" ref="redissonClient" />
</bean>
</beans>
複製代碼
這個類主要是用於獲取緩存管理器,由於Jedis
封裝Redis
基本操做的接口比較友好,因此基本操做使用Jedis
實現,可是將Redis
當作分佈式鎖使用時,若是是自行用Jedis
中的setNX + 時間戳過程方法實現的話,會略顯複雜,還可能寫的不嚴謹,存在原子性操做或者死鎖等問題。此處的分佈式鎖實現使用Redisson
幫咱們封裝好的方法實現加鎖與解鎖,順便提一句,Redisson
加鎖操做是使用lua
腳本一次執行加鎖與設置過時的操做的,因此不存在原子性問題。這處暫時不展開討論分佈式鎖的問題,往後有空再和你們一同探討分佈式鎖的問題。
package com.easylink.mall.core.cache.redis;
import com.easylink.mall.core.support.util.PropertiesFileUtil;
public class CacheUtil {
/**
* 緩存管理器,主要執行緩存操做
*/
private static CacheManager cacheManager;
/**
* 鎖管理器,主要執行加鎖與解鎖操做
*/
private static CacheManager lockManager;
public static void setCacheManager(CacheManager cacheManager) {
CacheUtil.cacheManager = cacheManager;
}
public static void setLockManager(CacheManager cacheManager) {
CacheUtil.lockManager = cacheManager;
}
public static CacheManager getCache() {
return cacheManager;
}
public static CacheManager getLockManager() {
return lockManager;
}
/** 獲取鎖 */
public static boolean tryLock(String key) {
int expires = 1000 * PropertiesFileUtil.getInstance("redis.properties").getInt("redis.lock.expires", 180);
return lockManager.setnx(key, expires);
}
/** 獲取鎖 */
public static boolean getLock(String key) {
return lockManager.lock(key);
}
/** 解鎖 */
public static void unlock(String key) {
lockManager.unlock(key);
}
}
複製代碼
package com.easylink.mall.core.cache.redis;
import java.io.Serializable;
import java.util.Set;
/**
* 緩存操做管理接口
*
* @author Ben.
*
*/
public interface CacheManager {
/**
* 根據key獲取對象
*
* @param key
* @return
*/
Object get(final String key);
/**
* 根據正則表達式獲取對象
*
* @param pattern
* 正則表達式
* @return
*/
Set<Object> getAll(final String pattern);
/**
* 設置key-value
*
* @param key
* @param value
* @param seconds
* 過時時間(秒)
*/
void set(final String key, final Serializable value, int seconds);
/**
* 設置key-value 過時時間使用默認配置值
*
* @param key
* @param value
*/
void set(final String key, final Serializable value);
/**
* 根據key判斷某一對象是否存在
*
* @param key
* @return 是否存在
*/
Boolean exists(final String key);
/**
* 根據key刪除對象
*
* @param key
*/
void del(final String key);
/**
* 根據正則表達式刪除對象
*
* @param pattern
* 正則表達式
* @return
*/
void delAll(final String pattern);
/**
* 根據key獲取對應對象的類型
*
* @param key
* @return 對應對象的類型
*/
String type(final String key);
/**
* 設置key的過時時間
*
* @param key
* @param seconds
* @return 是否設置成功
*/
Boolean expire(final String key, final int seconds);
/**
* 設置key在指定時間點後過時
*
* @param key
* @param unixTime
* @return 是否成功
*/
Boolean expireAt(final String key, final long unixTime);
/**
* 獲取對應key的過時時間
*
* @param key
* @return
*/
Long ttl(final String key);
/**
* 設置新值並返回舊值
*
* @param key
* @param value
* @return 舊值
*/
Object getSet(final String key, final Serializable value);
/**
* 對key進行加鎖
*
* @param key
* @return 是否加鎖成功
*/
boolean lock(String key);
/**
* 對key進行解鎖
*
* @param key
*/
void unlock(String key);
/**
* 根據key設置對應哈希表對象的field - value
*
* @param key
* @param field
* @param value
*/
void hset(String key, Serializable field, Serializable value);
/**
* 根據key獲取對應哈希表的對應field的對象
*
* @param key
* @param field
* @return
*/
Object hget(String key, Serializable field);
/**
* 根據key刪除對應哈希表的對應field的對象
*
* @param key
* @param field
* @return
*/
void hdel(String key, Serializable field);
/**
* 指定的 key 不存在時,爲 key 設置指定的value
*
* @param key
* @param value
* @return 是否設置成功
*/
boolean setnx(String key, Serializable value);
/**
* 對應key的值自增
*
* @param key
* @return 自增後的值
*/
Long incr(String key);
/**
* 用指定的字符串覆蓋給定 key 所儲存的字符串值,覆蓋的位置從偏移量 offset 開始
*
* @param key
* @param offset
* 偏移量
* @param value
*/
void setrange(String key, long offset, String value);
/**
* 用於獲取存儲在指定 key 中字符串的子字符串。字符串的截取範圍由 start 和 end 兩個偏移量決定(包括 start 和 end 在內)。
*
* @param key
* @param startOffset
* @param endOffset
* @return
*/
String getrange(String key, long startOffset, long endOffset);
/**
* 將value設置至指定key的set集合中
*
* @param key
* @param value
*/
void sadd(String key, Serializable value);
/**
* 獲取指定key的set集合
*
* @param key
* @return
*/
Set<?> sall(String key);
/**
* 刪除指定key的set集合中的value
*
* @param key
* @param value
* @return
*/
boolean sdel(String key, Serializable value);
}
複製代碼
基於Spring
的RedisTemplate
實現CacheManager
接口,主要用於對緩存的基本操做,不用於分佈式鎖做用,此處的分佈式鎖實現不嚴謹,不當作參考
/**
* Redis緩存輔助類
*
* @author ShenHuaJie
* @version 2016年4月2日 下午4:17:22
*/
public final class RedisHelper implements CacheManager {
private static final Logger logger = Logger.getLogger(RedisHelper.class);
private RedisSerializer<String> keySerializer;
private RedisSerializer<Object> valueSerializer;
private RedisTemplate<Serializable, Serializable> redisTemplate;
private final Integer EXPIRE = PropertiesFileUtil.getInstance("redis.properties").getInt("redis.expiration");
@SuppressWarnings("unchecked")
public void setRedisTemplate(RedisTemplate<Serializable, Serializable> redisTemplate) {
this.redisTemplate = redisTemplate;
this.keySerializer = (RedisSerializer<String>) redisTemplate.getKeySerializer();
this.valueSerializer = (RedisSerializer<Object>) redisTemplate.getValueSerializer();
CacheUtil.setCacheManager(this);
}
@Override
public final Object get(final String key) {
// 先過時
expire(key, EXPIRE);
// 後取值
return redisTemplate.boundValueOps(key).get();
}
@Override
public final Set<Object> getAll(final String pattern) {
Set<Object> values = new HashSet<Object>();
Set<Serializable> keys = redisTemplate.keys(pattern);
for (Serializable key : keys) {
expire(key.toString(), EXPIRE);
values.add(redisTemplate.opsForValue().get(key));
}
return values;
}
@Override
public final void set(final String key, final Serializable value, int seconds) {
redisTemplate.boundValueOps(key).set(value);
expire(key, seconds);
}
@Override
public final void set(final String key, final Serializable value) {
redisTemplate.boundValueOps(key).set(value);
expire(key, EXPIRE);
}
@Override
public final Boolean exists(final String key) {
return redisTemplate.hasKey(key);
}
@Override
public final void del(final String key) {
redisTemplate.delete(key);
}
@Override
public final void delAll(final String pattern) {
redisTemplate.delete(redisTemplate.keys(pattern));
}
@Override
public final String type(final String key) {
expire(key, EXPIRE);
return redisTemplate.type(key).getClass().getName();
}
@Override
public final Boolean expire(final String key, final int seconds) {
return redisTemplate.expire(key, seconds, TimeUnit.SECONDS);
}
@Override
public final Boolean expireAt(final String key, final long unixTime) {
return redisTemplate.expireAt(key, new Date(unixTime));
}
@Override
public final Long ttl(final String key) {
return redisTemplate.getExpire(key, TimeUnit.SECONDS);
}
@Override
public final void setrange(final String key, final long offset, final String value) {
redisTemplate.boundValueOps(key).set(value, offset);
expire(key, EXPIRE);
}
@Override
public final String getrange(final String key, final long startOffset, final long endOffset) {
expire(key, EXPIRE);
return redisTemplate.boundValueOps(key).get(startOffset, endOffset);
}
@Override
public final Object getSet(final String key, final Serializable value) {
expire(key, EXPIRE);
return redisTemplate.boundValueOps(key).getAndSet(value);
}
@Override
public boolean setnx(String key, Serializable value) {
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection redisConnection = null;
try {
redisConnection = RedisConnectionUtils.getConnection(factory);
if (redisConnection == null) {
return redisTemplate.boundValueOps(key).setIfAbsent(value);
}
logger.info(keySerializer);
logger.info(valueSerializer);
return redisConnection.setNX(keySerializer.serialize(key), valueSerializer.serialize(value));
} finally {
RedisConnectionUtils.releaseConnection(redisConnection, factory);
}
}
@Override
public boolean lock(String key) {
RedisConnectionFactory factory = redisTemplate.getConnectionFactory();
RedisConnection redisConnection = null;
try {
redisConnection = RedisConnectionUtils.getConnection(factory);
if (redisConnection == null) {
return redisTemplate.boundValueOps(key).setIfAbsent("0");
}
return redisConnection.setNX(keySerializer.serialize(key), valueSerializer.serialize("0"));
} finally {
RedisConnectionUtils.releaseConnection(redisConnection, factory);
}
}
@Override
public void unlock(String key) {
redisTemplate.delete(key);
}
@Override
public void hset(String key, Serializable field, Serializable value) {
redisTemplate.boundHashOps(key).put(field, value);
}
@Override
public Object hget(String key, Serializable field) {
return redisTemplate.boundHashOps(key).get(field);
}
@Override
public void hdel(String key, Serializable field) {
redisTemplate.boundHashOps(key).delete(field);
}
@Override
public void sadd(String key, Serializable value) {
redisTemplate.boundSetOps(key).add(value);
}
@Override
public Set<?> sall(String key) {
return redisTemplate.boundSetOps(key).members();
}
@Override
public boolean sdel(String key, Serializable value) {
return redisTemplate.boundSetOps(key).remove(value) == 1;
}
@Override
public Long incr(String key) {
return redisTemplate.boundValueOps(key).increment(1L);
}
}
複製代碼
基於Redisson
實現CacheManager
接口,主要用於實現基於Redis
的分佈式鎖
package com.easylink.mall.core.cache.redisson;
import java.io.Serializable;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBucket;
import org.redisson.api.RType;
import org.redisson.api.RedissonClient;
import com.easylink.mall.core.cache.redis.CacheManager;
import com.easylink.mall.core.cache.redis.CacheUtil;
import com.easylink.mall.core.support.util.PropertiesFileUtil;
/**
*
* Redis緩存輔助類
*
*/
public class RedissonHelper implements CacheManager {
private RedissonClient redissonClient;
private final Integer EXPIRE = PropertiesFileUtil.getInstance("redis.properties").getInt("redis.expiration");
public void setRedissonClient(Client client) {
this.redissonClient = client.getRedissonClient();
CacheUtil.setLockManager(this);
}
private RBucket<Object> getRedisBucket(String key) {
return redissonClient.getBucket(key);
}
@Override
public final Object get(final String key) {
RBucket<Object> temp = getRedisBucket(key);
expire(temp, EXPIRE);
return temp.get();
}
@Override
public final void set(final String key, final Serializable value) {
RBucket<Object> temp = getRedisBucket(key);
temp.set(value);
expire(temp, EXPIRE);
}
@Override
public final void set(final String key, final Serializable value, int seconds) {
RBucket<Object> temp = getRedisBucket(key);
temp.set(value);
expire(temp, seconds);
}
public final void multiSet(final Map<String, Object> temps) {
redissonClient.getBuckets().set(temps);
}
@Override
public final Boolean exists(final String key) {
RBucket<Object> temp = getRedisBucket(key);
return temp.isExists();
}
@Override
public final void del(final String key) {
redissonClient.getKeys().delete(key);
}
@Override
public final void delAll(final String pattern) {
redissonClient.getKeys().deleteByPattern(pattern);
}
@Override
public final String type(final String key) {
RType type = redissonClient.getKeys().getType(key);
if (type == null) {
return null;
}
return type.getClass().getName();
}
/**
* 在某段時間後失效
*
* @return
*/
private final void expire(final RBucket<Object> bucket, final int seconds) {
bucket.expire(seconds, TimeUnit.SECONDS);
}
/**
* 在某個時間點失效
*
* @param key
* @param unixTime
* @return
*
*/
@Override
public final Boolean expireAt(final String key, final long unixTime) {
return redissonClient.getBucket(key).expireAt(new Date(unixTime));
}
@Override
public final Long ttl(final String key) {
RBucket<Object> rBucket = getRedisBucket(key);
return rBucket.remainTimeToLive();
}
@Override
public final Object getSet(final String key, final Serializable value) {
RBucket<Object> rBucket = getRedisBucket(key);
return rBucket.getAndSet(value);
}
@Override
public Set<Object> getAll(String pattern) {
Set<Object> set = new HashSet<Object>();
Iterable<String> keys = redissonClient.getKeys().getKeysByPattern(pattern);
for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
String key = iterator.next();
set.add(getRedisBucket(key).get());
}
return set;
}
@Override
public Boolean expire(String key, int seconds) {
RBucket<Object> bucket = getRedisBucket(key);
expire(bucket, seconds);
return true;
}
@Override
public void hset(String key, Serializable field, Serializable value) {
redissonClient.getMap(key).put(field, value);
}
@Override
public Object hget(String key, Serializable field) {
return redissonClient.getMap(key).get(field);
}
@Override
public void hdel(String key, Serializable field) {
redissonClient.getMap(key).remove(field);
}
public void sadd(String key, Serializable value) {
redissonClient.getSet(key).add(value);
}
public Set<Object> sall(String key) {
return redissonClient.getSet(key).readAll();
}
public boolean sdel(String key, Serializable value) {
return redissonClient.getSet(key).remove(value);
}
@Override
public boolean lock(String key) {
return redissonClient.getLock(key).tryLock();
}
@Override
public void unlock(String key) {
redissonClient.getLock(key).unlock();
}
@Override
public boolean setnx(String key, Serializable value) {
try {
return redissonClient.getLock(key).tryLock(Long.valueOf(value.toString()), TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
return false;
}
}
@Override
public Long incr(String key) {
return null;
}
@Override
public void setrange(String key, long offset, String value) {
}
@Override
public String getrange(String key, long startOffset, long endOffset) {
return null;
}
}
複製代碼
package com.easylink.mall.core.cache.redisson;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.ClusterServersConfig;
import org.redisson.config.Config;
import org.redisson.config.MasterSlaveServersConfig;
import org.redisson.config.SingleServerConfig;
/**
* Redis鏈接配置
*
* @author ShenHuaJie
* @since 2017年8月23日 上午9:36:53
*/
public class Client {
/**
* Redis server address
*
*/
private String address;
/**
* Password for Redis authentication. Should be null if not needed
*/
private String password;
/**
* Redis cluster node urls list
*/
private Set<String> nodeAddresses = new HashSet<String>();
/**
* Redis master server address
*/
private String masterAddress;
/**
* Redis slave servers addresses
*/
private Set<String> slaveAddresses = new HashSet<String>();
private RedissonClient redissonClient;
public void init() {
Config config = new Config();
if (StringUtils.isNotBlank(address)) {
SingleServerConfig serverConfig = config.useSingleServer().setAddress(address);
if (StringUtils.isNotBlank(password)) {
serverConfig.setPassword(password);
}
} else if (!nodeAddresses.isEmpty()) {
ClusterServersConfig serverConfig = config.useClusterServers()
.addNodeAddress(nodeAddresses.toArray(new String[] {}));
if (StringUtils.isNotBlank(password)) {
serverConfig.setPassword(password);
}
} else if (masterAddress != null && !slaveAddresses.isEmpty()) {
MasterSlaveServersConfig serverConfig = config.useMasterSlaveServers().setMasterAddress(masterAddress)
.addSlaveAddress(slaveAddresses.toArray(new String[] {}));
if (StringUtils.isNotBlank(password)) {
serverConfig.setPassword(password);
}
}
this.redissonClient = Redisson.create(config);
}
public RedissonClient getRedissonClient() {
return redissonClient;
}
public void setAddress(String address) {
this.address = address;
}
public void setPassword(String password) {
this.password = password;
}
public void setNodeAddresses(String nodeAddresse) {
if (nodeAddresse != null) {
String[] nodeAddresses = nodeAddresse.split(",");
for (int i = 0; i < nodeAddresses.length; i++) {
if (StringUtils.isNotEmpty(nodeAddresses[i])) {
this.nodeAddresses.add(nodeAddresses[i]);
}
}
}
}
public void setMasterAddress(String masterAddress) {
this.masterAddress = masterAddress;
}
public void setSlaveAddresses(String slaveAddresse) {
if (slaveAddresse != null) {
String[] slaveAddresses = slaveAddresse.split(",");
for (int i = 0; i < slaveAddresses.length; i++) {
if (StringUtils.isNotEmpty(slaveAddresses[i])) {
this.slaveAddresses.add(slaveAddresses[i]);
}
}
}
}
}
複製代碼
package com.easylink.mall.core.support.util;
import java.util.HashMap;
import org.apache.commons.configuration2.PropertiesConfiguration;
import org.apache.commons.configuration2.builder.fluent.Configurations;
import org.apache.commons.configuration2.ex.ConfigurationException;
import org.apache.log4j.Logger;
/**
* 資源文件讀取工具
*
* @author Ben.
*
*/
public class PropertiesFileUtil {
private static Logger logger = Logger.getLogger(PropertiesFileUtil.class);
// 當打開多個資源文件時,緩存資源文件
private static HashMap<String, PropertiesConfiguration> configMap = new HashMap<String, PropertiesConfiguration>();
// 默認資源文件名稱
private static final String NAME = "config.properties";
// 私有構造方法,建立單例
private PropertiesFileUtil() {
}
public static synchronized PropertiesConfiguration getInstance() {
return getInstance(NAME);
}
public static synchronized PropertiesConfiguration getInstance(String name) {
PropertiesConfiguration propertiesConfiguration = configMap.get(name);
if (propertiesConfiguration == null) {
Configurations configs = new Configurations();
try {
propertiesConfiguration = configs.properties(name);
} catch (ConfigurationException e) {
logger.error("can not load properties file,name : " + name);
}
configMap.put(name, propertiesConfiguration);
}
return propertiesConfiguration;
}
}
複製代碼
編寫單元測試用例,測試是否搭建成功
package com.easylink.mall.core.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.easylink.mall.core.cache.redis.CacheUtil;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/spring-redis.xml")
public class JedisTest {
@Test
public void execute() {
CacheUtil.getCache().set("test-jedis", "test-value");
Object testValue = CacheUtil.getCache().get("test-jedis");
System.out.println(String.valueOf(testValue));
}
}
複製代碼
package com.easylink.mall.core.test;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import com.easylink.mall.core.cache.redis.CacheUtil;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:spring/spring-redisson.xml")
public class RedissonTest {
@Test
public void execute() {
// 加鎖
CacheUtil.getLockManager().lock("test-jedis");
// 解鎖
CacheUtil.getLockManager().unlock("test-jedis");
}
}
複製代碼
至此,上述過程已經說明了如何在JAVA
中使用Redis
進行一些緩存的基本操做或者是看成分佈式鎖去使用。內容比較簡單,基礎。可是適用於初學者去學習,畢竟先學會入門的使用,而後再對其的某些功能或者特性去深刻研究,這樣能讓本身更好的去學習一種技術。樓主因爲過久沒有更新文章,因此先寫一篇簡單的找一下感受。遲點再和你們一同探究Redis
的一些知識和常見問題,如:基礎的數據結構,緩存和數據庫一致性問題,緩存雪崩問題,緩存擊穿問題等。謝謝你們的支持,若是此文對你有所幫助,請點個贊,謝謝。