twemproxyでRedisのパーティショニングを実装する


はじめに

twemproxyを使用してRedisのパーティショニングを実装する方法を記述します。

環境

  • CentOS 6.5
  • Redis 2.8.16
  • twemproxy 0.3.0

Redisの構成

役割 名称 ポート
master redis 6379
master redis02 6380
master redis03 6381

Redisのインストールについては、RedisをSentinelで監視するをご参照ください
※ Redisのスレーブ設定を削除し、Sentinelを停止した状態にしています。

twemproxyによるパーティショニング

  • twemproxyのインストール
$ git clone https://github.com/twitter/twemproxy.git
$ cd twemproxy
$ autoreconf -fvi
$ ./configure --prefix=/usr/local/nutcracker 2>&1 | tee configure.log
$ make 2>&1 | tee make.log
$ sudo sh -c "make install 2>&1 | tee make-install.log"
$ sudo mkdir -p /usr/local/nutcracker/conf
  • twemproxyの設定ファイルを作成します。
/usr/local/nutcracker/conf/nutcracker.yml
alpha:
  listen: 127.0.0.1:22121
  hash: fnv1a_64
  distribution: ketama
  auto_eject_hosts: true
  redis: true
  server_retry_timeout: 2000
  server_failure_limit: 1
  servers:
   - 127.0.0.1:6379:1
   - 127.0.0.1:6380:1
   - 127.0.0.1:6381:1
  • 設定ファイルの検証をしておきます。
$ sudo /usr/local/nutcracker/sbin/nutcracker -t -c /usr/local/nutcracker/conf/nutcracker.yml
nutcracker: configuration file '/usr/local/nutcracker/conf/nutcracker.yml' syntax is ok
  • twemproxyを起動します。
$ sudo /usr/local/nutcracker/sbin/nutcracker     \
    -c /usr/local/nutcracker/conf/nutcracker.yml \
    -d                                           \
    -o /var/log/nutcracker.log                   \
    -p /var/run/nutcracker.pid
  • tewmproxyの状態を確認します。
$ telnet 127.0.0.1 22222 2> /dev/null | tail -n 1 | jq '.'
{
  "alpha": {
    "127.0.0.1:6381": {
      "out_queue_bytes": 0,
      "out_queue": 0,
      "in_queue_bytes": 0,
      "in_queue": 0,
      "response_bytes": 0,
      "server_eof": 0,
      "server_err": 0,
      "server_timedout": 0,
      "server_connections": 0,
      "server_ejected_at": 0,
      "requests": 0,
      "request_bytes": 0,
      "responses": 0
    },
    "client_eof": 0,
    "client_err": 0,
    "client_connections": 0,
    "server_ejects": 0,
    "forward_error": 0,
    "fragments": 0,
    "127.0.0.1:6379": {
      "out_queue_bytes": 0,
      "out_queue": 0,
      "in_queue_bytes": 0,
      "in_queue": 0,
      "response_bytes": 0,
      "server_eof": 0,
      "server_err": 0,
      "server_timedout": 0,
      "server_connections": 0,
      "server_ejected_at": 0,
      "requests": 0,
      "request_bytes": 0,
      "responses": 0
    },
    "127.0.0.1:6380": {
      "out_queue_bytes": 0,
      "out_queue": 0,
      "in_queue_bytes": 0,
      "in_queue": 0,
      "response_bytes": 0,
      "server_eof": 0,
      "server_err": 0,
      "server_timedout": 0,
      "server_connections": 0,
      "server_ejected_at": 0,
      "requests": 0,
      "request_bytes": 0,
      "responses": 0
    }
  },
  "curr_connections": 1,
  "total_connections": 1,
  "timestamp": 1410967210,
  "uptime": 2569,
  "version": "0.3.0",
  "source": "localhost.localdomain",
  "service": "nutcracker"
}

出力された項目の内容は以下で確認できます。

$ /usr/local/nutcracker/sbin/nutcracker --describe-stats
This is nutcracker-0.3.0

pool stats:
  client_eof          "# eof on client connections"
  client_err          "# errors on client connections"
  client_connections  "# active client connections"
  server_ejects       "# times backend server was ejected"
  forward_error       "# times we encountered a forwarding error"
  fragments           "# fragments created from a multi-vector request"

