2012年12月6日木曜日

virtual node について


virtual nodeについて(Cassandra勉強会第24回のスライド)

http://www.slideshare.net/seki_intheforest/virtual-node


virtual nodeはバージョン1.2.0 から実装されますが
Strategy関係で問題がある為最低でも1.2.1以降からと思っておいたほうがよい

動作として単純に一つのノードに割り当てるトークンをランダムに複数持つようにする機能で
複数のノードをランダムで複数のトークンを持たせる事で比較的負荷を均等にする事ができ
レンジが多く細分化されるのでパーテショナーによってデータの偏りがあまり起こらない

また、一つのノードに複数のトークンがある際、同じノードのトークンが連続する事があるが
レプリケーションが一つのノードに二重に取られる事は無い

virtual nodeの良い点悪い点


virtual nodeの良い点
  • ランダムの値のトークンに任せるのでトークンの値のmoveの作業をしなくて良い
  • ノードがダウンした際リング内の隣のノードが複数になるので負荷が集中しない
  • ノード追加した際の他のノードの受け渡しも全体のノードで行うようになるので早い
  • ノードの負荷はレンジの領域の多さではなく、トークンの数の多さで考えられるようになる
  • パーテショナーの偏りに対応できる
virtual nodeの悪い点
  • トークンの値を任意に変更できない
  • 起動後にトークンの数を変更できない
  • virtual nodeのトークンを全体的に変更する際はノードのdecommisionをしてから再度追加する事になる
  • トークンを大量に増やさなければ比較的に分散されない
  • 大量のトークンでの nodetool ring の見栄えがすごい

virtual nodeは総合的に見て、よりメンテナンスフリーに近づく形にはなっている

virtual node をメンテナンスする上での追加ツール


virtual nodeのトークンの値を変更する為のツールも1.2から登場する
  • shuffle
現在あるトークンの値を変えずにそのトークンを別のノードに移してシャッフルする
  • バランスツール
現在未実装、恐らく1.2.1から登場する

virtual node の使用の仕方

cassandra.yaml で設定を行いcassandraを起動するとトークンが作られる

(1.2.0 beta1 の cassandra.yaml)
# This defines the number of tokens randomly assigned to this node on the ring
# The more tokens, relative to other nodes, the larger the proportion of data
# that this node will store. You probably want all nodes to have the same number
# of tokens assuming they have equal hardware capability.
#
# If you leave this unspecified, Cassandra will use the default of 1 token for legacy compatibility,
# and will use the initial_token as described below.
#
# Specifying initial_token will override this setting.
#
# If you already have a cluster with 1 token per node, and wish to migrate to 
# multiple tokens per node, see http://wiki.apache.org/cassandra/Operations
# num_tokens: 256
num_tokensをコメントアウトして持ちたいトークンの数を指定する(デフォルトだと256が入っている)
また、initial_tokenの設定は無効になる

2012年12月5日水曜日

Leveled Compactionについて

Leveled Compactionについて(Cassandra勉強会第23回のスライド)

http://www.slideshare.net/seki_intheforest/leveled-compaction
 

Leveled Compactionを選ぶ上でよい場合とそうではない場合

よい場合
  • 読み込みのレスポンスを早くしたい
  • 書き込みより読み込みが多い
  • 一定のデータが頻度に更新され、使用される
  • 頻度にRowデータの削除などを行う
そうではない場合
  • I/Oのリソースが厳しい
  • 頻繁に大量の書き込みを行う
  • 一度きりの書き込みが多い
構造上SSTableを細分化するのでレスポンスや読み込みが早くなり
細かいSSTableのコンパクションも頻度に起こるので削除データもデータから消えやすいが
同時に細かいコンパクションが多発するので頻繁に大量の書き込みをしてI/Oのリソースを常に使う場合は
I/Oのリソースが足りなくなる可能性がありお勧めできない
 

2012年11月9日金曜日

astyanaxその1

astyanaxを使ってみる


