Автор оригинала: David Wong.
Что необходимо оптимизировать, пожалуйста, укажите в своих комментариях
I. спрос
Record user sign in, query user sign in
2, Техническое предложение
1. Используйте MySQL (поле времени max’u-это последовательные дни регистрации)
Ход мыслей: (1) Когда пользователь регистрируется, вставьте запись и запросите, следует ли регистрироваться вчера в соответствии со временем создания. Если есть регистрация заезда, максимальное время на первоначальной основе + 1. В противном случае будет обнаружена максимальная (2) регистрация. Запросите, существует ли запись в соответствии со временем “Идентификатор пользователя и создание”. Если он не существует, это означает, что он не зарегистрирован
2. Используйте функцию растрового изображения redis
Train of thought: (1) Each user has a separate redis record every month, such as 00101010101010. From left to right, it represents 01-31 days (there are several days in each month, just a few days) (2) In the early morning of the 8th day of each month, the redis records are uniformly moved to MySQL, as shown in the figure below
(3) Query the current month from redis, and get from MySQL last month
3. Сравнение схем
Example: 10000 users sign in 365 days Scheme 1: insert 3.65 million records into MySQL ·Frequent requests for database logging waste server overhead. ·As time goes on, the data increases dramatically ·The efficiency of massive data retrieval is not high. At the same time, only create time can be used as the interval query condition, and the large amount of data must be slow Scheme 2: insert 12W records into MySQL ·Save space. Each user only occupies 1 bit of space and 1 W users generate 10000 bit = 1050 bytes of data every day, which is about 1 KB ·Fast memory operation
3. Реализация (сценарий 2)
1. Ключевая структура
Prefix: year, month: user ID -- sign: 2019: 10:01 Enquiries: Single: keys sign? 2019? 10? 01 All: keys sign_* Months: keys sign*
2. Структура таблицы MySQL
3. Код (список 1 вызывающий метод и 3 класса)
(1) Способ регистрации
public static function userSignIn($userId)
{
$time = Time();
$today = date('d', $time);
$year = date('Y', $time);
$month = date('m', $time);
$signModel = new Sign($userId,$year,$month);
//1. Check in information of users today
$todaySign = $signModel->getSignLog($today);
if ($todaySign) {
Return self:: jsonarr (- 1, 'you have checked in', []);
}
try {
Db::startTrans();
$signModel->setSignLog($today);
//4. Bonus points
if (self::SING_IN_SCORE > 0) {
$dataScore['order_id'] = $userId.'_'.$today;
$datascore ['type '] = 2; // 2. Check in
$datascore ['remark '] =' check in to get points';
Finance::updateUserScore(Finance::OPT_ADD, $userId, self::SING_IN_SCORE, $dataScore);
}
$code = '0';
$MSG = 'sign in succeeded';
$score = self::SING_IN_SCORE;
Db::commit();
} catch (\Exception $e) {
Db::rollback();
$code = '-2';
$MSG = 'sign in failed';
$score = 0;
}
return self::jsonArr($code, $msg, ['score' => $score]);
}(2) Базовый класс Redis
(3) Войдите в класс операций redis
keySign = $this->keySign . '_' . $year . '_' . $month . ':' . $userId;
}
/**
*User sign in
* @param $day
* @return int|null
* @throws \Exception
* @author wenzhen-chen
*/
public function setSignLog($day)
{
return $this->setBit($this->keySign, $day, 1);
}
/**
*Check in record
* @param $day
* @return int|null
* @throws \Exception
* @author wenzhen-chen
*/
public function getSignLog($userId,$day)
{
return $this->getBit($this->keySign, $day);
}
/**
*Delete sign in record
* @return int|null
* @throws \Exception
* @author wenzhen-chen
*/
public function delSignLig()
{
return $this->del($this->keySign);
}
}(4) Регулярно обновляйте класс MySQL
keys('sign_' . $year . '_' . $month . ':*');
foreach ($keys as $key) {
$bitlog = ''; // user's attendance record in the current month
$userData = explode(':', $key);
$userId = $userData[1];
//3. Cycle to query whether the user has signed in (it is not stored by the number of days per month, but directly stored for 31 days)
for ($i = 1; $i <= 31; $i++) {
$isSign = $signModel->getBit($key, $i);
$bitLog .= $isSign;
}
$data[] = [
'user_id' => $userId,
'year' => $year,
'month' => $month,
'bit_log' => $bitLog,
'create_time' => $time,
'update_time' => $time
];
}
//4. Insert log
if ($data) {
$logModel = new SignLog();
$logModel->insertAll($data, '', 100);
}
}
}Оригинал: “https://developpaper.com/use-redis-bitmap-bitmap-to-implement-check-in-function-php-version/”