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