astyanaxは主にNetflixが開発を行っている Cassandra Java Client でcassandraへの読み書きはもちろん、主に自動的にリングやノードの状態を見て負荷を平均になるようにコントロールできる新しいクライアントです



astyanaxのインストール


事前に準備しておくもの
  • maven2
  • git
  • JDK6
まずgitからastyanaxを取得してビルドします
git clone https://github.com/Netflix/astyanax.git

mvnを使用してローカルリポジトリにおきたい場合は取得したastyanaxのディレクトリ上で
mvn clean install

jarファイルだけほしい場合は
mvn package

astyanaxの依存関係のライブラリを取得したい場合は以下のコマンドでtarget/dependency に出力される
mvn dependency:copy-dependencies

またgradlewを使用してビルドしたい場合は
gradlew build

astyanaxで適当にCassandraを使用してみる


Cassandra側でKeyspaceとColumn Familyを作成しておく
create keyspace ks
    with placement_strategy = 'SimpleStrategy'
    and strategy_options = {replication_factor:2}

create column family cf
    with column_type = 'Standard'
    and comparator = 'UTF8Type'
    and default_validation_class = 'UTF8Type'
    and key_validation_class = 'UTF8Type'

以下のような単体で動かせるようなソースコードを作成(ソース名ConnectionTest.java)
import org.apache.log4j.PropertyConfigurator;

import com.netflix.astyanax.*;
import com.netflix.astyanax.AstyanaxContext.Builder;
import com.netflix.astyanax.impl.AstyanaxConfigurationImpl;
import com.netflix.astyanax.thrift.ThriftFamilyFactory;
import com.netflix.astyanax.model.ColumnFamily;
import com.netflix.astyanax.model.ColumnList;
import com.netflix.astyanax.model.Column;
import com.netflix.astyanax.model.Row;
import com.netflix.astyanax.model.Rows;
import com.netflix.astyanax.serializers.StringSerializer;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.connectionpool.NodeDiscoveryType;
import com.netflix.astyanax.connectionpool.impl.CountingConnectionPoolMonitor;
import com.netflix.astyanax.connectionpool.impl.FixedRetryBackoffStrategy;
import com.netflix.astyanax.connectionpool.impl.SmaLatencyScoreStrategyImpl;
import com.netflix.astyanax.connectionpool.impl.BadHostDetectorImpl;
import com.netflix.astyanax.connectionpool.impl.ConnectionPoolType;
import com.netflix.astyanax.connectionpool.impl.ConnectionPoolConfigurationImpl;

public class ConnectionTest
{
    
    public static void main(String[] argv) throws ConnectionException{
        
        //適当にlog4jの設定を引数で渡してやる
        String filePath = argv[0];
        PropertyConfigurator.configure(filePath);
        
        //コネクション設定と開始
        AstyanaxContext<Keyspace> context = new AstyanaxContext.Builder()
            .forCluster("{クラスタ名}")
            .forKeyspace("ks")
            .withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
                //.setDiscoveryType(NodeDiscoveryType.NONE) ノードの情報を意識しない場合の設定
                .setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE) // リング内のノードを意識したアクセスの仕方に設定
                .setConnectionPoolType(ConnectionPoolType.TOKEN_AWARE) // ノードのトークンを意識したアクセスの仕方に設定
            )
            .withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
                .setPort(9160) // 使用ポート
                .setMaxConnsPerHost(1) // 限界のコネクション数
                .setSeeds("{ホスト}:9160") //Seedsのアドレス
            )
            .withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
            .buildKeyspace(ThriftFamilyFactory.getInstance());
        
        context.start();
        Keyspace keyspace = context.getEntity();
        
        //使用するカラムファミリの定義
        ColumnFamily<String, String> CF_TEST =
          new ColumnFamily<String, String>(
            "cf",              // カラムファミリ名
            StringSerializer.get(),  //キーのシリアライザ
            StringSerializer.get());   //カラムのシリアライザ
        
        //データの書込み
        MutationBatch m = keyspace.prepareMutationBatch();

        m.withRow(CF_TEST, "0001")
          .putColumn("value1", "hoge", null)
          .putColumn("value2", "hogehoge", null);
          
        m.withRow(CF_TEST, "0002")
          .putColumn("value1", "huga", null)
          .putColumn("value2", "hugahuga", null);
        
        try {
          OperationResult<Void> result = m.execute();
        } catch (ConnectionException e) {
        }
        
        //データの取得
        OperationResult<Rows<String, String>> result =
          keyspace.prepareQuery(CF_TEST)
                  .getKeySlice("0001", "0002")
                  .execute();
        
        //取得したデータの表示
        for (Row<String, String> row : result.getResult()) {
            System.out.println(row.getKey());
            for (Column<String> column : row.getColumns()) {
                System.out.println(column.getName() + " " + column.getStringValue());
            }
        }
    
    }
}

