spring - redis开发简介
来源:互联网 发布:深圳冰川网络 张雄 编辑:程序博客网 时间:2024/06/07 00:46
一.Redis简介
Redis是一款key-value 数据库,这种数据库的特点就是NOSQL,顾名思义就是没有SQL语句,我们可以由键直接取到值。Redis的键值可以包括字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)等数据类型。 对于这些数据类型,你可以执行原子操作。例如:对字符串进行附加操作(append);递增哈希中的值;向列表中增加元素;计算集合的交集、并集与差集等。为了获得优异的性能,Redis采用了内存中(in-memory)数据集(dataset)的方式。根据使用场景的不同,你可以每隔一段时间将数据集转存到磁盘上来持久化数据,或者在日志尾部追加每一条操作命令。
Redis同样支持主从复制(master-slave replication),并且具有非常快速的非阻塞首次同步(non-blocking first synchronization)、网络断开自动重连等功能。同时Redis还具有其它一些特性,其中包括简单的check-and-set机制、 pub/sub和配置设置等,以便使得Redis能够表现得更像缓存(cache)。
二.Redis和Memcached比较
1.性能上
Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis。虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。
2.内存利用效率
在内存使用效率上,如果使用简单的key-value存储,Memcached的内存利用率更高。而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。
3.数据的恢复
我们现在所使用的技术是mysql + memcached。memcached只负责缓存这块,它不负责对数据进行恢复的操作。Redis当然它有数据恢复的功能,在重启时数据是可以恢复的
4.传输速率
主要是测试了redis 的value以及hash,在数据量大的情况下,也就是高并发的情况下,redis的传输速率是memcached的两倍。所以数据量大的情况下最好使用redis。
三.Redis + Spring集成
由于 Redis 可以在重启时恢复数据,所以redis 的配置文件和mysql 的配置文件比较相似,用法同样也是比较相似的。所以学习redis我们其实可以把它当作数据库学习(其实它就是一个数据库)而不仅仅是缓存。
1.架包的配置
同数据库一样,想要用它就必须导入它的架包, 同时要注意一点架包的版本,导入版本不匹配的话,会出现一大堆的问题。建议架包的配置规则:
commons-pool-1.5.6.jar : 数据库连接池所需类,redis就是数据库。
jedis-2.1.0.jar : jedis 连接池jar包。
Spring-data-redis-1.0.2.RELEASE.jar : spring 整合redis 的包。
他们的版本最好是按以上的版本导入,版本不一致可能出现版本不匹配的现象。
2.配置文件的配置
配置文件的配置和 mysql 的配置文件很像,基本一样。
①如果你把 redis当作数据库取代 mysql 的话,就可以在ApplicationContext.xml 中配置如下,为了实现存储的Value是任意类型,这里针对key 和value 进行了单独的配置。
<?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"xmlns:context="http://www.springframework.org/schema/context" xmlns:mongo="http://www.springframework.org/schema/data/mongo"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/data/mongohttp://www.springframework.org/schema/data/mongo/spring-mongo-1.0.xsdhttp://www.springframework.org/schema/beans" >http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> //扫描service层<context:component-scan base-package="com.redisConfig.service"/>//扫描dao层<context:component-scan base-package="com.redisConfig.dao"/>//配置连接池的属性 <bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxActive" value="50" /> <!--最大连接数--> <property name="maxIdle" value="10" /> <!--最大空闲数--> <property name="maxWait" value="1000" /> <!--最大等待时间ms--> <property name="testOnBorrow" value="true" /> <!--取得连接是否进行验证--></bean>//配置redis连接 <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory" p:host-name="192.168.6.89" p:port="6379" p:pool-config-ref="poolConfig"/> //配置键的数据类型 (key:String) <bean id="keyRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"></bean>//配置值的数据类型 这里是将键和值拆分的配置,主要是实现Value存储可以任意类型 (value:Object) <bean id="valueRedisSerializer" class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer"></bean> <bean id="objectRedisTemplate" class="org.springframework.data.redis.core.RedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> <property name="keySerializer" ref="keyRedisSerializer"/> //对值进行序列化 <property name="hashKeySerializer" ref="valueRedisSerializer"/> </bean></beans>
②如果使用如下的配置,那么Value的值只能存储String 类型。
<bean id="stringRedisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="connectionFactory"/> </bean>
1.java代码的实现
既然说它像 mysql ,连配置文件都是那么的相似。他们的使用方法是否也是惊人的相似呢?
是的。他们的使用方法基本上是一样的,当然 mysql 查询数据的不同是 sql 的不同,redis 的不同是key 的不同。这里就要说一下NOSQL的理念。这就是 redis 本质上和关系型数据库的不同。Mysql 在dao 层是利用 JdbcTemplate 这个类,而 redis 主要是利用 RedisTemplate 这个类。两者之间有着惊人的相似。下面我们就将 redis 在dao层 的实现情景回想一下,是不是这样的,mysql会利用 JdbcTemplate 去调用方法,中间填充sql语句,那我们的 redis 会不会也是 利用 RedisTemplate 去调用方法,只是 sql 语句变成了 key,这种 key - value 的方式我们很熟悉,容器中的 map 和这个很像。结合以上的信息,我们组合一下,就很好的使用 redis了。这里要特殊说明一下,redis 的五种存储结构:字符串(strings)、哈希(hashes)、列表(lists)、集合(sets)和 有序集合(sorted sets)。在这里你可以选择那种存储结构。具体的代码如下:
①.dao层的实现
//dao层的代码@Repositorypublic class StudentDao { @Autowiredprivate RedisTemplate<String, Object> objectRedisTemplate;//存入缓存 存储结构为字符串 public void addValue(String key, String value){ objectRedisTemplate.opsForValue().set(key, value);}//取出缓存 存储结构为字符串 public Object getValue(String key){ return objectRedisTemplate.opsForValue().get(key);}//存入缓存 存储结构为列表 public void addList(String key, String value){ objectRedisTemplate.opsForList().rightPush(key, value);}//取出缓存 存储结构为列表 public List<Object> getList(String key){ List<Object> list = new ArrayList<Object>(); Long size = objectRedisTemplate.opsForList().size(key); for (int i = 0; i < size; i++) { list.add(objectRedisTemplate.opsForList().leftPop(key));} return list; } public void addHash(String key, String field, String value){ objectRedisTemplate.opsForHash().put(key, field, value); } public String getHash(String key,String field){ return objectRedisTemplate.opsForHash().get(key, field).toString(); } public void addHashObject(String key, Object field, Object value){ objectRedisTemplate.opsForHash().put(key, field, value); } public Object getHashObject(String key,Object field){ return objectRedisTemplate.opsForHash().get(key, field); } public void delHashObject(String key,Object field){ objectRedisTemplate.opsForHash().delete(key, field); }}
要注意是所有的 key 都是不能相同,即使用不同的存储结构。同一个存储结构,相同的 key 可能覆盖,也可能添加,但是不同存储结构的相同的 key 这是一定会报错的。所有不同类型的 key 可以加上类型的标识,防止错误。
Ⅰ. opsForValue
字符串(strings)存储结构,key - value 形式,和 Map 很相似。存储时添加时用set() ,取出用get() ,key 相等时,值是会覆盖的。
Ⅱ. opsForHash
哈希(hashes)存储结构,哈希相信大家很熟悉,Hashmap我们经常使用的容器,他们存储在hash表中。他的添加和取值比较有意思。个人觉得他有两个键objectRedisTemplate.opsForHash().put(key, field, value);
Key 和 field 都算是他的键,取值时也是两键组合才能取出值。同时这种存储结构占用内存是比较其他的存储结构都是要低的。
Ⅲ. opsForList
列表(lists)存储结构,像队列(queue)。存储时可以从两边加入到队列中,取出时也可以从队列的两边取。当然当数据取出时,数据就不存在。这让我想起了消息服务器ActiveMQ 的点对点的消息队列(queue),两个的功能极其的相似,完全可以用 redis 的列表(lists)存储结构来带替,AMQ的 Queue 队列,实现消息的传递。这里面key 相等,数据重复,是可以保存的,不会覆盖。
Ⅳ. opsForSet
集合(sets)存储结构,无序,key 相等 ,重复数据 只会保存一个。一旦取出数据后,下次再取就没有数据了,会被认为是消费了。
Ⅴ. opsForZSet
有序集合(sorted sets)存储结构。没有测试,有兴趣可以自己测试。
②. service 层的实现
@Componentpublic class StudentService { @Autowired private StudentDao studentDao; public void student(){ studentDao.addValue("key-redis0", "key-value"); studentDao.addValue("key-redis0", "key-value2"); studentDao.addValue("key-redis0", "key-value3"); System.out.println(studentDao.getValue("key-redis0")); } public void student2(){ studentDao.addList("key-redis6", "key-value4"); studentDao.addList("key-redis6", "key-value4"); studentDao.addList("key-redis6", "key-value5"); studentDao.addList("key-redis6", "key-value6"); studentDao.addList("key-redis6", "key-value7"); studentDao.addList("key-redis6", "key-value8"); studentDao.addList("key-redis6", "key-value9"); System.out.println(studentDao.getList("key-redis6").toString()); studentDao.addSet("key-redis8", "key-value4"); studentDao.addSet("key-redis7", "key-value4"); studentDao.addSet("key-redis7", "key-value5"); studentDao.addSet("key-redis7", "key-value6"); studentDao.addSet("key-redis7", "key-value7"); studentDao.addSet("key-redis7", "key-value8"); studentDao.addSet("key-redis7", "key-value9"); System.out.println(studentDao.getSet("key-redis7").toString()); System.out.println(studentDao.getSet("key-redis8").toString()); } public void student3(){ List<Student> list = new ArrayList<Student>(); Student student1 = new Student(); student1.setName("郭清鹏"); student1.setPassword("12345"); Student student2 = new Student(); student2.setName("刘绍"); student2.setPassword("12345"); Student student3 = new Student(); student3.setName("王显德"); student3.setPassword("12345"); list.add(student1); list.add(student2); list.add(student3); studentDao.addHashObject("key-student", "Student", list); List<Student> list2 = (List<Student>)studentDao.getHashObject("key-student", "Student"); for (Student student : list2) {System.out.println(student.getName());} }}③.测试
//测试//测试最好用单元测试,平常的main 方法由于要 new 对象,所以注解什么的都没有作用。测试代码如下:@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath*:applicationContext.xml"})public class TestStudentService { @Autowired private StudentService studentService; @Test public void sysout(){ studentService.student(); } @Test public void sysout1(){ //studentService.student2(); studentService.student2(); } @Test public void sysout2(){ studentService.student3(); }}
- spring - redis开发简介
- spring-data-redis简介
- Redis--开发 Spring Redis 应用程序
- 开发 Spring Redis 应用程序
- 开发spring简介
- 开发框架-Spring-简介
- Redis 实例:开发一个Spring Redis应用程序
- 使用spring-data-redis开发redis应用
- Redis简介-安装-Spring-SpringBoot集成教程
- Spring-data-redis简介(转)
- Maven+ Redis+Spring开发实例
- Spring 开发 Swing GUI 简介
- Spring+JDBC组合开发/Spring事务管理简介
- Redis学习之与Spring整合开发
- Spring Boot + Mybatis + Redis二级缓存开发指南
- Spring Boot + Mybatis + Redis二级缓存开发指南
- Redis简介
- Redis 简介
- mac快捷键大全
- javascript作用域链(Scope Chain)初探
- hql语句---fetch关键字学习
- 批量插入数据 C# SqlBulkCopy使用
- 关于id Tech5的MegaTexture技术
- spring - redis开发简介
- 第九章 中位数和顺序统计量
- ns3中采用Linux模式启动dce的问题
- ef根据年月进行分组
- iOS开发--Advanced NSOperations
- android webview 缩放及换行 及其webview 进度条
- hibernate3第六章之性能优化相关几个问题_1
- mysql导入数据
- 映射公网(花生壳、PubYun、No-IP、DynDNS、Ngrok、Tunnel、localtunnel、pagekite)