読者です 読者をやめる 読者になる 読者になる

cloverrose's blog

Python, Machine learning, Emacs, CI/CD, Webアプリなど

use memcache on Django/Heroku

Heroku memcache Django python

TwitterのIDからScreen Nameを参照している箇所でAPI規制頻度緩和とレスポンス向上のために、IDをKey、Screen NameをValueとしてMemcacheに保存することにしました。

memcachedのインストール

$ sudo port -d selfupdate
$ sudo port -d sync
$ sudo port install memcached

Herokuにインストールする方法はクレジットカードを登録して、Terminalで

$ heroku addons:add memcache:5mb

を実行するか、Heroku Add-onsでWEBから追加する。

pylibmcのインストール

memcacheにPythonからアクセスできるようにするためにpylibmcをインストールする。

$ pip install pylibmc

エラーが出るので、Installing — pylibmc v1.2.2 documentationを参考に

$ LIBMEMCACHED=/opt/local easy_install pylibmc
$ python
>>> import pylibmc

これでうまくインストールできた。

Herokuにインストールする方法はrequirements.txtに

pylibmc==1.2.3

を追加すればいい。

Localで使ってみる

memcachedを実行

$ memcached -vv

pylibmc - Python client for memcached — pylibmc v1.2.2 documentationを見ながら

>>> import pylibmc
>>> mc = pylibmc.Client(["127.0.0.1"], binary=True,
...                     behaviors={"tcp_nodelay": True,
...                                "ketama": True})
>>> mc["some_key"] = "Some value"
>>> mc["some_key"]
'Some value'
>>> del mc["some_key"]
>>> "some_key" in mc
False

など実行する。

なお、デーモン(memcached)を実行していないとCONNECTION FAILUREとなる。

django-pylibmc-saslのインストール

pylibmcはReference — pylibmc v1.2.2 documentationのパラメータを見るとわかるように、username, passwordを指定してコネクションを張ることができない。
一方Herokuではusername, passwordを指定する必要がある。
そこでSASLをサポートしたdjango-pylibmc-saslをインストールする。

$ pip install django-pylibmc-sasl

Herokuにインストールする方法はrequirements.txtに

django-pylibmc-sasl==0.2.4

を追加すればいい。

settings.pyの更新

settings.pyに以下を追加

CACHES = {
    'default': {
        'BACKEND': 'django_pylibmc.memcached.PyLibMCCache'
    }
}

Herokuのチュートリアルにも書いてあるけどdjango_pylibmcがos.environから必要な値を取得してうまいことやってくれるので設定はこれだけでいい。

views.pyの更新

from django.core.cache import cache  # settings.pyで設定したCACHES['default']を取得

def id_to_screen_name(id, api):
    screen_name = cache.get(str(id))  # キャッシュを参照
    if screen_name is not None:  # キャッシュに保存されていた
        return screen_name
    try:
        user = api.get_user(id)  # 重い処理/API制限を食らう処理
    except:
        return None
    cache.set(str(id), user.screen_name)  # キャッシュに保存
    return user.screen_name

という感じで書いた。

RemoteとLocalで接続先を切り替える設定

LocalとRemoteでMemcacheの接続先を変更しなければいけないのでGitのリポジトリに追加しないlocal_settings.pyを使って
LocalとRemoteで切り替える。

settings.pyの最後に以下を追加

try:
    from local_settings import *
except ImportError:
    pass

local_settings.pyの最後に以下を追加(もしくは新規作成)

import os
os.environ.setdefault('MEMCACHE_SERVERS', '127.0.0.1')