server stats:
  server_eof          "# eof on server connections"
  server_err          "# errors on server connections"
  server_timedout     "# timeouts on server connections"
  server_connections  "# active server connections"
  server_ejected_at   "timestamp when server was ejected in usec since epoch"
  requests            "# requests"
  request_bytes       "total request bytes"
  responses           "# responses"
  response_bytes      "total response bytes"
  in_queue            "# requests in incoming queue"
  in_queue_bytes      "current request bytes in incoming queue"
  out_queue           "# requests in outgoing queue"
  out_queue_bytes     "current request bytes in outgoing queue"

動作確認

  • twemproxy経由でRedisへデータをsetします。
$ /usr/local/redis/bin/redis-cli -p 22121 set key value
OK
$ /usr/local/redis/bin/redis-cli -p 22121 get key
"value"
  • Redisのデータを確認します。
$ /usr/local/redis/bin/redis-cli -p 6379 get key
(nil)
$ /usr/local/redis/bin/redis-cli -p 6379 dbsize
(integer) 0
  • Redis02のデータを確認します。
$ /usr/local/redis/bin/redis-cli -p 6380 get key
(nil)
$ /usr/local/redis/bin/redis-cli -p 6380 dbsize
(integer) 0
  • Redis03のデータを確認します。
$ /usr/local/redis/bin/redis-cli -p 6381 get key
"value"
$ /usr/local/redis/bin/redis-cli -p 6381 dbsize
(integer) 1
  • twemproxy経由でRedisにデータを投入します。
set_test_data.sh
#!/bin/sh

redis_cli=/usr/local/redis/bin/redis-cli
proxy_port=22121

datestr=$(date +"%s")

for i in {1..1000}
do
  # 数字のみの任意の文字列(長さ10)を生成します。
  val=$(cat /dev/urandom | tr -dc '[:digit:]' | head -c 10)
  # アルファベットのみの任意の文字列(長さ10)を生成します。
  val2=$(cat /dev/urandom | tr -dc '[:alpha:]' | head -c 10)
  key="key_${datestr}_$val"
  value="value_${datestr}_$val2"
  echo "$key" >> keys.$datestr.txt
  echo "$value" >> values.$datestr.txt
  $redis_cli -p $proxy_port set $key $value > /dev/null 2>&1
done

keys.$datestr.txt  => keys.1410995286.txt
values.$datestr.txt => values.1410995286.txt

  • twemproxy経由でデータを取得します。
$ xargs -a keys.1410995286.txt -l /usr/local/redis/bin/redis-cli -p 22121 get > get_result.txt
$ wc -l values.1410995286.txt
1000 values.1410995286.txt
$ wc -l get_result.txt
1000 get_result.txt
$ diff values.1410995286.txt get_result.txt
※ (出力なし)
  • Redisへ直接接続して、データの件数を確認します。
$ /usr/local/redis/bin/redis-cli -p 6379 dbsize
(integer) 335
$ /usr/local/redis/bin/redis-cli -p 6380 dbsize
(integer) 356
$ /usr/local/redis/bin/redis-cli -p 6381 dbsize
(integer) 309

おまけ

  • autconfのインストール

twemproxyのコンパイルには、autoconf2.64以上が必要となりました。
CentOS6の標準のリポジトリには存在しないようなので、今回はsource rpmよりリビルドする方法でインストールしました。

$ sudo yum install rpm-build
$ mkdir -p rmkdir $HOME/rpmbuild/{BUILD,SRPMS,SPECS,SOURCES,RPMS}
$ echo "_topdir $HOME/rpm" > $HOME/.rpmmacros
$ wget ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home%3A/monkeyiq%3A/centos6updates/CentOS_CentOS-6/src/autoconf-2.69-12.2.src.rpm
$ rpmbuild --rebuild autoconf-2.69-12.2.src.rpm
$ sudo yum localinstall rpmbuild/RPMS/noarch/autoconf-2.69-12.2.noarch.rpm
  • libtoolのインストール

以下のエラーが出る場合は、libtoolをインストールします。

$ autoreconf -fvi
..(省略)..
configure.ac:36: error: possibly undefined macro: AC_PROG_LIBTOOL
      If this token and others are legitimate, please use m4_pattern_allow.
      See the Autoconf documentation.
autoreconf: /usr/bin/autoconf failed with exit status: 1

参考