由於一直用spring,因此上redis,決定用spring-data-redis,該項目但願用maven或者gradle,暫時不打算學習gradle,因而把maven學習了下,並留下學習備忘。
spring data redis推薦jedis,所以稍微把jedis稍微看了下,jedis是redis的java客戶端。
sdr 支持低層次的經過鏈接器connector鏈接到Redis,支持高層次的友好的模板類RedisTemplate,RedisTemplate是創建在 低級別的connection基礎之上。RedisConnection接收或返回字節數組須要自身處理鏈接,好比關閉鏈接,而 RedisTemplate負責處理串行化和反串行化,而且管理對鏈接進行管理。RedisTemplate提供操做視圖,好比 (Bound)ValueOperations,java
(Bound)ListOperations,(Bound)SetOperations,(Bound)ZSetOperations,(Bound)HashOperations。RedisTemplate是線程安全的,可以用於多個實例中。redis
RedisTemplate 默認選擇java-based串行化,也能夠切換爲其它的串行化方式,或者設置enabledDefaultSerializer爲false或者設置串 行化器爲null,則RedisTemplate用raw byte arrays表示數據。
sdr鏈接到redis經過 RedisConnectionFactory來得到有效的RedisConnection。RedisConnection負責創建和處理和redis 後端通訊。RedisConnection提供getNativeconnection返回用來通訊的底層connection。
spring配置:
<?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:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
p:host-name="server" p:port="6379" p:use-pool="true"/>
spring
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>後端
</beans>
使用樣例:
數組
public class Example {
// 注入實際的模板
@Autowired
private RedisTemplate<String, String> template;//表示鍵值都是字符串類型。
// 注入模板爲ListOperations.
@Resource(name="redisTemplate")
private ListOperations<String, String> listOps;
public void addLink(String userId, URL url) {
listOps.leftPush(userId, url.toExternalForm());
}
}緩存
因爲大部分Redis鍵值對存儲都是鍵值均爲字符串,所以sdr作了兩個擴展,即StringRedisConnection以及StringRedisTemplate,兩個擴展均採用StringRedisSerializer。
安全
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>session
代碼示例:
@Autowired
private StringRedisTemplate redisTemplate;
public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
RedisTemplate 以及其子類都容許開發者經過RedisCallback直接跟Redis通訊,在callback中,開發者得到RedisConnection。 StringRedisTemplate在callback中能夠得到StringRedisConnection,須要強制轉換。
maven
利用Redis實現Jms的發佈和訂閱的功能:性能
發佈信息:能夠經過RedisConnection或者RedisTemplate來實現。
redisConnection.publish(byte[] msg,byte[] channel);
template.convertAndSend("hello!","world");
接收消息:在接受放,能夠訂閱根據頻道名來訂閱一個或多個頻道或者經過模式匹配。模式匹配很是有用,由於它不只容許一個命令建立多個訂閱,也能監聽在訂閱建立以後產生的新的頻道(只要匹配指定的模式)。
在 低層面上,RedisConnection提供subscribe和pSubscribe(根據模式匹配)方法,多個頻道和模式能夠一塊兒做爲參 數,RedisConnection也提供了getSubscription和isSubscribed方法。當用jedis鏈接器時,訂閱命令是同步 的,所以會產生堵塞,會致使該線程一直等待消息,只有當訂閱取消的時候,才釋放線程,採用unsubcribe或pUnsubscribe來取消同線程的 訂閱。爲了處理訂閱消息,須要實現MessageListener callback,每次當新的消息達到時,會調用callback執行onMessage方法,該方法可以得到消息,頻道,以及匹配的模式。
由 於MessageListener的自然堵塞,底層面的消息接收不太被人接受,並且它要求處理鏈接和線程的管理,爲了規避這個問題,sdr提供 RedisMessageListenerContainer,它被用來接受從Redis頻道傳來的消息並注入 MessageListener,RedisMessageListenerContainer負責相應接受消息的線程並派發處處理的監聽器中。
<?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:redis="http://www.springframework.org/schema/redis"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/redis http://www.springframework.org/schema/redis/spring-redis.xsd">
<!-- the default ConnectionFactory -->
<redis:listener-container>
<!-- the method attribute can be skipped as the default method name is "handleMessage" -->
<redis:listener ref="listener" method="handleMessage" topic="chatroom" />
</redis:listener-container>
<bean id="listener" class="redisexample.DefaultMessageDelegate"/>
...
<beans>
redis 對事務提供支持,包括multi,exec,discard命令,這些命令也能用於RedisTemplate,而後redisTemplate不保證用 相同的鏈接在同一個事務執行全部操做。sdr提供SessionCallback接口用於同線程的多操做執行。
Redis支持管道 (pipelining),管道能夠發送多個命令到服務端無需等待反饋而後讀取單一步的反饋。管道在你須要一行發送多個命令是提高性能,好比對相同的列表 增長多個元素。若是不關注管道操做的結果,則能夠調用RedisTemplate標準的excute方法,傳遞true做爲pipeline參數。 excutePipelined方法執行RedisCallback或者sessionCallback,而後返回結果。
List<Object> results = stringRedisTemplate.executePipelined(new RedisCallback<Object>() {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
StringRedisConnection stringRedisConn = (StringRedisConnection)connection;
for(int i=0; i< batchSize; i++) {
stringRedisConn.rPop("myqueue");
}
return null;//必須返回null
}
});//results爲myqueue的value。
Redis2.6 以及更高的版本支持經過eval和evalsha命令執行lua script。sdr封裝代碼執行,串行化以及利用代碼緩存。scripts可以經過RedisTemplate的execute方法來運 行,RedisTemplate用一個可配置的ScriptExecutor來執行提供的代碼。缺省的ScriptExecutor經過獲取代碼的 sha1,嘗試運行evalsha,失敗後執行eval。
lua script通常用於原子操做且命令的行爲被另外的命令結果所影響。
配置:
<bean id="script" class="org.springframework.data.redis.core.script.DefaultRedisScript">
<property name="location" value="classpath:META-INF/scripts/checkandset.lua"/>
<property name="resultType" value="java.lang.Boolean"/>
</bean>
java代碼:
@Autowired
RedisScript<Boolean> script;
public boolean checkAndSet(String expectedValue, String newValue) {
return redisTemplate.execute(script, Collections.singletonList("key"),
expectedValue, newValue);
}
lua script:
-- checkandset.lua
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then
redis.call('SET', KEYS[1], ARGV[2])
return true
end
return false
redis 支持類存放在org.springframework.data.redis.support,RedisSet和RedisZSet提供Redis支持 的intersection以及union等方法。RedisList能夠實現Queue以及Deque來實現FIFO和LiFO。
配置:
<bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
<constructor-arg ref="redisTemplate"/>
<constructor-arg value="queue-key"/>
</bean>
代碼:
// injected
private Deque<String> queue;
public void addTag(String tag) {
queue.push(tag);
}
Sdr提供了一個spring3.1 cache abstraction的實現。配置:
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" c:template-ref="redisTemplate"/>