먼저 적용 시나리오 살펴보기: 몇 년 전 WeChat에는 많은 투표 시스템이 있었습니다. 많은 사람들이 자신의 친구나 친구 집단에서 투표를 위해 투표할 사람을 찾습니다. 당시 비교적 규모가 큰 놀이공원에서도 이 투표 행사를 진행했는데, 일정 표를 넘으면 무료로 플레이할 수 있었던 것 같습니다. 저도 친구들한테 투표해달라는 부탁을 받았는데 하루에 3~5표씩 투표할 수 있었던 것 같더라고요. 자세한 내용은 기억이 안 나네요. 시스템에 들어간 후 친구의 투표 버튼을 눌렀는데 아무 일도 일어나지 않았습니다. 네트워크 문제인 줄 알았는데, 나중에 알고 보니 프로그램 문제였습니다. 투표하는 사람이 너무 많아 한동안 시스템이 이를 감당하지 못할 것이라고 당시 추측했습니다.
그때 우연히 redis를 배우고 있었거든요. 그래서 이 기능은 redis의 카운터를 통해 개선될 수 있다고 생각합니다.
여기에서는 사용자의 구체적인 투표 상황을 고려하지 않고 사용자의 총 투표 수만 계산합니다. 예를 들어 A가 B에게 투표한 기록은 고려하지 않습니다. 이러한 상황을 고려한다면 다른 솔루션을 사용해야 합니다(메시지 대기열을 사용할 수 있음).
검증
먼저 각 사용자의 투표수를 검증해야 합니다. 사용자는 매일 세 번의 투표 기회를 가지므로 키를 생성하고 유효 기간을 내일 아침으로 설정할 수 있습니다. 사용자가 투표할 때마다 1표가 추가됩니다. 사용자가 3표에 도달하면 오늘 투표 수를 모두 소진했다는 메시지가 표시됩니다.
// 投票次数校验 function checkVote($uid) { $key = "uid:$uid:cnt"; $tomrTime = mktime(0,0,0, date('m'), date('d')+1, date('Y')); if (!$redis->exsits($key)) { $redis->set($key, 0, ['ex' => $tomrTime - time()]); return true; } else if ( ($cnt = $redis->get($key)) < 3 ) { return true; } else { return false; } }
투표수를 세어보세요
투표수가 확인된 후, 사용자들이 얻은 표수를 세어야 합니다.
// 得票数计数 // uid表示投票人id // touid表示得票人id function vote ($uid, $toUid) { $key = "uid:$toUid:vote"; // 投票数校验 if (checkVote($uid)) { // 统计投票数及参选人得票数 $redis->incr($key); $redis->incr("uid:$uid:cnt"); return true; } else { return false; } }
내 Alibaba Cloud 호스트 구성에는 1개의 코어 CPU와 1G 메모리 구성만 있습니다. 증가 성능은 초당 100,000회 이상에 도달할 수 있습니다. Redis 성능은 정말 끔찍합니다.
# redis-benchmark -t incr -q INCR: 105708.25 requests per second
Mysql은 사용자의 투표를 비동기적으로 업데이트합니다
마지막으로 mysql이 특정 시간마다 사용자의 투표를 동기화할 수 있도록 예약된 작업만 수행하면 됩니다.
방법은 무한 루프를 만들어 모든 사용자가 탐색될 때까지 매번 50명의 사용자의 표를 얻은 다음 루프를 종료하고 스크립트를 종료하는 것입니다.
$start = 0; while (true) { // 每次循环取50个用户id $users = $DB->query("SELECT uid,votes FROM users LIMIT $start, 50"); if (!$users) { exit(); } $keys = []; foreach ($users as $userinfo) { $keys[] = "uid:{$userinfo['uid']}:vote"; } $votes = $redis->mget($keys); foreach ($votes as $index => $vote) { if ($vote != $users[$index]['votes']) { $DB->query("UPDATE users SET votes = '$vote' WHERE uid='{$users[$index]['uid']}"); } } $start += 50; }
Redis의 mget 명령은 한 번에 여러 키의 값을 가져오는 것입니다. Redis에 저장된 Redis 투표 수를 얻은 후 먼저 Mysql의 투표 수와 비교해야 합니다. Mysql 데이터가 다른 경우에만 업데이트하십시오.
위 내용은 Redis를 카운터로 사용하여 투표 시스템 개선의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!