• 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转化为list
    enrollStudentList = 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)
    {
    //课程id
    String CourseId= examineeArrangement.getCourseId();
    //学号
    String StudentCode = examineeArrangement.getStudentId();
    //试卷id
    String 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:单个实体存入Redis
    e.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 block
    e.printStackTrace();
    }
    }
    }


    总结:

        其实,我是在点击“交卷”的时候把数据存储到数据库的。
          我感觉我的Redis仅仅是用了一点点,并没有很好地利用。以后有机会自己再多学习一下,感谢我老公和红霞给我各种指导和建议。
         还有,就是不要仅仅依赖技术文档。这次我明显感觉到文档给我的满足不了业务需求,不要尝试用自己的简单逻辑处理,先去查查网上有没有好的方法。




  • 相关阅读:
    spring中@Lookup的作用
    spring中的观察者模式
    spring事务源码解析
    spring中@Configuration注解的作用
    HTML5和CSS3
    TCP/IP协议
    Android项目的settings.gradle和build.gradle
    AndroidManifest.xml 最全详解
    Android实现网络监听
    Android数据存取
  • 原文地址:https://www.cnblogs.com/tanqianqian/p/5975010.html
Copyright © 2020-2023  润新知