分散オブジェクトストレージシステム「STF」をインストールしてみたよ [ミドルウェア編]

分散オブジェクトストレージシステム<「STF」って?


livedoorさんがlivedoor Blogなどのサービスの画像データの保存で使用している分散オブジェクトストレージ(のこと


livedoor(NHN Japan)で使われているらしいサービス


livedoor Blog、 livedoor PICS、 livedoor Blog Roll、 デコポスト、 デコミィ、 ロケタッチ、 Cure などの大量の画像データを管理しています。
現在全体で約4億オブジェクト、約70TBのデータ量を保存しており、日々増えつつあります。


http://labs.edge.jp/stf/

MySQL5.1 + Q4M, Perl, Memcached, Apache(or Nginx)を利用して動作しています
管理画面用ツール, Dispatcher(ストレージにオブジェクトを保存してくれる), Storage(データの破損や修復、分散配置)をしてくれる3つのPSGI(Perlアプリケーション)で構成されているようです
Perlは5.12系以上が必要ですので、Perlbrew等を用いると良いと思います(ここらへんの情報が少ない)
また、64bitのLinuxが推奨っぽい感じがします
※中の人でないので、結構間違っていると思います


欠点としては,一貫性は優れていると思いますが、結局データの配置先等の情報はMySQLが保持しており、データ量が膨大になるとMySQL自体が太ってきてしまうことでしょうか...
できれば、MongoDB等に配置できるようになるといい気がします


必要なミドルウェア


インストールするためには以下のミドルウェアが必要なようです
Perlはよくわからんので、適当です(MTで懲りている)


  • perlbrew(Perl5.12系より上) + cpanm
  • MySQL 5.1系 ... 5.5系や5.0系などは不可です(Q4Mの関係上)
  • Q4M ... MySQL上で動作するメッセージキュー
  • TheSchwartz ... Q4Mが使用できない場合はこちらを選択可能
  • Dispatcher Proxy(Apacheやnginx)
  • Memcached

インストール先の環境について


インストール先の環境 : ServersMan@VPS CentOS 5.7
既に入っているアプリ : git, apache, mysql5.5, ruby(rvm), gcc等DeveloperTools(以下参照)


git bash curl libxslt gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison iconv-devel

インストールされるもの: perlbrew, perl 5.14.x, mysql 5.1 with q4m, nginx, memcached


注意事項


以下のものが事前にインストールされている必要があります


上記DeveloperToolsとリポジトリとしてremi, rpmforgeを利用しています
※rpmforgeはgitのインストールの際に利用しています
※enableを0にしておきましょうここを参照


rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
wget http://pkgs.repoforge.org/rpmforge-release/rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm
wget http://apt.sw.be/RPM-GPG-KEY.dag.txt
rpm -ivh rpmforge-release-0.5.2-2.el5.rf.x86_64.rpm

Perl + cpanmのインストール


CentOSのデフォルトの5.8系だとuse featureが使えない様子なのでperlbrewでperlのバージョンを変更して使います


curl -Lk  http://xrl.us/perlbrewinstall | bash
echo " source ~/perl5/perlbrew/etc/bashrc " >> .bashrc
source ~/.bashrc

これでperlbrewコマンドが使えるようになったはずです


perlは奇数ナンバー(例 5.15等)が開発版らしいので、インストールするのであれば偶数番号にしましょう


perlbrew install perl-5.14.2

※なお最新のインストール可能なperlのバージョンは以下で確認できます


]# perlbrew available

以下のように表示されます
先頭のiはインストール済みを表します


i perl-5.15.6
i perl-5.14.2
perl-5.12.4
perl-5.10.1
perl-5.8.9
perl-5.6.2
perl5.005_04
perl5.004_05
perl5.003_07

perlのインストールが完了したら、cpanmをインストールします


perlbrew use perl-5.14.2
perlbrew install-cpanm

以下のようになれば完了です


# perlbrew use perl-5.14.2
# perl -v

This is perl 5, version 14, subversion 2 (v5.14.2) built for x86_64-linux

Copyright 1987-2011, Larry Wall

Perl may be copied only under the terms of either the Artistic License or the
GNU General Public License, which may be found in the Perl 5 source kit.

Complete documentation for Perl, including FAQ lists, should be found on
this system using "man perl" or "perldoc perl". If you have access to the
Internet, point your browser at http://www.perl.org/, the Perl Home Page.

# which cpanm
/root/perl5/perlbrew/bin/cpanm
# which perl
/root/perl5/perlbrew/perls/perl-5.15.6/bin/perl

Q4Mのインストール


手元の環境はすべてMySQL5.5系なので、5.1系をインストールしなくては!




... と思ったら、中の人(?)がこんなのを用意してくれていましたのでそのまま使います
Q4Mを簡単に導入する方法


cd /tmp
git clone git://github.com/kazeburo/mysetup.git
cd mysetup/q4m
chmod +x setup.sh
./setup.sh

インストール完了後以下で起動します


/etc/init.d/q4m start

stop, restartも用意されています


自動起動設定も忘れずにしておきます


chkconfig q4m on

Q4M専用のMySQLが起動してそこでQ4Mが動作するようになります
既存環境を汚さなくて済むし、すごく楽ちんです!:0


なお、/usr/local/q4mというディレクトリにインストールされます
設定ファイルは/usr/local/q4m/etc/my.cnfです
デフォルトのポートは13306で、接続する際には/usr/local/q4m/bin/mysql -urootで接続できます


TheSchwartzのインストール


Q4Mがインストールできるのであれば、こちらは不要です


cpanm TheSchwartz

Nginx1.0系のインストール


以下でユーザを追加します


useradd -s /sbin/nologin -d /usr/local/nginx -M nginx

