アダルトアフィリエイト運営備忘録

アダルトアフィリエイトサイトの運営のノウハウをまとめています。

Rails+Redisで作るアダルト動画アクセスランキング

1. アダルトサイトにおける検索機能

f:id:thomas0103:20161227132615p:plain

Railsでアダルトサイトの運営をはじめ6ヶ月が経過しました。
月間PVは250万とまだまだのサイトですが、順調に成長を続けています。

アダルトサイトにおいて、"検索機能"は重要です。

検索にはいくつか種類がありますが、大まかに三種類に分けることが出来ます。

  • キーワードを入力して探す
  • タグ/カテゴリから探す
  • ランキング/新着順等の一覧から探す

Railsでは、キーワード検索ではElasticSearch等の全文検索、タグ/カテゴリなどは既存のリレーショナル・データベースを用いた実装などが使われます。

一覧から探す3番目のケースでは、新着順の場合の実装は投稿日が直近のものから出力すれば良いので実装は容易です。

問題なのは人気(PV、いいね)順のソートです。

PVのたびにリレーショナル・データベースに書き込む方法では、すぐに破綻します。

Redisは、キーと値だけを格納することに特化したデータベース(KVS; Key Valuse Store)で機能が制限される代わりに、リレーショナル・データベースよりも高速に動作します。また、ソート済みセット型という型が用意されており、PV順に並べ替えて取得するといった処理を高速に行うことが出来ます。

このエントリーでは、RailsとRedis間でデータをやり取りし、人気なアダルト動画をPV順に取り出す方法を紹介します。

2. Rails+Redisでアクセスランキングを作る

2.1: Redisなどのインストール

今回の開発環境は以下です。

  • OSX10.11
  • ruby2.0/rails4.2.6
  • heroku(本番環境)

僕の環境ではパッケージ管理にMacPortsを使っているので、以下のコマンドでRedisをインストールします。
Redisのインストールについてコケる場合は以下のページが詳しいです。
Mac OSXにredisをインストール - blog.katsuma.tv

$ sudo port install redis
(Redisサーバの起動は以下のコマンド)
$ sudo /opt/local/bin/redis-server /opt/local/etc/redis.conf

HomeBrewを使っている人はportコマンドの代わりに以下のようにしてもok。

$ brew install redis
(Redisサーバの起動は以下のコマンド)
$ redis-server /usr/local/etc/redis.conf

Rails側からRedisを扱うには以下のgemをインストールする必要があります。
Gemfileに以下を記述し、bundle installすれば完了。

gem 'redis'
$ bundle install

2.2: ローカルのRedisとRailsを連携させる

config/environments/development.rbに以下を記述します。
環境変数ENV["REDIS"] にRedisのURLを格納しています。

Rails.application.configure do
  ....
  # Redis環境変数
  ENV["REDIS"] = "http://localhost:6379"
end

config/initializersにredis.rbというファイルを作成し、以下のように記述します。
環境変数ENV["REDIS"]を用いてRedisオブジェクトを作成しておきます。

require 'redis'
uri = URI.parse(ENV["REDIS"])
REDIS = Redis.new(host: uri.host, port: uri.port)
end

2.3: RailsからRedisへの書き込み

Redisに書き込むには、zincrbyメソッドを使います。

REDIS.zincrby "ranking/daily_pv/#{Date.today.to_s}", 1, "#{movie.id}"

3つの引数はそれぞれ、キー、スコア、値になっています。アダルト動画のアクセスランキングの場合、どのアクセスも重みを1にしておきます。
今回は、第1引数にranking/daily_pvという識別子+日付、第3引数に動画IDを渡しています。

2.4: Railsから動画ランキングデータの読み込み

7日間のランキングを取得するにはzrevrangeを用い、以下のようにします。

REDIS.zrevrange "ranking/daily_pv/#{Date.today.to_s}", 0, 4

この例では、本日のアクセスランキング上位5件が配列で返ります。
以下のようにwithscoresオプションを付けると、アクセス数も取得できます。

REDIS.zrevrange "ranking/daily_pv/#{Date.today.to_s}", 0, 4, withscores: true

2.5: Herokuへのデプロイ

ローカルで動画ランキングの動作を確認したら、Herokuへのデプロイを行います。
HerokuでRedisを使う方法については、こちらのサイトが詳しいです。

HerokuのアドオンでRedisを簡単に使うことが出来ます。
現状では、Redis Cloudが30MBまで無料です。

以下のコマンドでアドオンをインストールします。

heroku addons:create rediscloud:30

インストールが完了すると、環境変数ENV['REDISCLOUD_URL']に作成されたRedisデータベースのURLが格納されます。
config/initializer/redis.rb内を以下のように書き換え、Heroku上のRedisデータベースを指し示すようにします。

if ENV["REDISCLOUD_URL"]
  REDIS = Redis.new(:url => ENV["REDISCLOUD_URL"])
end

あとは通常通りデプロイすればokです。

参考サイト

MacPortsでのRedisインストール
blog.katsuma.tv

RedisのインストールやRailsからの呼び出しなど。
qiita.com

Herokuでのデプロイ
https://dev.9bar.tokyo/rails/pvranking-with-redis-heroku-and-rails

Redis gemのメソッド
d.hatena.ne.jp

Redisの関数リファレンス
ソート済みセット型 — redis 2.0.3 documentation

RedisCloudの価格設定
elements.heroku.com