Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它能夠用做數據庫、緩存和消息中間件. 它支持多種類型的數據結構。html
Redis3.0+ 版本開始支持集羣java
字符串(strings)git
散列(hashes)github
列表(lists)redis
集合(sets)spring
有序集合(sorted sets)數據庫
數據緩存express
併發控制(分佈式鎖)編程
發佈訂閱(Pus/Sub)windows
消息隊列
HttpSession共享
登陸
redis.conf(windows版本下叫redis.windows.conf)
運行時配置更改
Redis容許在運行的過程當中,在不重啓服務器的狀況下更改服務器配置,同時也支持 使用特殊的CONFIG SET和 CONFIG GET命令用編程方式查詢並設置配置。
並不是全部的配置指令都支持這種使用方式,可是大部分是支持的。更多相關的信息請查閱CONFIG SET和 CONFIG GET頁面。
須要確保的是在經過CONFIG SET命令進行的設置的同時,也需在 redis.conf文件中進行了相應的更改。 將來Redis有計劃提供一個CONFIG REWRITE命令在不更改現有配置文件的同時, 根據當下的服務器配置對redis.conf文件進行重寫。
配置參數項詳解:http://www.runoob.com/redis/redis-conf.html
Redis官方網站:http://redis.io/
Redis中文社區:http://redis.cn/
spring-data-redis 1.5新特性
支持redis中HyperLogLog
RedisSerializers基於jackson
支持配置redis集羣
spring-data-redis 1.6新特性
支持 ZRANGEBYLEX 命令
ZSET
操做範圍負無窮到正無窮
RedisCache性能改進
通用Jackson2序列化、反序列化
spring-data-redis須要
jdk1.6+
spring3.2.8+
redis2.8+(or redis latest 2.6 )
ValueOperations | 對字符串操做 |
ListOperations | 對List集合操做 |
SetOperations | 對Set集合操做 |
ZSetOperations | 對有序set操做 |
HashOperations | 對Hash集合操做 |
HyperLogLogOperations | 對HyperLogLog操做 |
併發控制(分佈式鎖)
// 若是沒有設置進行設置 redisTemplate.opsForValue().setIfAbsent(key, value); // 給key設置過時時間,避免死鎖 redisTemplate.expire(key, timeout, unit);
Redis 事務能夠一次執行多個命令, 而且帶有如下兩個重要的保證:
一個事務從開始到執行會經歷如下三個階段:
public void multi() { long start = System.currentTimeMillis(); List result = redisTemplate.execute(new SessionCallback>() { @Override public List execute(RedisOperations operations) throws DataAccessException { operations.multi(); for (int i = 0; i < 100000; i++) { String key = "key" + i; String value = "value" + i; redisTemplate.opsForValue().set(key, value); } return operations.exec(); } }); long end = System.currentTimeMillis(); System.out.println("result:" + result + ",millis:" + (end - start)); }
支持事務註解
redisTemplate.setEnableTransactionSupport(true);
Redis管道一樣是打開管道,一次性向redis服務端發送命令,最後關閉管道,可是它跟事務是有區別的,Redis管道只是減小了鏈接消耗,並不具有事務的特性,它會進行一次性提交和一次性響應,成功的命令會執行,失敗的跳過,最終一次性返回結果。
使用Redis管道技術在批量發送redis命令的狀況下比較適用,能夠極大的提供執行效率。
public void pipelined() { long start = System.currentTimeMillis(); stringRedisTemplate.executePipelined(new RedisCallback() { public Object doInRedis(RedisConnection connection) throws DataAccessException { StringRedisConnection stringRedisConn = (StringRedisConnection) connection; for (int i = 0; i < 100000; i++) { stringRedisConn.set("key" + i, "value" + i); } return null; } }); long end = System.currentTimeMillis(); System.out.println("millis:" + (end - start)); }
Redis和lua都是基於C語言實現的,因此Redis中採用內置lua腳本解釋器,來支持lua腳本,lua很小。
目前還不是特別理解Redis腳本的使用場景,我的感受相似關係型數據庫中存儲過程的概念。
如下是一段java調用redis執行lua腳本的代碼示例:
java:
public void redisLuaScript() { DefaultRedisScript redisScript = new DefaultRedisScript(); ClassPathResource resource = new ClassPathResource("/redisScript/demo.lua"); redisScript.setScriptSource(new ResourceScriptSource(resource)); redisScript.setResultType(String.class); List keys = new ArrayList(); keys.add("mykey1"); keys.add("mykey2"); String result = redisTemplate.execute(redisScript, keys, new Object[] { "123", "456" }); System.out.println(result); }
if redis.call('GET', KEYS[1]) == false then redis.call('SET', KEYS[1], ARGV[1]) end if redis.call('GET', KEYS[2]) == false then redis.call('SET', KEYS[2], ARGV[2]) end return "ok"
SDR封裝了經過調用java原生的集合操做Redis數據類型,下降了在java中操做Redis數據類型的複雜度,同時也使得java原生集合支持分佈式
@Resource(name = "deque") private Deque deque; @Resource(name = "map") private Map map; @Test public void redisQueue() { deque.push("test1"); } @Test public void redisMap(){ map.put("key1", "v1"); }
spring cache 是一個spring緩存組件,spring3.1之後提供了Spring cache緩存抽象,和其餘spring組件同樣,例如spring事務等,採用註解驅動的方式,利用Spring AOP(動態代理)結合XML Schema來實現,採用這用方式對代碼的侵入性極小,是一種輕量級的緩存抽象。
SDR對SpringCache提供支持,將原有的基於JVM容器的緩存,採用基於Redis緩存中間件來完成,實現了分佈式緩存。
<cache:annotation-driven /> <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager"> <constructor-arg ref="redisTemplate" /> </bean>
@Cacheable(value = "userCache",condition="#mobile ne null and #mobile ne ''",unless = "#result eq '' or #result eq null") @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) @Override public User getUserByMobile(String mobile) { System.out.println("execute getUserByMobile start..."); User user = userDao.getUserByMobile(mobile); System.out.println("execute getUserByMobile end..."); return user; }
spring cache支持 SpEL語法
SpEL語法詳見官方介紹:http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#expressions
@Cacheable triggers cache population @CacheEvict triggers cache eviction @CachePut updates the cache without interfering with the method execution @Caching regroups multiple cache operations to be applied on a method @CacheConfig shares some common cache-related settings at class-level
@Cacheable
應用於方法上,若是存在緩存值則直接返回,若是不存在緩存則向下執行實際方法,
value參數,Redis中ZSET集合的鍵
condition參數,對傳入參數的篩選
unless參數,對返回結果的篩選
@CacheEvict
用於緩存發生變化時,對以前的緩存進行收回
@CachePut
更新緩存,執行實際的方法
@Caching
容許嵌套多個@Cacheable 、@CacheEvict、@CachePut
@Caching(evict = { @CacheEvict("primary"), @CacheEvict(cacheNames="secondary", key="#p0") })
@CacheConfig
緩存配置註解,這是一個類級別的註解,對緩存鍵的統一管理
@Service("userService") @CacheConfig(cacheNames="userCache") public class UserServiceImpl implements UserServices { @Resource(name = "userDao") private UserDao userDao; @Cacheable(condition="#mobile ne null and #mobile ne ''",unless = "#result eq '' or #result eq null") @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true) @Override public User getUserByMobile(String mobile) { System.out.println("execute getUserByMobile start..."); User user = userDao.getUserByMobile(mobile); System.out.println("execute getUserByMobile end..."); return user; } }
redisTemplate.convertAndSend("demo:message", "This is a new message...");
<!-- redis訂閱 --> <bean id="messageListener" class="org.springframework.data.redis.listener.adapter.MessageListenerAdapter"> <property name="delegate"> <bean id="demoListener" class="com.demo.lisenter.DemoListener" /> </property> <property name="serializer" ref="jdkSerializer" /> </bean> <bean id="redisContainer" class="org.springframework.data.redis.listener.RedisMessageListenerContainer"> <property name="connectionFactory" ref="jedisConnectionFactory" /> <property name="messageListeners"> <map> <entry key-ref="messageListener"> <bean class="org.springframework.data.redis.listener.ChannelTopic"> <constructor-arg value="demo:message" /> </bean> </entry> </map> </property> </bean>
Redis Sentinel 是Redis自2.8+之後Redis自身提供的高可用解決方案
Redis Sentinel提供任務監控、預警通知、自動故障轉移
在配置Redis Sentinel以前須要先配置Redis主從
一、在從庫的redis.conf文件中增長以下配置:
# slaveof <masterip> <masterport>
slaveof 10.200.0.102 6379
二、sentinel.conf
port 26379 daemonize yes sentinel monitor mymaster 10.200.0.102 6379 2 sentinel down-after-milliseconds mymaster 30000 sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymaster 900000
<!-- redis哨兵--> <bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration"> <property name="master"> <bean class="org.springframework.data.redis.connection.RedisNode"> <property name="name" value="mymaster" /> </bean> </property> <property name="sentinels"> <set> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="10.200.0.102" /> <constructor-arg name="port" value="26379" /> </bean> <bean class="org.springframework.data.redis.connection.RedisNode"> <constructor-arg name="host" value="10.200.0.102" /> <constructor-arg name="port" value="26380" /> </bean> </set> </property> </bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <constructor-arg ref="sentinelConfig" /> </bean>
程序經過Redis Sentinel 鏈接到Redis主庫6379
中止6379
src/redis-cli shutdown
自動切換至6380
在這個過程當中,Redis會自動修改sentinel.conf和redis.conf