CentOSらしくrepo追加でインストールしていきます
公式のインストール手順を一部修正して利用


vi /etc/yum.repos.d/nginx.repo

以下を入力します


[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=0
enabled=0

以下でyumでインストール!


yum install nginx --enablerepo=nginx

STF用の設定周りは次回


Memcachedのインストール


これまたyum(remi)経由で適当にインストール


yum install memcached --enablerepo=remi

ローカルホストからしかListenしないようにしておきます


vi /etc/sysconfig/memcached

以下のように入力します(メモリ量は適当に調整を)


PORT="11211"
USER="memcached"
MAXCONN="1024"
CACHESIZE="64"
OPTIONS="-l 127.0.0.1"

自動起動設定をして、memcachedを起動させます


chkconfig memcached on
/etc/init.d/memcached start

Perlbrewのコマンドメモ


  • perlbrew available ... インストール可能なperlのバージョンが出てきます
  • perlbrew list ... インストールされているperlが出てきます
  • perlbrew ... 使えるコマンドが出てきます(useとswitch, install-cpanくらいかな使うとして)

この記事の続き


スポンサーサイト

[Ruby]LevenshteinDistanceを使ったメールアドレス誤入力検知

[Ruby]LevenshteinDistanceを使ったメールアドレス誤入力検知


メールアドレスのホスト名の誤入力を検知するための、超簡易的な仕組みをご紹介


LevenshteinDistance(レーベンシュタイン距離)とは


2つの文字がどの程度異なっているかを数値で表す仕組みです
詳しくはWikipedia等をご参照してください


この仕組を用いて、いわゆるもしかして機能を実装することができます


LevenshteinDistanceのRubyによる実装


簡単に色々なところを参考にしながら実装してみました(多分あっているはず)
動作確認はruby1.9で行いましたが、1.8でも動作するように書いてあります(検証していないけど)
Gistにも掲載してありますので、そちらもご参照ください


# coding: utf-8

class LevenshteinDistance
def self.analyze(str1, str2, options = {})
_options = {:insert_cost => 1, :delete_cost => 1, :replace_cost => 1}.merge(options)
# remove Line feed code
x = str1.chomp
y = str2.chomp
return 0 if x == y

x = x.split(//)
y = y.split(//)

# str1 and str2 distance 2 dimensiton array
d = initalize_table(x.size, y.size)
(1..d.size - 1).each do |i|
(1..d[i].size - 1).each do |j|
d[i][j] = [
d[i-1][j] + _options[:delete_cost],
d[i][j-1] + _options[:insert_cost],
d[i-1][j-1] + (x[i-1] == y[j-1] ? 0 : _options[:replace_cost])
].min
end
end
d.last.last
end

# @example LevenshteinDistance.initalize_table(3,2)
# [
# [0, 1, 2],
# [1, 0, 0],
# [2, 0, 0],
# [3, 0, 0]
# ]
def self.initalize_table(x_size, y_size)
raise if x_size == 0 or y_size == 0
Array.new(x_size + 1) do |i|
i==0 ? (0..y_size).to_a : Array.new(y_size).unshift(i).map{|k| k.nil?? 0 : k}
end
end
end

メールアドレスの誤入力検知の簡単なサンプル


上記LevenshteinDistanceのRuby実装をlevenshtein_distance.rbとして保存しておきます
そのディレクトリと同一のディレクトリに以下のサンプルを適当な名前(sample.rb等)で作成してください


# coding: utf-8
require File.expand_path 'levenshtein_distance'

# 判定対象のメールアドレス
popular_emails = %w(gmail.com mail.goo.ne.jp hotmail.co.jp yahoo.co.jp)

# しきい値
threshold = 3

inputs = %w(1@gmai.com@gmai.com 1@gamil.com 1@mail.goo.co.jp 1@hotmail.ne.jp 1@yaho.co.jp)

inputs.each do |email|
_email = email.split('@')
_result = Array.new(popular_emails.size) do |popular|
LevenshteinDistance.analyze(_email.last, popular_emails[popular])
end
if _result.min <= threshold
_email[_email.size-1] = "<strong style='color:red;'>" + popular_emails[_result.index(_result.min)] + "</strong>"
puts "Did you mean: #{_email.join('@')}"
puts "You entered '#{email}'"
end
end

これは以下のように出力されます(strongタグは表示されていません)


Did you mean: 1@gmai.com@gmail.com
You entered '1@gmai.com@gmai.com'
Did you mean: 1@gmail.com
You entered '1@gamil.com'
Did you mean: 1@mail.goo.ne.jp
You entered '1@mail.goo.co.jp'
Did you mean: 1@hotmail.co.jp
You entered '1@hotmail.ne.jp'
Did you mean: 1@yahoo.co.jp
You entered '1@yaho.co.jp'

なお、途中の_resultはそれぞれ以下のようになっています


  • 1@gmai.com@gmai.com ... [1, 10, 7, 8]
  • 1@gamil.com ... [2, 10, 7, 7]
  • 1@mail.goo.co.jp ... [8, 2, 7, 5]
  • 1@hotmail.ne.jp ... [8, 7, 2, 9]
  • 1@yaho.co.jp ... [7, 8, 6, 1]

メールアドレスの誤入力検知サンプルプログラムの解説


popular_emailsが、正しいメールアドレスのサンプルです
(実運用の際にはここを適切に設定するまたは、機械学習を用いて動的に変化するようにする必要があります)
popular_emailsの一覧と入力(inputs)を比較してLevenshteinDistanceがthreshold以下のものが存在した場合は、Did you mean: xxxと出力するようにしています


thresholdが3なのは, neとcoの入れ間違えと誤入力1文字(gmailのlが抜けたりなど)までは許容するためにいれてあります
もちろん閾値が大きいほど誤検知が多くなってしまいます

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。