pekeqの日記

過去に書いたブログエントリから反響のあったものを抜粋しています

アクセスカウンタ

古い話題というか、もう議論は出尽くしているかもしれんが、
まあいまさら感は否めない。

何も考えてない

  • 毎回readして+1してwrite

排他する

  • 毎回flockしてreadして+1してwrite
    • symlinkとかバリエーション多数。なぜかうまくいかない場合があったりして悩む。大抵処理の順序が間違ってるとかNFSしてたとか
  • セマフォを使って排他
    • よく初心者向け掲示板とかで用語だけ書いている人がいるけど、実際に作った人はいるのだろうか
  • DB使う
    • updateで+1。DB接続コスト等が結構バカにならないのと結構遅いのとカウンタごときでDB使うのかという敗北感
    • GDBMなら壊れないという記述はどこまで本当なのだろうか

排他しなくていい方法を考える

  • 毎回ファイルに1バイトずつappend。stat()でファイルサイズを読む
    • 実は100万アクセスしても1MBだ。大抵の零細サイトならこれでおk?
    • truncate()でファイルサイズを変更することもできる。これならシステムコール1回で書き込み終わる
  • 毎回utime()でファイルの時刻を1秒ずつ進め、stat()で最終更新時刻を取る
    • システムコール1回で処理が完結するからatomicになるというやり方。カウント抜けは発生するが壊れない。
    • 最初にepochのファイルを準備するのがちと面倒。ファイルコピーすると情報が飛ぶとか扱いが大変
  • ファイル名にカウンタを含め、毎回rename()でファイル名変更。readdir()でファイル名を読んでカウンタ取得
  • オープンしたファイルをmmap()で開く

競合を回避する

  • メッセージキューを使ってカウントアップ処理を一箇所に集中
    • named pipe/POSIX queueなど。カウントアップ専任のプロセスが必要なのでちと面倒

追記

コメント欄の内容を足してみた。ありがとう!