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();    }}






0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 和教育退订不了怎么办 舒张压降不下来怎么办 题目一行写不下怎么办 明细账写错了怎么办 生活太单调乏味怎么办 png图片不清晰怎么办 发票没写单位怎么办 右转车道直行了怎么办 注塑模具产品吸气怎么办 包装机理料线缺料不停怎么办 儿童小脑发育不好怎么办 普通税票弄坏了怎么办 肠胃不好人消瘦怎么办 子宫小发育不良怎么办 卵泡涨的慢怎么办 先天性子宫发育不良怎么办 签证出生日期错了怎么办 车启动开不动怎么办 etc显示无效卡怎么办 最小化只能保留一个怎么办 word句号在中间怎么办 搜狗输入法打不出字怎么办 台式电脑键盘打不出字怎么办 键盘挨锁了怎么办 名牌包过安检怎么办 和地铁安检员冲突怎么办 乘客不配合安检怎么办? 富人移民了穷人怎么办 感觉自己太帅怎么办 上海街头艺人证怎么办 婆婆死了带孩子怎么办 婆婆不带孩子怎么办 空腹吃李子了怎么办 唱歌不在调上怎么办 彩色衣服变黄怎么办 小学生学习态度不好怎么办 孕晚期血小板低怎么办 情侣空间别人不同意怎么办 手机屏幕进了水怎么办 买到二次号码怎么办 买到二手号码怎么办