spring data redis推薦jedis,因此稍微把jedis稍微看了下,jedis是redis的java客戶端。
sdr支持低層次的通過連接器connector連接到Redis,支持高層次的友好的模板類RedisTemplate,RedisTemplate是建立在低級別的connection基礎之上。RedisConnection接收或返回字節數組需要自身處理連接,比如關閉連接,而RedisTemplate負責處理串行化和反串行化,并且管理對連接進行管理。RedisTemplate提供操作視圖,比如(Bound)ValueOperations,
(Bound)ListOperations,(Bound)SetOperations,(Bound)ZSetOperations,(Bound)HashOperations。RedisTemplate是線程安全的,能夠用于多個實例中。
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"/>
使用樣例:
由于大部分Redis鍵值對存儲都是鍵值均為字符串,因此sdr做了兩個擴展,即StringRedisConnection以及StringRedisTemplate,兩個擴展均采用StringRedisSerializer。
代碼示例:
<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"/>
<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate"
p:connection-factory-ref="jedisConnectionFactory"/>
</beans>p:connection-factory-ref="jedisConnectionFactory"/>
使用樣例:
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());
}
}
// 注入實際的模板
@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"/>
p:connection-factory-ref="jedisConnectionFactory"/>
代碼示例:
@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,需要強制轉換。
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負責相應接受消息的線程并派發到處理的監聽器中。
redis對事務提供支持,包括multi,exec,discard命令,這些命令也能用于RedisTemplate,然后redisTemplate不保證用相同的連接在同一個事務執行所有操作。sdr提供SessionCallback接口用于同線程的多操作執行。
Redis支持管道(pipelining),管道可以發送多個命令到服務端無需等待反饋然后讀取單一步的反饋。管道在你需要一行發送多個命令是提升性能,比如對相同的列表增加多個元素。如果不關注管道操作的結果,則可以調用RedisTemplate標準的excute方法,傳遞true作為pipeline參數。excutePipelined方法執行RedisCallback或者sessionCallback,然后返回結果。
配置:
Sdr提供了一個spring3.1 cache abstraction的實現。配置:
private StringRedisTemplate redisTemplate;
public void addLink(String userId, URL url) {
redisTemplate.opsForList().leftPush(userId, url.toExternalForm());
}
RedisTemplate以及其子類都允許開發者通過RedisCallback直接跟Redis通信,在callback中,開發者獲得RedisConnection。StringRedisTemplate在callback中可以獲得StringRedisConnection,需要強制轉換。
利用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>
<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一般用于原子操作且命令的行為被另外的命令結果所影響。
配置:
redis支持類存放在org.springframework.data.redis.support,RedisSet和RedisZSet提供Redis支持的intersection以及union等方法。RedisList可以實現Queue以及Deque來實現FIFO和LiFO。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代碼:
<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:
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
local current = redis.call('GET', KEYS[1])
if current == ARGV[1]
then
redis.call('SET', KEYS[1], ARGV[2])
return true
end
return false
配置:
<bean id="queue" class="org.springframework.data.redis.support.collections.DefaultRedisList">
<constructor-arg ref="redisTemplate"/>
<constructor-arg value="queue-key"/>
</bean>
代碼:<constructor-arg ref="redisTemplate"/>
<constructor-arg value="queue-key"/>
</bean>
// injected
private Deque<String> queue;
public void addTag(String tag) {
queue.push(tag);
}
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"/>