2015年11月21日土曜日

HBase リージョン分割した後にクライアントが最新行キーを持つリージョンからしかデータが取れなくなった時の対処法

HBase リージョン分割した後にクライアントが最新行キーを
持つリージョンからしかデータが取れなくなった時の対処法

HBaseからとにかく全件を取得したいクライアントで起こる事象。
例えばHBaseをキューのように溜まってるデータを取ったら
消すようにして使用している場合。

具体的には org.apache.hadoop.hbase.client.Scan を何も設定せず
そのまま使用していて、HBaseサーバ側でリージョン分割が
発生した場合に現象が発生する。

これはリージョンサーバの情報をクライアントが覚えておき、
無駄な通信をしないようにする仕様から来ていると思われる。
分散システム前提のシステムをキューとして使用しようとすること
自体が設計に反しているが、それを敢えてやる場合の話である。
(上司が勘違いされている場合は、部下が必死で「HBaseを
 キュートして使うのはちょっと違いますよ。」と説得しましょう。
 HBaseはビッグデータの最終的な入れ物。前段でキューが必要なら
 RDBを使った方がよほど良い。)

1番いいのはリージョン分割しないようにHBaseの分割サイズを
調整しHBaseに入るデータ量を上回るように、HBaseのパラメータおよび
取得クライアント側の性能を設計することだ。

HBaseリージョンサーバの分割設計は、MemStoreのフラッシュサイズと
リージョンサーバの最大サイズの設計からなる。

フラッシュサイズは
1. 固定値(hbase.hregion.memstore.flush.size)と
2. 計算値(hbase-env.shの HBASE_REGIONSERVER_OPTSで設定するヒープサイズ ×
 hbase.regionserver.global.memstore.upperLimit and lowerLimit)
で調整できる。
(フラッシュとは、メモリからディスクへのフラッシュのこと)
また、リージョン分割のサイズは hbase.hregion.max.filesize で調整できる。


とは言ってもHBaseの仕組み上、リージョン分割は念頭に置かなければならない。
リージョン分割ありきで考えるならば、クライアントはいつ分割が発生しても
いいように備えなければならない。

