Redis缓存方案

1 Redis简介
  Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工做由VMware主持。
  redis是一个key-value存储系统。和Memcached相似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set –有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操做,并且这些操做都是原子性的。在此基础上,redis支持各类不一样方式的排序。与memcached同样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操做写入追加的记录文件,而且在此基础上实现了master-slave(主从)同步。
2 安装
  2.1 安装环境:
    CentOS 6.5
    Redis 2.8.13html

 

  2.2 下载安装:
    下载文件到 /opt/ 目录下
      wget http://download.redis.io/releases/redis-2.8.13.tar.gz
    解压文件
      tar zxvf redis-2.8.13.tar.gz
    切换目录到 redis-2.8.13 目录下
      cd redis-2.8.13
    执行make命令,最后几行的输出结果
      Hint: To run ‘make test’ is a good ideajava

      make[1]: Leaving directory `/opt/redis-2.8.13/src’mysql

  2.3 执行安装命令
    make install
  提示:
    cd src && make install
    make[1]: Entering directory `/opt/redis-2.8.13/src'linux

    Hint: To run 'make test' is a good ideagit

    INSTALL install
    INSTALL install
    INSTALL install
    INSTALL install
    INSTALL install
    make[1]: Leaving directory `/opt/redis-2.8.13/src'
  根据提示,执行:cd src && make install
  提示:
  Hint: To run 'make test' is a good ideagithub

  INSTALL install
  INSTALL install
  INSTALL install
  INSTALL install
  INSTALL instal
  按照提示执行:make test
  提示:
    You need tcl 8.5 or newer in order to run the Redis test
   make: *** [test] Error 1
  解决方法参考:http://www.linuxfromscratch.org/blfs/view/cvs/general/tcl.htmlredis

3 Redis之java操做篇(Jedis)spring

  主要介绍如何用Jedis对Redis数据库进行操做,只作了简单的例子。前提:安装好Redis数据库,并已启动好服务。sql

  1) 新建测试工程,修改 pom.xml 配置文件数据库

 

 1 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 2  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 3     <modelVersion>4.0.0</modelVersion>
 4     <groupId>org.viking</groupId>
 5     <artifactId>redis_demo</artifactId>
 6     <packaging>war</packaging>
 7     <version>0.0.1-SNAPSHOT</version>
 8     <name>redis_demo Maven Webapp</name>
 9     <url>http://maven.apache.org</url>
10     <dependencies>
11         <dependency>
12             <groupId>jdk.tools</groupId>
13             <artifactId>jdk.tools</artifactId>
14             <version>1.7</version>
15             <scope>system</scope>
16             <systemPath>${JAVA_HOME}/lib/tools.jar</systemPath>
17         </dependency>
18         <dependency>
19           <groupId>junit</groupId>
20           <artifactId>junit</artifactId>
21           <version>4.12</version>
22         </dependency>
23         <dependency>
24           <groupId>redis.clients</groupId>
25           <artifactId>jedis</artifactId>
26           <version>2.8.0</version>
27         </dependency>
28         <dependency>
29           <groupId>commons-pool</groupId>
30           <artifactId>commons-pool</artifactId>
31           <version>1.6</version>
32         </dependency>
33     </dependencies>
34     <build>
35         <finalName>${project.artifactId}</finalName>
36         <plugins>
37             <plugin>
38                 <groupId>org.apache.maven.plugins</groupId>
39                 <artifactId>maven-compiler-plugin</artifactId>
40                 <version>2.3.2</version>
41                 <configuration>
42                     <source>${java-version}</source>
43                     <target>${java-version}</target>
44                     <encoding>utf8</encoding>
45                 </configuration>
46             </plugin>
47         </plugins>
48     </build>
49 </project>

 

  2) 建立 RedisUtil.java (用来测试Reids链接池使用)

 1 package demo;  2 
 3 import redis.clients.jedis.Jedis;  4 import redis.clients.jedis.JedisPool;  5 import redis.clients.jedis.JedisPoolConfig;  6 
 7 public final class RedisUtil {  8 
 9 //Redis服务器IP
10 private static String ADDR = "127.0.0.1"; 11 
12 //Redis的端口号
13 private static int PORT = 6379; 14 
15 //访问密码 16 //private static String AUTH = "admin"; 17 
18 //可用链接实例的最大数目,默认值为8; 19 //若是赋值为-1,则表示不限制;若是pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。
20 private static int MAX_ACTIVE = 1024; 21 
22 //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例,默认值也是8。
23 private static int MAX_IDLE = 200; 24 
25 //等待可用链接的最大时间,单位毫秒,默认值为-1,表示永不超时。若是超过等待时间,则直接抛出JedisConnectionException;
26 private static int MAX_WAIT = 10000; 27 
28 private static int TIMEOUT = 10000; 29 
30 //在borrow一个jedis实例时,是否提早进行validate操做;若是为true,则获得的jedis实例均是可用的;
31 private static boolean TEST_ON_BORROW = true; 32 
33 private static JedisPool jedisPool = null; 34 
35 /**
36  * 初始化Redis链接池 37  */
38 static { 39 try { 40 JedisPoolConfig config = new JedisPoolConfig(); 41 config.setMaxIdle(MAX_ACTIVE); 42 //change "maxActive" -> "maxTotal" and "maxWait" -> "maxWaitMillis" in all examples.
43 config.setMaxTotal(MAX_ACTIVE); 44 config.setMaxIdle(MAX_IDLE); 45 config.setMaxWaitMillis(MAX_WAIT); 46 config.setTestOnBorrow(TEST_ON_BORROW); 47 jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT); 48 } catch (Exception e) { 49 e.printStackTrace(); 50 } 51 } 52 
53 /**
54  * 获取Jedis实例 55  * @return
56  */
57 public synchronized static Jedis getJedis() { 58 try { 59 if (jedisPool != null) { 60 Jedis resource = jedisPool.getResource(); 61 return resource; 62 } else { 63 return null; 64 } 65 } catch (Exception e) { 66 e.printStackTrace(); 67 return null; 68 } 69 } 70 
71 /**
72  * 释放jedis资源 73  * @param jedis 74  */
75 public static void returnResource(final Jedis jedis) { 76 if (jedis != null) { 77 jedisPool.returnResource(jedis); 78 } 79 } 80 }

  3) 建立 TestRedis.java

 1 package demo;  2 
 3 import java.util.HashMap;  4 import java.util.Iterator;  5 import java.util.List;  6 import java.util.Map;  7 import org.junit.Before;  8 import org.junit.Test;  9 import redis.clients.jedis.Jedis;  10 
 11 public class TestRedis {  12     private Jedis jedis;  13 
 14 @Before  15 public void setup() {  16 //链接redis服务器
 17 jedis = new Jedis("127.0.0.1", 6379);  18 }  19 
 20 /**
 21  * redis存储字符串  22  */
 23 @Test  24 public void testString() {  25 //-----添加数据---------- 
 26 jedis.set("name","yuanxj");//向key-->name中放入了value-->yuanxj 
 27 System.out.println(jedis.get("name"));//执行结果:yuanxj 
 28 
 29 jedis.append("name", " is Fraud"); //拼接
 30 System.out.println(jedis.get("name"));  31 
 32 jedis.del("name");  //删除某个键
 33 System.out.println(jedis.get("name"));  34 //设置多个键值对
 35 jedis.mset("name","Viking","age","30","qq","1001");  36 jedis.incr("age"); //进行加1操做
 37 System.out.println(jedis.get("name") + "-" + jedis.get("age") + "-" + jedis.get("qq"));  38 
 39 }  40 
 41 /**
 42  * redis操做Map  43  */
 44 @Test  45 public void testMap() {  46 //-----添加数据---------- 
 47 Map<String, String> map = new HashMap<String, String>();  48 map.put("name", "yuanxj");  49 map.put("age", "30");  50 map.put("qq", "1001");  51 jedis.hmset("user1",map);  52 //第一个参数是存入redis中map对象的key,后面跟的是放入map中的对象的key,后面的key能够跟多个,是可变参数 
 53 List<String> rsmap = jedis.hmget("user1", "name", "age", "qq");  54 System.out.println(rsmap);  55   
 56 //删除map中的某个键值 
 57 jedis.hdel("user1","age");  58 System.out.println(jedis.hmget("user1", "age")); //由于删除了,因此返回的是null 
 59 System.out.println(jedis.hlen("user1")); //返回key为user的键中存放的值的个数2 
 60 System.out.println(jedis.exists("user1"));//是否存在key为user的记录 返回true 
 61 System.out.println(jedis.hkeys("user1"));//返回map对象中的全部key 
 62 System.out.println(jedis.hvals("user1"));//返回map对象中的全部value 
 63   
 64 Iterator<String> iter=jedis.hkeys("user1").iterator();  65 while (iter.hasNext()){  66 String key = iter.next();  67 System.out.println(key+":"+jedis.hmget("user1",key));  68 }  69 }  70 
 71 /** 
 72  * jedis操做List  73  */  
 74 @Test  75 public void testList(){  76 //开始前,先移除全部的内容 
 77 jedis.del("java framework");  78 System.out.println(jedis.lrange("java framework",0,-1));  79 //先向key java framework中存放三条数据 
 80 jedis.lpush("java framework","spring");  81 jedis.lpush("java framework","struts");  82 jedis.lpush("java framework","hibernate");  83 //再取出全部数据jedis.lrange是按范围取出,  84 // 第一个是key,第二个是起始位置,第三个是结束位置,jedis.llen获取长度 -1表示取得全部 
 85 System.out.println(jedis.lrange("java framework",0,-1));  86 
 87 jedis.del("java framework");  88 jedis.rpush("java framework","spring");  89 jedis.rpush("java framework","struts");  90 jedis.rpush("java framework","hibernate");  91 System.out.println(jedis.lrange("java framework",0,-1));  92 }  93 
 94 /** 
 95  * jedis操做Set  96  */  
 97 @Test  98 public void testSet(){  99 //添加 
100 jedis.sadd("user2","yuanxj"); 101 jedis.sadd("user2","Fraud"); 102 jedis.sadd("user2","Viking"); 103 jedis.sadd("user2","Jake"); 104 jedis.sadd("user2","who"); 105 //移除noname 
106 jedis.srem("user2","who"); 107 System.out.println(jedis.smembers("user2"));//获取全部加入的value 
108 System.out.println(jedis.sismember("user2", "who"));//判断 who 是不是user集合的元素 
109 System.out.println(jedis.srandmember("user2")); 110 System.out.println(jedis.scard("user2"));//返回集合的元素个数 
111 } 112   
113 @Test 114 public void test() throws InterruptedException { 115 //jedis 排序 116 //注意,此处的rpush和lpush是List的操做。是一个双向链表(但从表现来看的) 
117 jedis.del("a");//先清除数据,再加入数据进行测试 
118 jedis.rpush("a", "1"); 119 jedis.lpush("a","6"); 120 jedis.lpush("a","3"); 121 jedis.lpush("a","9"); 122 System.out.println(jedis.lrange("a",0,-1));// [9, 3, 6, 1] 
123 System.out.println(jedis.sort("a")); //[1, 3, 6, 9] //输入排序后结果 
124 System.out.println(jedis.lrange("a",0,-1)); 125 } 126 
127 @Test 128 public void testRedisPool() { 129 RedisUtil.getJedis().set("newname", "中文测试"); 130 System.out.println(RedisUtil.getJedis().get("newname")); 131 } 132 }

  4) 测试运行结果

  Run as Junit Test  -> See the result!

 

4 Redis之java操做篇(数据对象的存取)

  摘要:Redis自己没有存取对象的功能,而是有存取byte数据的功能,咱们能够对要存取的对象进行序列化后,进行操做.

  建立SerializeUtil.java

 1 public class SerializeUtil {  2 /**
 3  * 序列化  4  * @param object  5  */
 6 public static byte[] serialize(Object object) {  7 ObjectOutputStream oos = null;  8 ByteArrayOutputStream baos = null;  9 try { 10 // 序列化
11 baos = new ByteArrayOutputStream(); 12 oos = new ObjectOutputStream(baos); 13 oos.writeObject(object); 14 byte[] bytes = baos.toByteArray(); 15 return bytes; 16 } catch (Exception e) { 17  e.printStackTrace(); 18 } 19 return null; 20 } 21 
22 /**
23  * 反序列化 24  * @param bytes 25  */
26 public static Object unserialize(byte[] bytes) { 27 ByteArrayInputStream bais = null; 28 try { 29 // 反序列化
30 bais = new ByteArrayInputStream(bytes); 31 ObjectInputStream ois = new ObjectInputStream(bais); 32 return ois.readObject(); 33 } catch (Exception e) { 34  e.printStackTrace(); 35 } 36 return null; 37 } 38 }

  1) 新建测试对象

 1 package demo.bean;  2 
 3 import java.io.Serializable;  4 
 5 public class Goods implements Serializable {  6     /**
 7  *  8      */
 9     private static final long serialVersionUID = 6856239042967045162L; 10     private String name; 11     private Float price; 12     private String desc; 13     public String getName() { 14         return name; 15  } 16     public void setName(String name) { 17         this.name = name; 18  } 19     public Float getPrice() { 20         return price; 21  } 22     public void setPrice(Float price) { 23         this.price = price; 24  } 25     public String getDesc() { 26         return desc; 27  } 28     public void setDesc(String desc) { 29         this.desc = desc; 30  } 31     
32 }

  2) 新建测试代码

 1 package demo;  2 
 3 import demo.bean.Goods;  4 
 5 public class TestObject {  6     public static void main (String[] args) {  7         Goods g1 = new Goods();  8         g1.setName("苹果");  9  g1.setPrice(5f); 10         g1.setDesc("这里的苹果大又甜"); 11         
12         Goods g2 = new Goods(); 13         g2.setName("橘子"); 14         g2.setPrice(3.5f); 15         g2.setDesc("这里的橘子水不少"); 16         
17         RedisUtil.getJedis().set("g1".getBytes(), SerializeUtil.serialize(g1)); 18         byte[] bg1 = RedisUtil.getJedis().get("g1".getBytes()); 19         Goods rg1 = (Goods)SerializeUtil.unserialize(bg1); 20  System.out.println(rg1.getName()); 21  System.out.println(rg1.getPrice()); 22  System.out.println(rg1.getDesc()); 23  } 24 }

  5 使用mybatis-redis

  mybatis-redis是mybatis集成redis实现二级缓存的一个实现,和mybatis-memcached相似,这种方式是mybatis集成redis最快的方式,无需本身编写代码实现cache接口
  mybatis-redis的官方git地址https://github.com/mybatis/redis-cache
  项目集成mybatis-redis

 1 <dependency>
 2 <groupId>org.mybatis.caches</groupId>
 3 <artifactId>mybatis-redis</artifactId>
 4 <version>1.0.0-beta2</version>
 5 </dependency>
 6 <dependency>
 7 <groupId>redis.clients</groupId>
 8 <artifactId>jedis</artifactId>
 9 <version>2.8.0</version>
10 </dependency>

  在mybatis配置中开启缓存

 1 <setting name="cacheEnabled" value="true"/>
 2 <?xml version="1.0" encoding="UTF-8" ?>
 3 <!DOCTYPE configuration  4  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"  5  "http://mybatis.org/dtd/mybatis-3-config.dtd">
 6 <configuration>
 7     <settings>
 8         <setting name="cacheEnabled" value="true"/>
 9         <!--<setting name="lazyLoadingEnabled" value="false"/>-->
10         <!--<setting name="aggressiveLazyLoading" value="true"/>-->
11     </settings>
12     <plugins>
13         <!--mybatis 分页插件-->
14         <plugin interceptor="com.github.pagehelper.PageHelper">
15             <property name="dialect" value="mysql" />
16         </plugin>
17     </plugins>
18 </configuration>

  在项目的资源(maven resource)目录中加入redis.propertis文件

1 host=localhost

 2 port=6379    

3 timeout=5000   

  最后在mapper映射文件中开启cache便可

 1 <?xml version="1.0" encoding="UTF-8" ?>
 2 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 3 <mapper namespace="com.lisi.test.dao.UserDao">
 4 <!--启用mybatis-redis-->
 5 <cache type="org.mybatis.caches.redis.RedisCache"/>
 6 <resultMap type="User" id="UserResult">
 7 <result property="id" column="id"/>
 8 <result property="uuid" column="uuid"/>
 9 <result property="username" column="username"/>
10 <result property="password" column="password"/>
11 <result property="createTime" column="create_time"/>
12 </resultMap>
13 <insert id="save" parameterType="User">
14 <selectKey resultType="int" keyProperty="id" order="AFTER">
15 SELECT LAST_INSERT_ID() 16 </selectKey>
17 insert into 18 t_user(uuid,username,password,create_time) 19 values(#{uuid},#{username},#{password},#{createTime}) 20 </insert>
21   
22 <delete id="delete" parameterType="long">
23  delete from t_user where id = 24  #{id} 25     </delete>
26    
27 <select id="getById" parameterType="long" resultType="User">
28  select 29  id,uuid,username,password,create_time as createTime from t_user 30  where id=#{id} 31     </select>
32   
33 <update id="update" parameterType="User">
34  update t_user set 35  username=#{username} 36  where id = #{id} 37     </update>
38 </mapper>

6 使用spring-data-redis

  spring-data-redis是比较有名的项目,相关资料不少。
  使用spring-data-redis的关键依赖,由于用到spring,因此spring的相关依赖是须要加入的。

 1 <dependency>
 2 <groupId>redis.clients</groupId>
 3 <artifactId>jedis</artifactId>
 4 <version>2.8.0</version>
 5 </dependency>
 6 <dependency>
 7 <groupId>org.springframework.data</groupId>
 8 <artifactId>spring-data-redis</artifactId>
 9 <version>1.7.2.RELEASE</version>
10 </dependency>

  mybatis使用spring-data-redis集成redis缓存和第一种方式很类似,都须要本身实现cache接口,只是使用spring-data-redis后方便使用spring的方式来管理,

  代码:

 1 /**  2  * Use JedisConnectionFactory  3  */  4 public class SpringRedisCache implements Cache {  5 private static Logger logger = LoggerFactory.getLogger(SpringRedisCache.class);  6 
 7 private JedisConnectionFactory jedisConnectionFactory = (JedisConnectionFactory)SpringContextHolder.getBean("jedisConnectionFactory");  8 private final String id;  9 
 10 private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();  11 
 12 public SpringRedisCache(final String id) {  13 if (id == null) {  14 throw new IllegalArgumentException("Cache instances require an ID");  15 }  16 logger.debug("SpringRedisCache:id=" + id);  17 this.id = id;  18 }  19 
 20 @Override  21 public void clear() {  22 RedisConnection connection = null;  23 try {  24 connection = jedisConnectionFactory.getConnection();  25 connection.flushDb();  26 connection.flushAll();  27 } catch (JedisConnectionException e) {  28 e.printStackTrace();  29 } finally {  30 if (connection != null) {  31 connection.close();  32 }  33 }  34 }  35 
 36 @Override  37 public String getId() {  38 return this.id;  39 }  40 
 41 @Override  42 public Object getObject(Object key) {  43 Object result = null;  44 RedisConnection connection = null;  45 try {  46 connection = jedisConnectionFactory.getConnection();  47 RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();  48 result = serializer.deserialize(connection.get(serializer.serialize(key)));  49 } catch (JedisConnectionException e) {  50 e.printStackTrace();  51 } finally {  52 if (connection != null) {  53 connection.close();  54 }  55 }  56 return result;  57 }  58 
 59 @Override  60 public ReadWriteLock getReadWriteLock() {  61 return this.readWriteLock;  62 }  63 
 64 @Override  65 public int getSize() {  66 int result = 0;  67 RedisConnection connection = null;  68 try {  69 connection = jedisConnectionFactory.getConnection();  70 result = Integer.valueOf(connection.dbSize().toString());  71 } catch (JedisConnectionException e) {  72 e.printStackTrace();  73 } finally {  74 if (connection != null) {  75 connection.close();  76 }  77 }  78 return result;  79 }  80 
 81 @Override  82 public void putObject(Object key, Object value) {  83 RedisConnection connection = null;  84 try {  85 connection = jedisConnectionFactory.getConnection();  86 RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer();  87 connection.set(serializer.serialize(key), serializer.serialize(value));  88 } catch (JedisConnectionException e) {  89 e.printStackTrace();  90 } finally {  91 if (connection != null) {  92 connection.close();  93 }  94 }  95 }  96 
 97 @Override  98 public Object removeObject(Object key) {  99 RedisConnection connection = null; 100 Object result = null; 101 try { 102 connection = jedisConnectionFactory.getConnection(); 103 RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); 104 result = connection.expire(serializer.serialize(key), 0); 105 } catch (JedisConnectionException e) { 106 e.printStackTrace(); 107 } finally { 108 if (connection != null) { 109 connection.close(); 110 } 111 } 112 return result; 113 } 114 }

  上面使用的SpringContextHolder源码

 1 @Component  2 public class SpringContextHolder implements ApplicationContextAware {  3 private static ApplicationContext context;  4 
 5 @Override  6 public void setApplicationContext(ApplicationContext context)  7 throws BeansException {  8 SpringContextHolder.context = context;  9 } 10 public static <T> T getBean(String name){ 11 return (T)context.getBean(name); 12 } 13 }

  在项目的资源(maven resource)目录中加入redis.propertis文件

1 redis.host=localhost 2 redis.port=6379 3 redis.pass= 4 redis.timeout=5000 5 redis.default.db=0 6 redis.maxIdle=300 7 redis.maxActive=600 8 redis.maxWait=1000 9 redis.testOnBorrow=true

  在spring中配置加入

 1  <!-- redis数据池配置 -->
 2 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
 3 <property name="maxIdle" value="${redis.maxIdle}" />
 4 <property name="maxTotal" value="${redis.maxActive}" />
 5 <property name="maxWaitMillis" value="${redis.maxWait}" />
 6 <property name="testOnBorrow" value="${redis.testOnBorrow}" />
 7 </bean>
 8 <!-- Spring-data-redis connectFactory -->
 9 <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
10 <property name="usePool" value="true"></property>
11 <property name="hostName" value="${redis.host}" />
12 <property name="port" value="${redis.port}" />
13 <property name="password" value="${redis.pass}" />
14 <property name="timeout" value="${redis.timeout}" />
15 <property name="database" value="${redis.default.db}"/>
16 <constructor-arg index="0" ref="jedisPoolConfig" />
17 </bean>

  最后修改mapper文件中cache的type为SpringRedisCache便可;

  使用spring-data-redis还可使用它的RedisTemplate去实现cache接口,不过由于RedisTemplate是对JedisConnectionFactory的包装,在spring配置文件的配置更多.

 

<!-- Start -->

获知及时信息,请关注个人我的微信订阅号:0与1的那点事

 

<!-- End -->

 

本文为博主原创文章,转载请注明出处!

http://www.cnblogs.com/libingbin/

感谢您的阅读。

相关文章
相关标签/搜索