ビルドして実行(lib内に各jar、第一引数に適当なlog4jの設定ファイルで実行)
$ javac -cp ./lib/*:./ ConnectionTest.java
$ java -cp ./lib/*:./ ConnectionTest ./log4j.properties
0002
value1 huga
value2 hugahuga
0001
value1 hoge
value2 hogehoge

2012年10月31日水曜日

Cassandraインストールドキュメント

Cassandra推奨ハードウェア

Cassandra インストール

Cassandra のインストール(RHEL・CentOS編)

Cassandra のインストール(Debian・Ubuntu編)

Cassandra のインストール(Generic編)

その他サーバーの推奨設定

ユーザーリソースの限界値の設定
Disable Swap の挙動の変更
時間の同期

Cassandraの基本設定

基本的な設定項目
各ノードのリング内の位置設定
JVM のメモリ使用量設定

Cassandra 推奨ハードウェア構成

Cassandra推奨ハードウェア構成

■ノード構成
  • 動作確認環境用最小構成 3 台以上
  • プロダクション用最小構成 6 台以上推奨(9 台以上が望ましい)
  • Unix、Linux、Windows サーバーの稼働する環境

■HWスペック
  • メモリ8GB以上
  • HDD500GB以上(SATA可)
  • Commitlog 用とデータディスク用の 2 台のディスクを推奨
  • データディスク用としてSSDの使用は、尚、望ましい
  • Gigabit Ethernet推奨

  • AWS・EC2上では m1.large 以上必須

Cassandra のインストール(RHEL・CentOS編)


■インストールに必要なもの


  • yum コマンド
  • root 権限又は sudo を使用可能な権限
  • Oracle Java SE Runtime Environment(JRE)
  • JRE1.6.0_19 以上が推奨されています。JRE1.7 のものは非推奨です。
  • Java Native Access(JNA)その他サーバーの推奨設定

■Cassandra のインストール

  1. Java のバージョンを確認
  2. 以下のコマンドで JAVA(JRE)のバージョンを確認します。

    $java -version

    JAVA(JRE)が 16.0_19 以上の Oracle の SunJava が推奨されています。また,JAVA(JRE)1.7 は非推奨です。推奨されるバージョンがインストールされていない場合はここでインストールします。

  3. EPEL(Extra Packages for Enterprise Linux)のインストール
  4. (RHEL 5.x/CentOS 5.x のみ)
    以下のコマンドを実行し EPEL をインストールします。EPEL は jna の実行に必要にな
    ります。

    $sudo rpm –Uvh \
    http://dl.fedoraproject.org/pub/epel/5/i386/epel-release-5-4.noarch.rpm
  5. yum で使用するリポジトリに DataStax のリポジトリを追加
  6. yum で使用する/etc /yum.repos.d を作成して Datastax のリポジトリを追加します。

    $sudo vi /etc/yum.repos.d/datastax.repo
  7. 3 で作成したファイルに DataStax のリポジトリ情報を書き込み
  8. [datastax]
    name=DataStax Repo for Apache Cassandra baseurl=http://rpm.datastax.com/community enabled=1 gpgcheck=0
  9. yum で Cassandra パッケージをインストール
  10. 以下のコマンドを実行し Cassandra をインストールします。 この時 Cassandra ユーザーが作成され、Cassandra の起動時に使用されます。

    yum install apache-cassandra11
  11. 使用する Java を OpenJDK から SunJava に変更
  12. yum でインストールした後は OpenJDK が入ってしまうので、alternatives コマンドでSunJava を使用するように変更します。

    sudo alternatives --install /usr/bin/java java /usr/java/jre1.6.0_25/bin/java 20000 sudo alternatives --config java
  13. Cassandra を起動
  14. 以下のコマンドを実行しcassandraを起動します。

    sudo /etc/init.d/Cassandra start

Cassandra の基本設定

設定は conf/cassandra.yaml で設定します。 debianは/etc/cassandra内、CentOS などはインストールされた先/etc/cassandra/conf 内、他は任意で設置 したconf ディレクトリに存在します。

基本的な設定項目

  • クラスター名
  • 全体のクラスター名を設定します。

    cluster_name: 'Test Cluster'
  • DB データ格納先
  • data_file_directories:
        - /var/lib/cassandra/data
  • コミットログ格納先
  • commitlog_directory: /var/lib/cassandra/commitlog
  • キャッシュデータ格納先
  • saved_caches_directory: /var/lib/cassandra/saved_caches

    ※上記3つのデータ格納先ディレクトリはそれぞれデフォルトの設定です。cassandra を実行するユーザーで書き込めるディレクトリを指定してください。パスの部分を変えれば変更が可能です。

  • seeds
  • seeds はノード初回起動時に keyspace などのメタ情報等を seeds に設定されたホストに問い合わせに行き、その後はノードの生き死にの確認をする際に利用されます。リング構築時最初に起動するノードには、そのノードの自アドレスを設定して起動してください。また、そのリングの中で最初に起動するノードでは無い場合、生きているノードのアドレスを指定してください。

    seed_provider:
      - class_name: org.apache.cassandra.locator.SimpleSeedProvider
          - seeds: "127.0.0.1"
    
  • listen_address
  • listen_address はリングを構築する上での、自ノードのアドレスです。基本的に自ノードのアドレスを設定します。また NIC が複数存在する場合などは、複数あるアドレスのうち、いずれかを指定してください。

    listen_address: localhost
  • rpc_address
  • rpc_address はデータをやり取りする際に使用されるアドレスです。基本的に、0.0.0.0(全ての NIC で使用する)を設定します

    rpc_address: localhost
  • ポート番号
  • rpcで使用するポートが rpc_port、ノード間で使用するのが strage_portです。そのノードで使用できるポート番号をそれぞれ設定してください。

    rpc_port: 9160
    storage_port: 7000
    

各ノードのリング内の位置設定

一つのリングにリングの位置として一周 0~2^127 までのレンジがありますいずれかのレンジをノードに指定する事で、そのレンジ位置から次のノードまでのレンジに対応するデータがそのノードに入る事になります。(データがどのレンジ位置になるかはデフォルトの場合 rowkey を hash にした値が使用されます)また、このレンジ位置をノードではトークンと言います。複数のノードでリングを構成する際はこのトークンの値を均等に分けて設定する事により各ノードに入るデータの割合を均等にする事が出来ます。 以下のような5つのノードでリング構成を構築しました。

設定例

192.168.1.10
192.168.1.11
192.168.1.12
192.168.1.13
192.168.1.14

この5つのノードの位置を均等にします。この時、トークンの値を自動的に生成してくれるツールを使うと便利です。今回はそのトークン値生成ツールを使用して設定を行います。

  1. wget でトークン値生成ツールを取得します。
  2. $wget https://raw.github.com/riptano/ComboAMI/2.2/tokentoolv2.py
  3. 取得したトークン値生成ツールを python で実行し、トークンの数値を取得します
  4. $python tokentoolv2.py 5
    {
        "0": {
            "0": 0,
            "1": 34028236692093846346337460743176821145,
            "2": 68056473384187692692674921486353642291,
            "3": 102084710076281539039012382229530463436,
            "4": 136112946768375385385349842972707284582
             }
    }
    
  5. nodetool の move コマンドを使用して、
  6. 取得した値をそれぞれのノードに設定します。(nodetool は cassandra の bin 配下、又はパッケージでインストールした場合は/usr/bin/nodetoolにあります)

    
    $ nodetool -h 192.168.1.10 move 0
    $ nodetool -h 192.168.1.11 move 34028236692093846346337460743176821145
    $ nodetool -h 192.168.1.12 move 68056473384187692692674921486353642291
    $ nodetool -h 192.168.1.13 move 102084710076281539039012382229530463436
    $ nodetool -h 192.168.1.14 move 136112946768375385385349842972707284582
    
    
  7. nodetool の ring コマンドを使用して、均等にデータが配置されたか確認します。
  8. $ nodetool -h 192.168.1.10 ring

    それぞれのノードに Token が設定されているか、データが均等に配置されているか確認してください。データが均等になっていなければ nodetool の move で Token を変更することで調節が可能です。

JVM のメモリ使用量設定

Cassandra はデフォルトでJVMが使用するヒープメモリを自動的に計算して設定していますが非常に小さな値となってしまう場合があります。JVMのメモリ使用量を確認しOSの搭載メモリの半分に満たない場合は手動にて設定変更を行います。

#vim cassandra-env.sh
MAX_HEAP_SIZE=”4G” ←コメントアウトをはずし指定(搭載メモリの半分以上)
HEAP_NEWSIZE=”800M” ←コメントアウトをはずし指定(CPU core * 100MB)

Cassandra のインストール(Generic編)


■インストールに必要なもの


  • root 権限又は sudo を使用可能な権限
  • Oracle Java SE Runtime Environment(JRE)
  • JRE1.6.0_19 以上が推奨されています。JRE1.7 のものは非推奨です。
  • Java Native Access(JNA)その他サーバーの推奨設定

■Cassandra のインストール

  1. Java のバージョンを確認
  2. 以下のコマンドで JAVA(JRE)のバージョンを確認します。
    $java -version
    JAVA(JRE)が 16.0_19 以上の Oracle の SunJava が推奨されています。また,JAVA(JRE)1.7 は非推奨です。推奨されるバージョンがインストールされていない場合はここでインストールします。
  3. Cassandra のダウンロード
  4. Cassandra 公式サイトからバイナリーをダウンロードして解凍します。
    $wget http://www.ring.gr.jp/archives/net/apache/cassandra/1.1.6/apache-cassandra-1.1.6-bin.tar.gz
    $tar zxvf apache-cassandra-1.1.6-bin.tar.gz
    $rm apache-cassandra-1.1.6-bin.tar.gz
  5. Cassandra を各ディレクトリに配置
  6. 解凍したファイルを任意に配置します。
    例)
    ・/usr/local にファイルを配置した後、シンボリックリンクを貼る

    $sudo mv apache-cassandra-1.1.6 /usr/local
    $cd /usr/local
    $sudo ln –s apache-cassandra-1.1.6 cassandra

    ・cassandraユーザーの作成
    $groupadd cassandra
    $useradd -g cassandra -s /usr/sbin/nologin cassandra

    ・ログディレクトリ・データディレクトリの作成
    $mkdir /var/lib/cassandra
    $mkdir /var/log/cassandra
    $chmod cassandra:cassandra /var/lib/cassandra /var/log/cassandra
  7. Cassandraの起動
  8. 以下のコマンドを実行します。

    $sudo -u cassandra /usr/local/cassandra/bin/cassandra

その他サーバーの推奨設定

ユーザーリソースの限界値の設定

  1. limits.conf
  2. Cassandra はデフォルトのユーザーリソースより多くのリソースが必要になります。以下 のように /etc/security/limits.conf へ書き込み設定を行います

    cassandra soft nofile 32768
    cassandra hard nofile 32768
    root soft nofile 32768
    root hard nofile 32768
    cassandra soft memlock unlimited
    cassandra hard memlock unlimited
    root soft memlock unlimited
    root hard memlock unlimited
    cassandra soft as unlimited
    cassandra hard as unlimited
    root soft as unlimited
    root hard as unlimited

  3. sysctl
  4. さらに次のコマンドを実行しリソースを増やす必要がある場合もあります。

    sysctl -w vm.max_map_count=131072

    このコマンドで大量のマップが使用できます。永続化させる場合には/etc/sysctl.confに以下を追記してください。

    vm.max_map_count=131072
  5. 90-nproc.conf
  6. CentOS, RHEL, OEL Sysems の場合は /etc/security/limits.d/90-nproc.conf のlimit 値 も 以下のように 1024 から 10240 へ変更してください

    soft nproc 10240

Disable Swap の挙動の変更

OS 上の OutOfMemory(OOM)killer が Java Virtual Machine(JVM)を落とし Cassandraが強制終了されないように以下のように設定してください。
$sudo swapoof --all

時間の同期

Cassandra に投入されたデータはタイムスタンプを基準とし常に新しいタイムスタンプのデータが上書きをします。その為、全てのノードは NTP(Network Time Protocol)で時間を合わせる必要があります。

Cassandra のインストール(Debian・Ubuntu編)

■インストールに必要なもの

  • apt-get コマンド
  • root 権限又は sudo を使用可能な権限
  • Oracle Java SE Runtime Environment(JRE)
  • (JRE1.6.0_19 以上が推奨されています。JRE1.7 のものは非推奨です。)
  • Java Native Access(JNA)
  • (Ubuntu 10.04 LTS を使用している場合はJNA3.4にアップデートが必要です。)
  • その他サーバーの推奨設定

■Cassandra のインストール

  1. Java のバージョンを確認
  2. 以下のコマンドで JAVA(JRE)のバージョンを確認します。

    $java -version

    JAVA(JRE)が 16.0_19 以上の Oracle の SunJava が推奨されています。また,JAVA(JRE)1.7 は非推奨です。 推奨されるバージョンがインストールされていない場合はここでインストールします。

  3. インストール用に Cassandra のリポジトリを設定
  4. apt-get を使用してCassandraをインストールするため、インストール用のリポジトリを設定ファイルに記載します。

    $vi /etc/apt/source.list.d/Cassandra.source.list
    deb http://www.apache.org/dist/cassandra/debian 11x main
    deb-src http://www.apache.org/dist/cassandra/debian 11x main
  5. Cassandra のリポジトリを使用するため公開キーを追加
  6. 以下のコマンドを実行し公開キーを追加します。

    $gpg –keyserver pgp.mit.edu –recv-keys 4BD736A82B5C1B00
    $pgp –export –armor 4BD736A82B5C1B00
  7. Cassandra をインストール
  8. apt のリストをアップデートした後、apt-get を使用してインストールします。

    $sudo apt-get update
    $sudo apt-get install cassandra
  9. Cassandra の起動
  10. Cassandra をインストールすると自動的に Cassandra が起動します。初期設定のまま起動されてしまうので、一度起動したCassandra を停止し初期化を行い、再び起動する必要があります。

    $sudo service Cassandra stop
    $sudo bash –c ‘rm /var/lib/cassandra/data/system/*
    $sudo service Cassandra start

JWT(Jason Webトークン)を理解するJWT(Jason Webトークン)を理解する

JWT ( Jason Web トークン)を理解する   JSON Web Token はオープンスタンダードです。これは、任意の 2 つの機関 ( ユーザー、サーバー)間で情報を転送するために使用されます。 JWT では、ユーザーデー...