単純な順かつリソース消費量の順に案を挙げていくと、
1. 毎回HTableから作り直す。
2. 毎回リージョン情報をクリアする。(HTable#clearRegionCache())
3. 開始行キーを先頭にリセットする。(Scan#setStartRow())

となるだろうか。(実際の検証はしてないのであくまで推測。)

ということで3. の開始行キーを設定する方法を紹介する。
// HTable htable = ... 
Scan scan = new Scan();

// use addFamily() when you want to set row family only, 
// but it's better to specify a column, because you're going to get 
// all of data. this column would be like a second key.
// take care of your machine's memory.
scan.addColumn(Bytes.toBytes(FAMILY_XXX), Bytes.toBytes(COL_XXX)); 

// set 0x00(null) so that HBase will scan from the first region server.
scan.setStartRow(new byte[]{ (byte)0x00} ); 

HashMap dataMap = new HashMap<>();
try(ResultScanner result = htable.getScanner(scan);) {
    for(Result item : result){
        // Row ID
        byte[] rowId = result.getRow();
         // Column data example.
        byte[] data = result.getValue(Bytes.toBytes(FAMILY_XXX), Bytes.toBytes(COL_XXX));
        // for example, get small sortable value like date_and_time value.
        dataMap.put(rowId, data);
    }
}

// then sort the sortable value using Entry<>, sort of value.
ArrayList> dataEntries = new ArrayList<>(dataMap.entrySet());
Collections.sort(dataEntries, (o1, o2) -> {
    // define how to sort between byte[].
    // for example parse byte[] to Long when the data is UNIX epoch time. (8bytes)
    Long t1 = ...   // convert with ByteBuffer or something.
    return t1.compareTo(t2);
});

// loop with sorted key list.
for( Entry  dataEntry : dataEntries){
     // then get all of columns with row id.
     // this is safer way because you can manage when you should stop the function or not.
     // you can choose resource or spec or ..
    Get get = new Get(dataEntry.getKey());
    Result result = htable.get(get);
    byte[] content = result.getValue(xxx);
    ....
}

2015年8月24日月曜日

JUnitでHBaseクライアント側を通す - How to test HBase in Unit Test process (client side)

jUnitでHBaseの擬似HTableをつくってUnit Testを通すやり方。

HBaseにつなぐソースのユニットテストを、実際のHBaseに
繋がずに通したいときに、擬似HTable(モック)を作成して
通す方法。

簡単に言うと
①HConnectionを偽装
②偽装HConnectionを使用してHTableを偽装
となる。
また、おまけで
③Scan時に擬似データを返すように擬似データを登録
することも可能。

※①②ともHBaseの内部の処理を通るため作成には
数十秒かかる。そこで通るタイムアウト絡みの
パラメータを乗っ取れば(リフレクション)高速化できる
のであろうが、そこまでは追わなかった。

いろいろ試した結果、この方法に辿り着いた。

一応試行の遍歴を記すと、
・実際にHBaseに接続した時のHTableオブジェクトを
 シリアライズ化して保存し、それを復元する試行。
→引数なしのHTableコンストラクタが定義されてないので
 エラー。

※そもそもシリアライザを継承してないのでシリアライズしても
 表面上のパラメタだけしか取得できない。
 そこでJSON化を試し、それなりの情報が取得でき、それの
 復元化(復元マッパの登録)まで出来たが、やはり最後は
 コンストラクタ呼び出しがされるので、引数なしコンストラクタ
 未定義でエラー。

ダメかと思ったが、HTableはHConnectionを引数にするコンストラクタが
あるのでHConnectionの偽装、それを使用してしかも -ROOT- を指定する
ことでHTableのコンストラクタを通すことができた。

HBase、Hadoopを内部から理解されてる方ならHBaseクライアントの
Unit Test方法は一般的なのかもしれないが、取っ掛かもなくいきなり
HBaseクライアントのUnit Testをする必要が生じた方々はこれを
参考にしていただければ。一助になれば。

以下、テストクラスのコードサンプル。
// Prepare the configuration
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "127.0.0.1");

// 1.Create HConnection - HConnectionの作成
HConnection con = ... 
// make HTable with table name "-ROOT-" and set isClosed to false.
// prepare class loader
// get inner HTable's implemented class
// get "isClosed" member
Field fld = cls.getDeclaredField("isClosed");
fld.setAccessible(true);
fld.set( ... 

// 2.make HTable mock with -ROOT- table , so that it will work.
// 「-ROOT-」テーブルのHTableモックの作成。 
HTable tbl = new HTable("-ROOT-", con);

// 3. you can put the data of htable with reflection.

2015年3月2日月曜日

Oracle 目的のサイズのアーカイブログ作成方法

目的のサイズのアーカイブログ作成方法

方法1:REDOログファイルのサイズを目的のサイズで作成して自然にログスイッチさせる。
方法2:オンラインREDOログのサイズを確認して、目的のサイズになったら手動でログスイッチする。

方法1の場合、環境作成後だとREDOログファイルを作り直さなければならず面倒。
また、試験は本番環境と同じ条件で実施したいだろうから、REDOログファイルの
作り直しとかはあまりやりたくない。

よって以下では方法2のやり方を記載する。

1. ログスイッチしてサイズを0リセット
alter system switch logfile;

2. 開始時点の【生成済みREDOログサイズ】を確認
select value from V$SYSSTAT where name = 'redo size';

3. 任意のSQLを大量投入

4. 【生成済みREDOログサイズ】を確認して、開始時点との差分から
 現在のオンラインREDOログサイズを算出。
select value from V$SYSSTAT where name = 'redo size';

5. 目的のサイズになったらログスイッチ
alter system switch logfile;

2015年2月27日金曜日

Windows の新規作成ショートカットの遍歴

Windows のエクスプローラでフォルダやテキストファイルファイルを
新規作成する時のキーボードショートカットの遍歴。

Windows XP: ALTを押したまま f → w
Windows 7: ALTを押したまま f → x
Windows 8: ALTを押したまま h → w

もうちょっとキーボーダーオリエンテッドにしてほしいと思う一方、
やむを得ない事情も推測できるので、OS毎に体に叩き込んで覚えている。

ファイルやバッチを作りたいときの最速のアクセス方法だと思い、
多用している人も多いと思うのだが。
あと、Windows 7までは片手でてきててよかったが、
Windows 8から右手を使うか、左手親指(または我を折って小指)でALTを押しながら、
左手人差し指でがんばって「h」を押すか、になってしまい、
非常に残念である。

(Windows 8のどう考えても使いづらいスタートメニューとか、
MSはたまに(しょっちゅう?)意思決定機関は大丈夫か?と疑わざるを
得ない変更をやらかしてくれる。
 (あのスタートメニューはMS社内でも「いやこれはありえないでしょ」
  的な意見もあったはずだろう。それこそ社のブランドイメージとか
  利益に責任を持つ役員陣が使ってみた時に「これではブランドイメージが
  傷つく」と敏感に感じ取って声をあげれなかったのだろうか。
  IEマジックとかExcelマジックとか揶揄されているが、あきらかに
  バグだったりおかしな仕様だったりするのに、ソフトの提供側の
  方が偉くて、使用者はその仕様に従うしかない構造である。
  「世界トップシェアのソフトなのだから、そんな小さな意見に
   耳を傾けていられるか」という態度。
  そんなことをしていると、いつか凋落すると思うのだが。。。)
  2021年頃にたまたま読み返して追記:本当にGAFAとかと差が。。。上記は2015年に書いたので私にも少しは先見の明があった^^

MSとしては「意思決定プロセスは過去の成長してきた実績があり、
過去の成功・失敗からフィードバックしてAIとかも駆使して
日々改善しているから万全だ!」
とか思ってるかもしれないが、組織が巨大すぎて、導き出したはずの
「正解」がいざ蓋をあけると、正常な感覚からは遥か遠い彼方へ
行ったりするのだろうな。
僭越ながらアドバイス申し上げると、一般市民の「正常な感覚」も
意思決定プロセスのパラメータに加えるべきなのだろう。)

2015年2月12日木曜日

JIS X 0201 半濁点の誤記報告

JIS X 0201 "7ビット及び8ビットの情報交換用符号化文字集合" の

「゜」(半濁点)の名称が「KATAKANA SEMI-VOCED SOUND MARK」となっており、

voiceのiが抜けてる!

JISへ連絡いたしました。


2020/09/09追記

久々にJISを確認したところ、「2019年7月1日の法改正」で

名称が変わったようで、それに合わせてかは不明ですが、

「゜」(半濁点)の名称が「KATAKANA SEMI-VOICED SOUND MARK」と

修正されてました!!!

ありがとうございます!!!

(これで私もJISに名前を残すことができた。)


PowerShellのslコマンド

lsコマンドのジョークコマンド"sl"がPowerShell で通った!
と思ったら Set-Locationのエイリアスだった。。

Unixコマンドのエイリアスと、PowerShell観点のショートカットの
せめぎあいを垣間見ました。

ジョークコマンドはこちらもどうぞ