ITOO考评学生端性能优化——Redis
【项目背景】
1.学生抽题慢
2.做学生端的时候发现学生每次做一道题的时候触发一次数据库,把数据更新到数据库里面,这样子学生端前台响应很慢,每次点击的时候都有1-2秒的延迟。然后当学生多的时候,不断的对一张表进行更改,大家都懂得。
【解决方案】
(加Redis)
1. 把共用的东西放到Redis里面
2. 师姐的意思大体是这样子的,我每次更新的时候并不是更新的数据库,而是Redis,一段时间后内容把整个都提交到数据库里面。(反正原话我已经忘记了……)
【代码展示】
1. 关于问题1
其实解决抽题中的公共部分,而且给的文档很详细很简单:
/*** 代码逻辑:* 首先查看Redis是否有题型* 如果有的话,直接读取Redis的内容,如果没有的话,就去数据库里面查**/public void queryComponentById(HttpServletRequest request,HttpServletResponse response) {System.out.println("进入查询组件方法");String perSortTypeId = request.getParameter("questionTypeId");if (perSortTypeId == null || perSortTypeId.equals("")) {return;}// jediscluster.del(perSortTypeId);// 定义题型集合List<QuestionTypeDetail> questionTypesDetailList = new ArrayList<QuestionTypeDetail>();String getQuestionTypeDetail=jediscluster.get(perSortTypeId);if (getQuestionTypeDetail==null || getQuestionTypeDetail.equals("")) {questionTypesDetailList = examPageBean.queryComponentById(perSortTypeId, dataBaseName);if (questionTypesDetailList==null || questionTypesDetailList.equals("")) {System.out.println("没有相应的题型组件");}else{try {jediscluster.set(perSortTypeId,JsonUtils.objectToJson(questionTypesDetailList));} catch (IOException e) {e.printStackTrace();}}}else{JsonUtils.jsonToList(getQuestionTypeDetail, QuestionTypeDetail.class);}JacksonJsonUntil.beanToJson(response, questionTypesDetailList);
主要用到的Redis的代码例子:
//添加list@RequestMapping("test4")public void test4(HttpServletRequest request,HttpServletResponse response) throws Exception {jediscluster.set("listkey" ,JsonUtils.objectToJson(list));}
//查询list@RequestMapping("test6")public void test6(HttpServletRequest request,HttpServletResponse response) throws Exception {List<EnrollStudent> enrollStudentList = new ArrayList<EnrollStudent>();//获取缓存String json = jediscluster.get("listkey");//将json转化为listenrollStudentList = JsonUtils.jsonToList(json,EnrollStudent.class);}
2. 关于问题2
昨天才接触Redis,我还比较单纯,已经对于Redis的操作,只有文档上面的Get,set这两个方法。所以当郭郭跟我说,重名的时候,数据就会被覆盖了,我一测试,可不是嘛,于是我果断的用perSortTypeId作为key值。
但是,今天在查询的时候,才知道是因为我直接set,如果用list存储结构,用lpush()方法就能轻松解决问题了。但是也是因为关于底层Redis封装的方法太少了,用起来一直在各种转换。
/*** 根据课程id,学生id,试卷id,数据库;查询考生答题记录;* 十一期 谭倩倩* 修改人:谭倩倩* 修改原因:添加Radis* @param request* @param response*/@RequestMapping("/queryStudentRecord")public void queryStudentRecord(HttpServletRequest request,HttpServletResponse response){//课程idString CourseId= examineeArrangement.getCourseId();//学号String StudentCode = examineeArrangement.getStudentId();//试卷idString PaperId = examineeArrangement.getPaperMainId();//数据库String DateBaseName = "itoo_exam";//查询考生答题记录//把查询出来的学生答题记录保存用Radis下来_十一期 谭倩倩List<PaperRecord> ListPaperRecord=new ArrayList<PaperRecord>();String stuPaperRecord=examineeArrangement.getStudentId()+"ListPaperRecord";// String getListPaperRecord=jediscluster.get(stuPaperRecord);List<String> getListPaperRecord= jediscluster.lrange(stuPaperRecord, 0, jediscluster.llen(stuPaperRecord)-1);//lrange()方法是来查询出所有以stuPaperRecord为key健的值,上面说过因为是list结构存储。if (getListPaperRecord==null || getListPaperRecord.equals("")||getListPaperRecord.size()==0) {ListPaperRecord = paperRecordBean.queryAllStuPaperRecord(CourseId, StudentCode, PaperId, DateBaseName);for (int i = 0; i < ListPaperRecord.size(); i++) {PaperRecord enPR=ListPaperRecord.get(i);try {jediscluster.lpush(stuPaperRecord, JsonUtils.objectToJson(enPR));} catch (IOException e) {// TODO:单个实体存入Redise.printStackTrace();}}}else{// List<PaperRecord> changeRecord= (List<PaperRecord>)getListPaperRecord;ListPaperRecord.clear();for (int i = 0; i < getListPaperRecord.size(); i++) {PaperRecord enPaRecord=JsonUtils.jsonToPojo(getListPaperRecord.get(i), PaperRecord.class);ListPaperRecord.add(enPaRecord);}}JacksonJsonUntil.beanToJson(response, ListPaperRecord);}
重点逻辑:
获取Redis存储数据的个数作为循环的条件把list的每个实体查询出来,匹配对应的答案,更新list里面的数据//缓存更新List<PaperRecord> stuListPaperRecord=new ArrayList<PaperRecord>();String stuPaperRecord=examineeArrangement.getStudentId()+"ListPaperRecord";long count=jediscluster.llen(stuPaperRecord);//获取Redis存储数据的个数// stuListPaperRecord=JsonUtils.jsonToList(StrListPaperRecord,PaperRecord.class);if (count==0) {examPageBean.updatePaperRecord(studentAnswer, questionId, score,teacherCode, examineeArrangement);}else{//更新缓存,for (long i = 0; i < count; i++) {//TODO:自己测试用String strPR=jediscluster.lindex(stuPaperRecord, i);// int i=(int)count;// PaperRecord enPaperRecord=stuListPaperRecord.get(i);// if (getEn.length()>0) {// PaperRecord paperRecord=new PaperRecord();PaperRecord paperRecord=JsonUtils.jsonToPojo(strPR, PaperRecord.class);if (paperRecord.getQuestionContentId().equals(questionId)) {paperRecord.setStudentAnswer(studentAnswer);String jsonPaRecord;try {jsonPaRecord = JsonUtils.objectToJson(paperRecord);jediscluster.lset(stuPaperRecord, i, jsonPaRecord);//更新Redis里面的数据System.out.println("答题记录写入缓存成功");} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
总结:
其实,我是在点击“交卷”的时候把数据存储到数据库的。
我感觉我的Redis仅仅是用了一点点,并没有很好地利用。以后有机会自己再多学习一下,感谢我老公和红霞给我各种指导和建议。
还有,就是不要仅仅依赖技术文档。这次我明显感觉到文档给我的满足不了业务需求,不要尝试用自己的简单逻辑处理,先去查查网上有没有好的方法。

浙公网安备 33010602011771号