When website performance hits a bottleneck

1. Problem description
1. Origin. In the project of an online examination system, I hope that each question answered by the user has a corresponding record: one is to record the number of correct and incorrect questions of each question; the other is to record each wrong question of the user to form a user set of errors.
When website performance hits a bottleneck
2. Realize. Since there are an indeterminate number of questions in the test paper, I use a loop to judge whether the user's answer is correct, and record the data in the loop and write it to the database.
When website performance hits a bottleneck
3. Bottleneck. Since every time an answer sheet is submitted, dozens or more database write or update operations will be generated, so it will consume a lot of time.
2. Problem Analysis

1. Since each question has to be recorded twice: one is to update the number of correct and incorrect questions, and the other is to record the wrong question set. If each test paper has 20 test questions, then each answer sheet will be recorded 40 times in the database. operation, resulting in a lot of pressure on the database.
2. Since each test question is a different database record, it is difficult to update in batches (some are new records, some are updated records).
3. If a large number of users submit concurrently, the server may crash and be slow. Although my small website is usually not visited by so many people, the system I developed cannot end up becoming an unusable waste product, so it must be optimized!
3. Solutions and solutions

1. Because there are a lot of database operations, my first consideration is to use redis to improve performance.
2. Since the operation of updating data includes both new records and updated records, the update operation and the operation must be logically separated.
3. I use the thinkphp framework to develop, and the model layer comes with a batch-added function addAll(), so the operation of adding new data is solved with it; then I search online or write a function myself to assemble and update sql in batches Statement, which is in the following statement structure:
UPDATEcategories SET
display_order = CASE id
WHEN 1 THEN 3
WHEN 2 THEN 4
WHEN 3 THEN 5
END,
title = CASE id
WHEN 1 THEN 'New Title 1'
WHEN 2 THEN 'New Title 2'
WHEN 3 THEN 'New Title 3'
END
WHERE id IN(1,2,3)

4. Record the data to be updated or added through the hash table of redis, trigger the database operation at the appropriate time, operate the redis data through php, and delete the redis data after the execution is successful, thereby solving the bottleneck problem.

Attachment: The following is the optimization of the correct and wrong records of the test questions. The optimized code for the wrong question set is similar, so only the code of the former is shown.
5.redis recording process:
$check ? $field = 'r' : $field = 'w';//Check right or wrong
$redis = new \Redis();
$redis->connect('127.0.0.1',6379 );
$redis->hIncrBy('qid_check_log','qid.'.$qid.'.'.$field,1); //The key value is incremented by 1

6. Dump the redis data to mysql:
$redis = new \Redis();
$redis->connect('127.0.0.1',6379);
$data_cache = $redis -> hGetAll('qid_check_log');
$ temp = array(); //Data to be updated
$i = 0;

//要增加的数据
foreach($data_cache as $key=>$num){
    $arr = explode('.',$key);
    $qid = $arr[1];
    $field = $arr[2];
    $temp[$i]['qid'] = $qid;
    $ids[] = $qid;//需要更新的试题id
    $temp[$i][$field] = $num;
    $redis -> hDel($qid_check_log,$key);
    $i++;
}

if(empty($ids)) return true;//如果没有更新,则直接返回

//获取原来的数据
$map['qid'] = array('in',$ids);
$old_data = M('questionlog') -> where($map) -> select();
$old_data2 = array();
foreach($old_data as $one){
    $old_data2[$one['qid']] = $one;
}
unset($old_data);

//合并数据
foreach($temp as &$one){
    if(isset($one['r'])){
        $one['r'] = $old_data2[$one['qid']]['r'] + $one['r'];
    }else{
        $one['r'] = $old_data2[$one['qid']]['r'];
    }

    if(isset($one['w'])){
        $one['w'] = $old_data2[$one['qid']]['w'] + $one['w'];
    }else{
        $one['w'] = $old_data2[$one['qid']]['w'];
    }
}

$re = batch_update('questionlog',$temp,'qid');//执行批量更新

后记:其实当初我在编写程序的时候没有设计好,如果设计得合理的化,也许不需要redis也能完成这个优化,不过,也正好因为这个机会,让我在项目中真正用到了redis,感受到了它的速度优势,哈哈!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325947052&siteId=291194637