ITOO---“秒杀”选课之Redis序列化
来源:互联网 发布:mac 体验 编辑:程序博客网 时间:2024/06/01 09:56
1.我的选课
在进行选课活动中了为了尽量减少客户端和数据库的连接次数,在实现的思路是这样设计的:客户端的请求优先访问Redis缓存空间,如果Redis中没有则从数据库中加载,并添加到Redis中。这样多个客户端会优先从Redis中加载所需的资源,减少了数据库的压力。
ps:选课中的课程比较多,数据库量较大。
在Redis的存储遇到了个问题,因为Redis的存储方式是(Key,Value)形式的,在设计中Key采用自定义+课程ID的方式,而Value是String类型的,但是从数据库中查询出来的数据是List形式的。Redis本身是不支持这种数据库类型的存储的。
2.Redis五种存储类型
Redis常用五种数据类型:string,hash,list,set,zset(sorted set).
1.String类型
String是最简单的类型,一个key对应一个value
String类型的数据最大1G。
String类型的值可以被视作integer,从而可以让“INCR”命令族操作(incrby、decr、decrby),这种情况下,该integer的值限制在64位有符号数。
在list、set和zset中包含的独立的元素类型都是redis String类型。2.List类型
链表类型,主要功能是push、pop、获取一个范围的所有值等。其中的key可以理解为链表的名字。
在Redis中,list就是Redis
String的列表,按照插入顺序排序。比如使用LPUSH命令在list头插入一个元素,使用RPUSH命令在list的尾插入一个元素。当这两个命令之一作用于一个空的key时,一个新的list就创建出来了。List的最大长度是2^32-1个元素。
3.Set类型
集合,和数学中的集合概念相似。操作中的key理解为集合的名字。
在Redis中,set就是Redis String的无序集合,不允许有重复元素。
Set的最大元素数是2^32-1。
Redis中对set的操作还有交集、并集、差集等。
4.ZSet(Sorted Set)类型
Zset是set的一个升级版本,在set的基础上增加了一个顺序属性,这一属性在添加修改元素时可以指定,每次指定后zset会自动安装指定值重新调整顺序。可以理解为一张表,一列存value,一列存顺序。操作中的key理解为zset的名字。
Zset的最大元素数是2^32-1。
对于已经有序的zset,仍然可以使用SORT命令,通过指定ASC|DESC参数对其进行排序。
5.hash类型
hash是最接近关系数据库结构的数据类型,可以将数据库一条记录或程序中一个对象转换成hashmap存放在redis中。
3.序列化类
- 如果要满足需求进行List的存储,则需要进行序列化,既将List序列化成字符进行存储。这里就需要借助序列化的工具类了。序列化工具类SerializeUtil如下:
package com.dmsdbj.itoo.teachingManagement.service.impl;import java.io.ByteArrayInputStream;import java.io.ByteArrayOutputStream;import java.io.Closeable;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.util.ArrayList;import java.util.List;import org.slf4j.Logger;import org.slf4j.LoggerFactory;/** * 序列化对象工具类,用于保存和读取redis数据使用 * Created by F-mdh on 2017/7/9. */public class SerializeUtil { private static Logger log = LoggerFactory.getLogger(SerializeUtil.class); /** * 序列化对象 * @param object * @return */ public static byte[] serialize(Object object) { ObjectOutputStream oos = null; ByteArrayOutputStream baos = null; byte[] bytes = null; try { // 序列化 baos = new ByteArrayOutputStream(); oos = new ObjectOutputStream(baos); oos.writeObject(object); bytes = baos.toByteArray(); } catch (Exception e) { e.printStackTrace(); } finally { try { if (oos != null) { oos.close(); } if (baos != null) { baos.close(); } } catch (Exception e2) { e2.printStackTrace(); } } return bytes; } /** * 反序列化对象 * @param bytes * @return */ public static Object unserialize(byte[] bytes) { Object obj = null; ByteArrayInputStream bais = null; try { // 反序列化 bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); obj = ois.readObject(); ois.close(); bais.close(); } catch (Exception e) { e.printStackTrace(); } return obj; } /** * 关闭的数据源或目标。调用 close()方法可释放对象保存的资源(如打开文件) * 关闭此流并释放与此流关联的所有系统资源。如果已经关闭该流,则调用此方法无效。 * @param closeable */ public static void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (Exception e) { log.info("Unable to close %s", closeable, e); } } } /** * 列表序列化(用于Redis整存整取) * @param value * @return */ public static <T> byte[] serialize(List<T> value) { if (value == null) { throw new NullPointerException("Can't serialize null"); } byte[] rv=null; ByteArrayOutputStream bos = null; ObjectOutputStream os = null; try { bos = new ByteArrayOutputStream(); os = new ObjectOutputStream(bos); for(T obj : value){ os.writeObject(obj); } os.writeObject(null); os.close(); bos.close(); rv = bos.toByteArray(); } catch (IOException e) { throw new IllegalArgumentException("Non-serializable object", e); } finally { close(os); close(bos); } return rv; } /** * 反序列化列表(用于Redis整存整取) * @param in * @return */ public static <T> List<T> unserializeForList(byte[] in) { List<T> list = new ArrayList<T>(); ByteArrayInputStream bis = null; ObjectInputStream is = null; try { if(in != null) { bis=new ByteArrayInputStream(in); is=new ObjectInputStream(bis); while (true) { T obj = (T) is.readObject(); if(obj == null){ break; }else{ list.add(obj); } } is.close(); bis.close(); } } catch (IOException e) { log.warn("Caught IOException decoding %d bytes of data", in == null ? 0 : in.length, e); } catch (ClassNotFoundException e) { log.warn("Caught CNFE decoding %d bytes of data", in == null ? 0 : in.length, e); } finally { close(is); close(bis); } return list; }}
4.代码
/** *从redis中 查询所有的公选数据: * @param : * @return */ @Override public List<ChooseCourseModel> queryAllCoursePage() { //获取公共选修课性质 String coursetype="3B6FE3BAB12E3BA8AFE36D"; //1.接受数据volist List<ChooseCourseModel> chooseCourseModelList = new ArrayList<>(); //2.实例化redis //创建一个spring容器 ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:redis.xml"); //从容器中获得JedisClient对象 JedisClientCluster jedisClientCluster=(JedisClientCluster)applicationContext.getBean("jedisClientCluster"); //3.获取查询条件 //4.从redis查询数据 String key = "tm:ChooseCourseServiceImpl:publicchoosecourse"; byte[] in= jedisClientCluster.get(key.getBytes());//拿到数据 chooseCourseModelList = SerializeUtil.unserializeForList(in);//反序列化,赋值volist //4.1 if yes 判断拿出的数据 if (chooseCourseModelList.isEmpty() || "".equals(chooseCourseModelList)) { //4.2 if no 查数据库 chooseCourseModelList = chooseCourseDao.queryAllCoursePage(coursetype); //4.2.1 判断是否为空 //4.2.2 放入redis中 jedisClientCluster.set(key.getBytes(), SerializeUtil.serialize(chooseCourseModelList)); } return chooseCourseModelList; }
调用工具类:
序列化:
jedisClientCluster.set(key.getBytes(), SerializeUtil.serialize(chooseCourseModelList));
反序列化:
chooseCourseModelList = SerializeUtil.unserializeForList(in);//反序列化,赋值volist
- ITOO---“秒杀”选课之Redis序列化
- ITOO---选课里的“秒杀”业务设计
- ITOO---选课里的“秒杀”业务实现(一)
- ITOO---选课之RabbitMQ搭建
- ITOO项目选课系统的问题小结
- ITOO---选课里的Spring-RabbitMq
- Redis之序列化POJO
- redis秒杀
- Redis 秒杀
- php redis秒杀
- redis秒杀
- redis秒杀案例
- REDIS实践之使用watch完成秒杀抢购功能
- Redis序列之Sentinel
- ITOO之底层关系
- ITOO之用户体验
- ITOO项目之Memcached
- 【ITOO】MVC之Razor
- HDU6078Wavel Sequence(计数dp)
- Qt5构建出错问题解决办法
- D
- HDU-2256
- HOJ13832 Fence
- ITOO---“秒杀”选课之Redis序列化
- XYNUOJ 第四次比赛 The Intervals
- 聊天室入门实战(node,socket.io实现)--第一章(实现登录群聊功能)
- Linux操作系统的主要组成部分
- 生成迷宫并找出走出迷宫的路径
- Mongodb删除collection
- 10个JavaScript难点,为您解决
- 正则表达式
- 嵌套矩形问题