标签:
普通的基于mss框架的系统在并发量不是很高的情况下,对redis的需求不是很高。redis在系统中的角色相当于一个对象缓存器,在高并发的系统中(比如秒杀系统),在某一刻对数据库中的一条数据可能是成千上万的用户同时去访问,系统的用户体验度直接受到数据库的性能的影响。为了保证数据的完整性,用户只能串行访问数据库中的某一条记录。redis则是把记录对应的对象序列化存储在自身的容器中,减少数据库的压力。废话不多说,接下来简单介绍redis的使用。
http://www.newasp.net/soft/67186.html#downloaded
该地址有redis的介绍,安装以及启动。
<dependency>
<groupId>redis.client</groupId>
<artifactId>jedis</artifactId>
<version>2.7.3</version>
</dependency>
Jedis jedis = jedisPool.getResource();
返回一个操作redis对象池的对象,该对象的存储方式类似于map一样也是采用键值对来存储对象的。jedisPool的初始化采用构造函数指明redis服务器所在的ip地址跟监听的接口,如果实验的redis服务器在本机则ip地址填写localhost即可。
如以上所说,redis服务器以键值对来存储对象,但是值得存储方式是将对象序列化再进行存储。jdk为用户提供了一套对象序列化API,此时大家想到的应该是让被序列化类去实现Serializable接口。这种方法是可行的,但是缺点在与sun提供的这套API是比较低效率的,而且压缩之后的对象还是比较占空间的。此时我们可以采用Protostuff对象提供的序列化API,测试证明了这套API的序列化效率更高切压缩空间更小。
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-core</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>com.dyuproject.protostuff</groupId>
<artifactId>protostuff-runtime</artifactId>
<version>1.0.8</version>
</dependency>
<dependency>
<groupId>velocity</groupId>
<artifactId>velocity</artifactId>
<version>1.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2</version>
</dependency>
RuntimeSchema<T> schema = RuntimeSchema.createFrom(T.class);
首先是告知protostuffIOUtil即将要序列化的对象的序列化规则。
byte[] bytes = ProtostuffIOUtil.toByteArray(Object, schema,LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
将Object对象进行序列化,schema则是序列化规则,参数三是序列过过程中使用到的缓冲区。
如上面提到的,schema代表序列化规则,所以通过Object object = schema.newMessage();可以让容器按规则生成一个空对象,在根据冲redis中拿到的序列值进行反化
ProtostuffIOUtil.mergeFrom(bytes,object,schema);
该方法是根据参数三的对象序列化规则,对参数一的序列值进行操作,然后将对象封装在空对象object中。
讲了这么对先在该说说redis的存取方法了,如同上面我所说的一样,跟map集合很相似的是redis的取值也是使用get(“key”)方法。不过传入的参数必须是字节数组,而且方法的返回值也是一个字节数组,所以只要将返回的字节数组使用Protostuff的反序列化即可得到所要的对象。
byte[] bytes = jedis.get(key.getBytes());
不同的是redis的存储并不是使用put()方法,而是setex(key.getBytes(), timeout, bytes);方法。方法中的参数一是键值对中的键,参数三是序列化后的对象字节数组,参数二是指明该对象在redis服务器中缓存多长时间,它的单位是秒。
int timeout = 60 * 60;
String result = jedis.setex(key.getBytes(), timeout, bytes);
package org.seckill.dao.cache;
import com.dyuproject.protostuff.LinkedBuffer;
import com.dyuproject.protostuff.ProtostuffIOUtil;
import com.dyuproject.protostuff.runtime.RuntimeSchema;
import org.seckill.entity.Seckill;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* Created by Administrator on 2016/8/10 0010.
*/
public class RedisDao{
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private JedisPool jedisPool;
//序列化工具类,泛型指明该类序列化的规则
private RuntimeSchema<Seckill> schema = RuntimeSchema.createFrom(Seckill.class);
public RedisDao(String ip,int port){
jedisPool = new JedisPool(ip,port);
}
public Seckill getSeckill(long seckillId){
//redis操作逻辑
try {
Jedis jedis = jedisPool.getResource();
try {
String key = "seckill:" + seckillId;
//并没有实现内部序列化操作
//get->byte[]->反序列化->Object(Seckill)
//采用自定义序列化
byte[] bytes = jedis.get(key.getBytes());
//缓存重新取到
if(bytes != null){
//空对象
Seckill seckill = schema.newMessage();
ProtostuffIOUtil.mergeFrom(bytes,seckill,schema);
//seckill 被反序列了
return seckill;
}
}finally {
jedis.close();
}
}catch (Exception e){
logger.error(e.getMessage(),e);
}
return null;
}
public String putSeckill(Seckill seckill){
//set Object(Seckill)->序列化->byte[]
try{
Jedis jedis = jedisPool.getResource();
try {
String key = "seckill:" + seckill.getSeckillId();
byte[] bytes = ProtostuffIOUtil.toByteArray(seckill, schema,
LinkedBuffer.allocate(LinkedBuffer.DEFAULT_BUFFER_SIZE));
//超时缓存
int timeout = 60 * 60;
String result = jedis.setex(key.getBytes(), timeout, bytes);
return result;
}finally{
jedis.close();
}
}catch (Exception e){
logger.error(e.getMessage(),e);
}
return null;
}
}
如有什么不足或者错误的地方希望大家留言指出,转载的话请标明出处;
标签:
原文地址:http://www.cnblogs.com/onedaylin/p/5801419.html