Redis概要及配置
Redis(Remote Dictionary Server)是一个由key-value的存储系统。是一个开源的使用ANSI C语言、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。它通常被称为数据结构服务器,因为值(value)可以是字符串(String),哈希(Map),列表(list),集合(sets)和有序集合(sorted sets)等类型。
Redis缓存产品有以下三个特点:
1:Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
2:Redis不仅仅支持简单的key-value类型的数据,同时还提供list,set,zset,hash等数据结构的存储。
3:Redis支持数据的备份,即master-slave模式的数据备份。
Redis的优势:
1:性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。
2:丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。
3:原子 – Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
4:丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。
Linux环境安装Redis
解压缩Redis
tar -zxvf redis-4.0.7.tar.gz
编译Redis服务
cd redis-4.0.7
make
开启Redis服务
cd src
./redis-server
开启Redis客户端
cd redis-4.0.7/src
./redis-cli
测试添加key-value
set key value
get key
Redis数据类型
字符串 String
设置:set key value 获取:get key 判断是否存在:exists key 删除:del key 设置生命周期:expire key seconds 查找key:keys pattern (*统配N个字符,?统配1个字符) 序列化:dump key 截取:getrange key start end |
设置:hmset key field value [ field value ] 获取某个字段:hget key field 获取某些字段:hmget key field [ field ] 获取所有数据:hgetall key 删除指定字段:hdel key field [ field ] 是否存在字段:hexists key field 获取所有字段:hkeys key 获取所有值:hvals key |
前追加:lpush key value [ value ] 后追加:rpush key value [ value ] 范围获取:lrange key start stop 指定索引获取:lindex key index 插入元素:linsert key before|after pivot value 前移除:lpop key 后移除:rpop key 范围移除:ltrim key start stop 移除元素:lrem key count value 设置索引值:lset key index value |
添加元素:sadd key member [ member ] 获取元素:smembers key 获取长度:scard key 获取集合交集:sinter key [ key ] 获取交集保存:sinterstore storekey key [ key ] 获取集合差值:sdiff key [ key ] 获取差值保存:sdiffstore storekey key [ key ] 获取集合并集:sunion key [ key ] 获取并集保存:sunionstore storekey key [ key ] 获取随机元素:srandmember key [ count ] 移动元素:smove source destination member 移除随机元素:spop key [ count ] 移除指定元素:srem key member [ member ] |
向有序集合添加一个或多个成员,或者更新已存在成员的分数:zadd key score1 member1 [score2 member2] 有序集合中对指定成员的分数加上增量: increment zincrby key increment member 通过索引区间返回有序集合成指定区间内的成员:zrange key start stop [withscore] 通过分数返回有序集合指定区间内的成员:zrangebyscore key min max [withscore] [limit] 获取有序集合的成员数:zcard key 计算在有序集合中指定区间分数的成员数:zcound key min max 返回有序集合中指定成员的索引:zrank key member 移除有序集合中的一个或多个成员:zrem key member [member ...] 移除有序集合中给定的排名区间的所有成员:zremrangebyrank key start stop 移除有序集合中给定的分数区间的所有成员:zremrangebyscore key min max |
Java连接Redis
1:Pom中添加依赖
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.9.0</version> </dependency> |
2:实例化Jedis对象
Jedis jedis = new Jedis("172.31.79.19",6379); |
System.out.println(jedis.ping()); |
Linux系统设置
1:关闭防火墙
service iptables stop
chkconfig iptables off
2:关闭进程守护模式 redis.conf配置文件中
protected-mode no
3:设置任何ip均可访问 redis.conf配置文件中
bind 0.0.0.0
4:设置redis密码
config set requirepass xxx
5:重启redis服务
./redis-cli shutdown
./src/redis-server ./redis.conf
字符串 String
// 实例化 Jedis对象,连接Redis Jedis jedis = new Jedis("172.31.79.19",6379); // 添加数据 jedis.set("company", "上海博为峰软件股份有限公司"); // 获取数据 System.out.println( jedis.get("company") ); |
哈希 Hash
// 实例化 Jedis对象,连接Redis Jedis jedis = new Jedis("172.31.79.19",6379); // 添加数据 Map<String, String> map = new HashMap<String, String>(); map.put("userId", "100001"); map.put("userName", "张三"); map.put("userAge", "20"); jedis.hmset("user", map); // 获取数据 for( Map.Entry<String, String> field : jedis.hgetAll("user").entrySet() ) { System.out.println( field.getKey() + " => " + field.getValue() ); } |
列表 List
// 实例化 Jedis对象,连接Redis Jedis jedis = new Jedis("172.31.79.19",6379); // 添加数据 jedis.lpush("lessons","JavaSE","Web前段","SQL","JavaEE"); // 获取数据 for( String value : jedis.lrange("lessons", 0, 100) ) { System.out.println( value ); } |
集合 Set
// 实例化 Jedis对象,连接Redis Jedis jedis = new Jedis("172.31.79.19",6379); // 添加数据 Map<String,Double> map = new HashMap<String,Double>(); map.put("Nginx", 1D); map.put("Redis", 2D); map.put("ActiveMQ", 3D); map.put("Dubbo", 4D); jedis.zadd("JavaWeb", map); // 获取数据 for( String member : jedis.zrange("JavaWeb",0,100)) { System.out.println( member ); } |
SSM+Redis整合
Maven+SSM+Redis整合实例
1:Pom添加依赖
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-ehcache</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>1.6.1.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.7.3</version> </dependency> |
<!-- 加载配置文件 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-*.xml</param-value> </context-param> |
3:添加redis配置文件:spring-redis.xml
<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:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 连接池基本参数配置,类似数据库连接池 --> <context:property-placeholder location="classpath:*.properties" /> <!-- redis配置 --> <!-- redis连接池 --> <bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="300"></property> <property name="maxIdle" value="200"></property> <property name="MaxWaitMillis" value="10000"></property> <property name="testOnBorrow" value="true"></property> <property name="testOnReturn" value="true"></property> </bean> <!-- redis连接工厂 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="172.31.79.19"></property> <property name="port" value="6379"></property> <property name="password" value="abc123"></property> <property name="poolConfig" ref="jedisConfig"></property> </bean> <!-- redis操作模板,这里采用尽量面向对象的模板 --> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> </bean> </beans> |
package com.bwf.ssm.redis; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class SerializeUtil { /** * * 序列化 */ public static byte[] serialize(Object obj) { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; try { // 序列化 baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(obj); byte[] byteArray = baos.toByteArray(); return byteArray; } catch (IOException e) { e.printStackTrace(); } return null; } /** * * 反序列化 * * @param bytes * @return */ public static Object unSerialize(byte[] bytes) { ByteArrayInputStream bais = null; try { // 反序列化为对象 bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); return ois.readObject(); } catch (Exception e) { e.printStackTrace(); } return null; } } |
package com.bwf.ssm.redis; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import org.apache.ibatis.cache.Cache; import org.springframework.beans.factory.annotation.Autowired; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; public class RedisCache implements Cache { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); /** * Jedis客户端 */ @Autowired private Jedis redisClient = createClient(); private String id; public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("必须传入ID"); } System.out.println("MybatisRedisCache:id=" + id); this.id = id; } @Override public void clear() { redisClient.flushDB(); } @Override public String getId() { return this.id; } @Override public Object getObject(Object key) { System.out.println("==== Redis ==== GetObject : key = "+key); byte[] ob = redisClient.get(SerializeUtil.serialize(key.toString())); System.out.println("==== Redis ==== GetObject : key = "+SerializeUtil.serialize(key.toString())); if (ob == null) { return null; } Object value = SerializeUtil.unSerialize(ob); return value; } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } @Override public int getSize() { return Integer.valueOf(redisClient.dbSize().toString()); } @Override public void putObject(Object key, Object value) { System.out.println("==== Redis ==== PutObject : key = "+key+" , value = "+value); redisClient.set(SerializeUtil.serialize(key.toString()), SerializeUtil.serialize(value)); } @Override public Object removeObject(Object key) { return redisClient.expire(SerializeUtil.serialize(key.toString()), 0); } protected static Jedis createClient() { try { @SuppressWarnings("resource") JedisPool pool = new JedisPool(new JedisPoolConfig(), "172.31.79.19", 6379,3000,"abc123"); return pool.getResource(); } catch (Exception e) { e.printStackTrace(); } throw new RuntimeException("初始化连接池错误"); } } |
6:要缓存的实体对象实现Serializable接口
7:在需要缓存的mapper上添加:
<cache type="com.bwf.ssm.cache.RedisCache"/>
SSM+Redis参数配置化
1:修改RedisCache类
package com.bwf.redis; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import javax.annotation.Resource; import org.apache.ibatis.cache.Cache; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.data.redis.connection.jedis.JedisConnection; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer; import org.springframework.data.redis.serializer.RedisSerializer; import org.springframework.stereotype.Component; import com.bwf.ssm.redis.SerializeUtil; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.exceptions.JedisConnectionException; public class RedisCache implements Cache { private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock(); private static JedisConnectionFactory jedisConnectionFactory; private String id; public RedisCache(final String id) { if (id == null) { throw new IllegalArgumentException("必须传入ID"); } System.out.println("MybatisRedisCache:id=" + id); this.id = id; } @Override public void clear() { JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); connection.flushDb(); connection.flushAll(); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } } @Override public String getId() { return this.id; } @Override public Object getObject(Object key) { System.out.println("==== Redis ==== GetObject : key = "+key); Object result = null; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = serializer.deserialize(connection.get(serializer.serialize(key))); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } return result; } @Override public ReadWriteLock getReadWriteLock() { return readWriteLock; } @Override public int getSize() { int result = 0; JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); result = Integer.valueOf(connection.dbSize().toString()); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } return result; } @Override public void putObject(Object key, Object value) { System.out.println("==== Redis ==== PutObject : key = "+key+" , value = "+value); JedisConnection connection = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); connection.set(serializer.serialize(key), serializer.serialize(value)); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } } @Override public Object removeObject(Object key) { System.out.println("==== Redis ==== RemoveObject : key = "+key); JedisConnection connection = null; Object result = null; try { connection = jedisConnectionFactory.getConnection(); RedisSerializer<Object> serializer = new JdkSerializationRedisSerializer(); result = connection.expire(serializer.serialize(key), 0); } catch (JedisConnectionException e) { e.printStackTrace(); } finally { if (connection != null) { connection.close(); } } return result; } public static void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.jedisConnectionFactory = jedisConnectionFactory; } } |
2:添加RedisCacheTransfer类
package com.bwf.redis; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; public class RedisCacheTransfer { @Autowired public void setJedisConnectionFactory(JedisConnectionFactory jedisConnectionFactory) { RedisCache.setJedisConnectionFactory(jedisConnectionFactory); } } |
3:修改spring-redis.xml文件
<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:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> <!-- 连接池基本参数配置,类似数据库连接池 --> <context:property-placeholder location="classpath:*.properties" /> <!-- 自动扫描 --> <context:component-scan base-package="com.bwf.redis.*" /> <!-- redis配置 --> <!-- redis连接池 --> <bean id="jedisConfig" class="redis.clients.jedis.JedisPoolConfig"> <property name="maxTotal" value="300"></property> <property name="maxIdle" value="200"></property> <property name="MaxWaitMillis" value="10000"></property> <property name="testOnBorrow" value="true"></property> <property name="testOnReturn" value="true"></property> </bean> <!-- redis连接工厂 --> <bean id="connectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"> <property name="hostName" value="192.168.136.131"></property> <property name="port" value="6379"></property> <property name="password" value="abc123"></property> <property name="poolConfig" ref="jedisConfig"></property> </bean> <!-- redis操作模板,这里采用尽量面向对象的模板 --> <bean id="redisTemplate" class="org.springframework.data.redis.core.StringRedisTemplate"> <property name="connectionFactory" ref="connectionFactory" /> <property name="keySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="valueSerializer"> <bean class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" /> </property> <property name="hashKeySerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> <property name="hashValueSerializer"> <bean class="org.springframework.data.redis.serializer.StringRedisSerializer" /> </property> </bean> <!-- 使用中间类解决RedisCache.jedisConnectionFactory的静态注入,从而使MyBatis实现第三方缓存 --> <bean id="redisCacheTransfer" class="com.bwf.redis.RedisCacheTransfer"> <property name="jedisConnectionFactory" ref="connectionFactory" /> </bean> </beans> |