2013年1月8日火曜日

Cassandra1.2のデフォルトパーテショナーに関して

 1.2では1.1と比べ幾つか仕様変更や追加があります

その中でパーテショナーの設定ではデフォルトパーテショナーが変更され、RandomPartitionerから新たに追加されたMurmur3Partitionerに変更になりました

Murmur3Partitionerに関してはハッシュ値をRandomPartitionerより早く取得できシノニムも少なく抑えられるハッシュ関数で、事実上RandomPartitionerと同じ立ち位置になります

しかし、トークンのレンジ範囲はMurmur3PartitionerとRandomPartitionerでは違いがあります
・RandomPartitionerのレンジ範囲
                     0 ~ 2^127
( 0 ~ 170141183460469231731687303715884105728 )

・Murmur3Partitionerのレンジ範囲
                 -2^63 ~ 2^63 - 1
( -9223372036854775808 ~ 9223372036854775807 )

Murmur3Partitionerに対応したノードのトークン値を均等にする求め方はpythonを使い
python -c 'print [((2**64 / リングのノード数) * i) - 2**63 for i in range(リングのノード数)]'
で求め、複数のリングが存在する場合はリングごとに1ずつ値をずらします

例)3ノードのリングが2つある場合
python -c 'print [((2**64 / 3) * i) - 2**63 for i in range(3)]
[-9223372036854775808L, -3074457345618258603L, 3074457345618258602L]

なので

一つ目のリングのノード3つは
-9223372036854775808
-3074457345618258603
3074457345618258602

二つ目のリングのノード3つは一つずらし
-9223372036854775807
-3074457345618258602
3074457345618258603

また、1.2に移行する際などデフォルトパーテショナーが変更されているので注意が必要です(必ず使用していたパーテショナーに合わせてください)

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

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

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