ページが表示されるたびに増分される整数の MySQL 列があります。SQL クエリは次のようになります。
UPDATE page SET views = views + 1 WHERE id = $id
同じページ (同じ ID) が 1 秒間に何度も表示され (MySQL でレコードがロックされる)、クエリが MySQL を停止させると、スケーリングの問題が発生し始めました。これに対抗するために、次の戦略を使用しています。
ページが読み込まれるたびに、Memcache のカウンターをインクリメントし、バックグラウンドで MySQL のカウンターを更新するジョブ (Gearman) を (3 台のワーカー マシン間で) キューに入れます。簡略化されたコードは次のようになります。
ページ ビュー:
$memcache->increment("page_view:$id");
$gearman->doBackground('page_view', json_encode(array('id' => $id)));
バックグラウンド ワーカーで:
$payload = json_decode($payload);
$views = $memcache->get("page_view:{$payload->id}");
if (!empty($views)) {
$mysql->query("UPDATE page SET views = views + $views WHERE id = {$payload->id}");
$memcache->delete("page_view:{$payload->id}");
}
これはうまくいきました。これにより、DB へのクエリを削減でき (DB に書き込む前に memcache にビューを集約するため)、DB の書き込みはバックグラウンドで行われ、ページの読み込みが滞ることはありません。
残念ながら、MySQL のロックが再び発生し始めています。非常にアクティブなページがほぼ同時に実行され、MySQL が再びロックされるようです。ロックは書き込みを遅くし、多くの場合、ワーカーを殺します。これにより、キューが非常に大きくなり、多くの場合、「遅れている」ジョブが 70k 以上あります。
私の質問: これを拡大するには、次に何をすべきですか?