リレーショナル・データベースの「関係」にまつわるオハナシ
言葉
関係データベース、RDBMS。
話。
「参照整合性みたいな感じで関係を持っているからRDBMSと言うんだよ」
一理あり、一見筋も通っていそうだけど、ほんとに?
SQLの習慣では、リレーションを「テーブル (table)」、属性を「列(column)」、タプルを「行(row)」と呼ぶ。
数学的なリレーションの話
RDBMSはリレーション(テーブル)を使っているから、そういう名前がつけられたものなんだけど、そもそもリレーションってタプル(行)の集合だから、タプルは属性を原子的な値に写像するものなのです。
例えば、
{name: 'Takaya Hashiguchi', p.age: 25}
属性は、属性ヘッダ行(つまり列)で定義されてて、ドメインや制約型がついてることもある。
例えば、
{name: string, age: int}
これがリレーショナルな構造を表現する要点。
RDBMS、リレーショナル・データベース
名前は数学的だけど、実装は割りと実用的。
なぜ、数学的な話を持ちだしたかというと、リレーショナル・データベースが数学的な「関係」であることを強調したいから。外部キーを使って他のテーブルと「関係」を持つからじゃない。
そうした制約は関係のない話。
リレーショナル・データベースは、数学的な側面があんまり表に出ていない。
出さないようにしている?
でも、ユーザは強力なクエリを表現できるし、システムも規定のパターンで最適化できるから、リレーショナルモデルの力は数学によるところが大っきいと思う。
RDBMSは集合論から派生した関係代数をもとにして構築されてて、射影、選択、結合(デカルト積、つまりJOIN)などを組み合わせたもの。
nameだけを返す、つまり -> SELECT x.name
People を x に改名する、つまり -> FROM People x
age が nullのところを選択する、つまり -> WHERE x.age IS NULL
Solr4.0のJapaneseTokenizerFactory ( kuromoji ) で記号や特殊文字が捨てられないようにする方法
Solr4.0 の schema.xml(sample) では 以下のようになっていて、このまま text_jaを使っても記号や特殊記号をインデックス化してくれない
このまま使うと記号や特殊記号が消えてしまう
※ lucene-gosenはdefaultで記号を拾います
schema.xml
<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false"> <analyzer> <tokenizer class="solr.JapaneseTokenizerFactory" mode="search"/> </analyzer> </fieldType>
しかし、kuromojiのサイトではキチンと解析できていることがわかる
つまり、できるはず
ということでソース追ってみたら discardPunctuationという設定があった!
JapaneseTokenizerFactory に対して discardPunctuation="false"を与えると記号や特殊記号を拾ってくれるようになる
※ default true
ただし、Solr3.6系ではソースコード上では実装されているが schema.xmlから設定することができない
もし、やるならソースコードを書き換える必要がある
schema.xml
<fieldType name="text_ja" class="solr.TextField" positionIncrementGap="100" autoGeneratePhraseQueries="false"> <analyzer> <tokenizer class="solr.JapaneseTokenizerFactory" mode="search" discardPunctuation="false" /> </analyzer> </fieldType>
"★","♂","☆" 等の記号が拾われていることがわかる!
Centos6.x系にNTPサーバを構築する
NTPサーバをインストールする
[root@jigoku ~]# yum install -y ntp
NTPサーバの設定を変更する
RFC4330によると,NTPサーバはホスト名で設定することが推奨されている
1.NTPサーバの設定ファイルを編集する(/etc/ntp.conf)
2.ローカルからの時刻同期を許可
3.時刻同期先のNTPサーバを変更
ntp.nict.jp は,日本標準時を供給している独立行政法人情報通信研究機構(NICT)を指しており,精度は日本標準時に対して10ナノ秒以内らしい.
ntp.nict.jp を指定すると,4台のNTPサーバをラウンドロビンで参照する.
stratumは1であり,個人利用を認めている.
ntp.jst.mfeed.ad.jp はインターネットマルチフィードによるNTPサービス.
インターネットマルチフィードはIPS間を相互接続するJANAPを運用しているため,国内のISPと直接接続しているらしい.
ntp.jst.mfeed.ad.jp を指定すると,3台のNTPサーバをラウンドロビンで参照する.
stratumは2.
ntp.ring.gr.jp を指定すると複数のNTPサーバをラウンドロビンで参照する.
[root@jigoku ~]# vi /etc/ntp.conf # 2.ローカルからの時刻同期を許可 # Hosts on local network are less restricted. # restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap ↓ restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap # 3.時刻同期先のNTPサーバを変更 # Use public servers from the pool.ntp.org project. # Please consider joining the pool (http://www.pool.ntp.org/join.html). # server 0.centos.pool.ntp.org # server 1.centos.pool.ntp.org # server 2.centos.pool.ntp.org ↓ server ntp.nict.jp server ntp.jst.mfeed.ad.jp server ntp.ring.gr.jp
NTPサーバを起動する
1.ntpdateで手動でサーバの時刻を合わせる.大幅にズレているとNTPサーバを起動できない場合がある.
2./etc/rc.d/init.d/ntpd startでNTPサーバを起動する
3.chkconfig onで自動起動設定(--listで確認できる)
[root@jigoku ~]# ntpdate ntp.nict.jp 27 Jul 01:32:22 ntpdate[1817]: step time server 133.243.238.244 offset -302.827464 sec [root@jigoku ~]# /etc/rc.d/init.d/ntpd start ntpd を起動中: [ OK ] [root@jigoku ~]# chkconfig ntpd on [root@jigoku ~]# chkconfig --list ntpd ntpd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
NTPサーバの確認
NTPサーバと時刻同期中はサーバ名の前が空白
時刻同期が完了すると*や+が表示される
[root@jigoku ~]# ntpq -p remote refid st t when poll reach delay offset jitter ============================================================================== ntp-a3.nict.go. .NICT. 1 u 22 64 3 5.784 -0.579 0.473 ntp1.jst.mfeed. 210.173.160.56 2 u 22 64 3 4.278 -0.248 0.525 udon.nict.go.jp 103.1.106.69 2 u 21 64 3 7.154 -1.083 0.814 [root@jigoku ~]# ntpq -p remote refid st t when poll reach delay offset jitter ============================================================================== *ntp-a3.nict.go. .NICT. 1 u 60 64 377 5.718 -2.791 1.092 +ntp1.jst.mfeed. 210.173.160.56 2 u 62 64 377 4.064 -1.396 1.049 +udon.nict.go.jp 133.243.238.244 2 u 61 64 377 5.781 -2.626 0.947
ntpqの説明
' '(reject) 距離が遠くて捨てられたサーバー 'x'(falsetick) falseticker検査で捨てられたサーバー '.'(excess) 参照サーバーが多くて捨てられたサーバー '-'(outlyer) クラスタリング検査で捨てられたサーバー '+'(candidat) 接続テストに合格し、いつでも参照可能なサーバー '#'(selected) 同期距離が遠いが参照可能なサーバー '*'(sys.peer) 同期中であると宣言されたサーバー 'o'(pps.peer) 同期中であると宣言されたサーバー(同期はPPS信号から間接的に行なう。) remote リモート・サーバーのホスト名 refid 参照ID(不明の場合は、0.0.0.0) st stratum番号,サーバーが第何階層かを表します。 t 階層タイプ(l:local,u:unicast,m:multicast,b:broadcast) when 最後のパケットを受け取ってからの時間(単位:秒) poll ポーリング間隔(単位:秒) reach 到達可能なレジスタを(8進数表現) delay ポーリングインターバルの遅延見積もり(単位:ミリ秒) offset 階層のオフセット(単位:ミリ秒) disp 階層の分散(単位:ミリ秒)
CentOS 6.x系の初期設定
CentOS 6.x系をインストールするが終わったので、初期設定をしていきます
ここでは,一般ユーザを作成したり,rootになれる管理者ユーザを設定したり
環境に配慮したエコなインストール(minimal.isoによる最小構成)だったので
Baseパッケージなどの必要なパッケージ群をインストールしたりと,色々やります!
1. ユーザの作成
[root@jigoku ~]# useradd takaya [root@jigoku ~]# passwd takaya ユーザー takaya のパスワードを変更。 新しいパスワード: 新しいパスワードを再入力してください: passwd: 全ての認証トークンが正しく更新できました。 [root@jigoku ~]# su takaya [takaya@jigoku root]$ su - パスワード: [root@jigoku ~]#
2. rootになれるユーザを制限する
※ root権限があると何でも出来てしまうので,基本は一般ユーザでログインしroot権限が必要な場合のみsuでrootになるようにする
takayaをrootになれる管理者とする場合
[root@jigoku ~]# usermod -G wheel takaya # takayaを管理者用wheelグループに追加 [root@jigoku ~]# vi /etc/pam.d/su #%PAM-1.0 #auth required pam_wheel.so use_uid ↓ #%PAM-1.0 auth required pam_wheel.so use_uid 管理者用一般ユーザからはrootになれて、管理者以外の一般ユーザからはrootになれないことを確認 [root@jigoku ~]# useradd twitter # 一般ユーザtwitterを作成 [twitter@jigoku root]$ su root # rootになろうと試みる(パスワードは一致していても違うと出力される) パスワード: su: パスワードが違います [root@jigoku ~]# su takaya # 管理者用一般ユーザになる [takaya@jigoku root]$ su root # rootになる パスワード: [root@jigoku ~]#
3. パッケージ管理の初期設定(yumの初期設定)
[root@jigoku ~]# yum -y update Loaded plugins: fastestmirror, presto Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os error was 14: PYCURL ERROR 6 - "Couldn't resolve host 'mirrorlist.centos.org'" Error: Cannot retrieve repository metadata (repomd.xml) for repository: base. Please verify its path and try again # 名前解決まわりでのエラー DHCPを有効にしているとIPv6との競合でこういう状況になる もしくは単純にプロバイダーのDNSが落ちているか なので、DNS2にGoogle Public DNSを指定し、IPv6を無効化する [root@jigoku ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DNS2=8.8.8.8 IPV6INIT=no USERCTL=no [root@jigoku ~]# yum -y update 結構時間がかかる # yum-cronをインストール [root@jigoku ~]# yum -y install yum-cron Complete! [root@jigoku ~]# /etc/rc.d/init.d/yum-cron start 夜間 yum 更新の有効化中: [ OK ] [root@jigoku ~]# chkconfig yum-cron on # ベースパッケージ群と開発ツールパッケージ群をインストール [root@jigoku ~]# yum -y groupinstall "Base" "Development tools"
CentOSのフルインストールディスク(ここのCentOS-6.3-x86_64-bin-DVD1.iso と CentOS-6.3-x86_64-bin-DVD2.iso )だとOSのインストール時にインストールするパッケージを選べるのですが,今回は環境に配慮したエコなインストールを行ったので,必要なパッケージを別途インストールしています
具体的には、ここから適当なリポジトリを選んで指定したパッケージ群をインストールしています!
インストールしているパッケージ一覧を見るには以下のコマンドを叩きます
[root@jigoku ~]# rpm -qa --queryformat "%-40{GROUP}:%{NAME}-%{VERSION}-%{RELEASE}\n" | sort Applications/Archiving :cpio-2.10-10.el6 Applications/Archiving :tar-1.23-7.el6 Applications/Archiving :unzip-6.0-1.el6 Applications/Archiving :zip-3.0-1.el6 (略) System Environment/Shells :tcsh-6.17-19.el6_2 User Interface/Desktops :abrt-cli-2.0.8-6.el6.centos User Interface/Desktops :abrt-tui-2.0.8-6.el6.centos User Interface/Desktops :hicolor-icon-theme-0.11-1.1.el6 User Interface/Desktops :libreport-cli-2.0.9-5.el6.centos
4. SELinux を無効化する
# 手動でSELinuxの設定変更(再起動すると元に戻る) [root@jigoku ~]# getenforce Enforcing [root@jigoku ~]# setenforce 0 [root@jigoku ~]# getenforce Permissive # SELinux設定ファイルを編集する [root@jigoku ~]# vi /etc/sysconfig/selinux # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. # SELINUX=enforcing # ←SELinuxを有効化 SELINUX=disabled # ←SELinuxを無効化 # SELINUXTYPE= can take one of these two values: # targeted - Targeted processes are protected, # mls - Multi Level Security protection. SELINUXTYPE=targeted
/etc/sysconfig/selinux では SELinux を SELINUXTYPE で指定されたセキュリティ・ポリシーをどういった状態(SELINUX)で起動するか という設定を行なっています.
ちなみに,SELINUXTYPEはセキュリティ・ポリシー(ポリシーセット)を指定します.targetedを指定するとhttpdなどの代表的なデーモンのみが制御対象となり,strictを指定すると全てのデーモンが制御対象になります.MLSを指定すると全てのデーモンにRBAC(role base access control)を追加したstrictよりも厳格な動作をします.また,SELINUXは状態(state)を指定します.enforcingを指定するとセキュリティ・ポリシーに反する動作を全て拒否します.permissiveはセキュリティ・ポリシーに反する動作に対し警告を行います.disabledはSELinuxを無効化します.
たまにSELinux無効化反対派と出会いますが,元々SELinuxは政府系とか金融系などの厳格なセキュリティ要求を満たすために設けられた機能です.政府機関や金融機関からの強い要望がない限りSELinuxは無効で大丈夫だと思います.守るべき情報資産価値よりSELinuxの運用保守コストが大きくなるケースが殆どです.
5. nkfコマンドをインストールする
日本語処理に必要不可欠なのでインストールしておきます
[root@jigoku ~]# yum -y install nkf
んー、色々忘れてる気がするけど終わり\(^o^)/
CentOS 6.x系をインストールする
社会へ出るため徳島から東京へ引っ越した
しかし,自宅サーバは in the ダンボール のまま,はやくも7月なう です
今日は海の日です
リア充達は海でアレコレやっているというのに、ボクは自宅サーバを復活させようとしている
明日は仕事だというのに…
POP a Home-Server from ダンボール
半年くらい動かしていなかった癖に自宅サーバ様は壊れてなかった(つまらん
が
CentOSのバージョンが5.6だった
時代は6.x系に突入しているというのに!!
そういえば,上長に「Linuxわかってない」って詰られたし,勉強の意味も込めて再インストールすることにします
1. まずCentOSをDLしてきます
Index of /Linux/centos/6/isos/x86_64からCentOS-6.3-x86_64-minimal.iso をDLします
最近だと最小構成インストール(minimal.iso)が用意されているんですね
しかも,330MBしかない!
まさしくECOですね!
2. CentOS-6.3-x86_64-minimal.isoをDVDに焼きます
330MBをDVD(4.7GB)に焼いていて、ECOじゃないっていうツッコミはスルーします
DVDメディアしか自宅になかったんです(;´Д`)
WindowsだとisoファイルをDVDに焼くためにリッピングソフトが必要なのですが,Macだと「ディスクユーティリティ.app」で簡単に焼けちゃいます
3. インストール
6.x系のインストール画面カッコいいですね!
インストール時の注意点として,地域設定時に「システムクロックでUTCを使用(S)」からチェックを外す
※「インストール言語の選択」で "Japanese" を選択してていれば,使用するタイムゾーンは "アジア/東京" になっています.CentOSはntpdを利用して,世界標準時刻(GMTとかUTC)を発信しているNTPサーバに接続し,自動的に時刻調整を行うことができます.GMTと日本標準時刻(JST)では9時間の時差がありますので,OSをGMTのまま運用させると面倒が多くなります.従って,通常は自国との時差を計算してシステム動作の基準時刻を設定するわけです.CentOSインストール時のデフォルトでは「システムクロックでUTCを使用(S)」にチェックが入っていますが,運用上はGMTを用いる場合と大差ないです.ここでは素直にGMT基準の地域選択を利用するためにチェックを外しておきます.
4. インストールが完了したらネットワークの設定
[root@jigoku ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=none HWADDR=00:00:00:00:00:00 NM_CONTROLLED=yes ONBOOT=yes TYPE=Ethernet UUID="xxxxxxxxxxxxxxxxx" IPADDR=192.168.11.123 NETMASK=255.255.255.0 GATEWAY=192.168.11.1 DNS1=192.168.11.1 [root@jigoku ~]# /etc/rc.d/init.d/network restart インターフェース eth0 を終了中: [ OK ] ループバックインターフェースを終了中 [ OK ] ループバックインターフェイスを呼び込み中 [ OK ] インターフェース eth0 を活性化中: [ OK ]
なんか日本語化されている...気持悪い(´・ω・`)
Finagleハッカソンへ行ってきたっ! #finagle_hack
Scalaを始めて数ヶ月、より深くScalaを学ぶためにTwitter製RPCフレームワークであるFinagleで遊び倒そうの会へ参加してきました。
まったくのFinagle初心者の私でしたが、水島さん(@kmizu)のわかりやすい資料や中村さん(@gakuzzzz)の解説のお陰でFinagleは触って遊ぶことができました!
ありがとうございました(´∀`)
また、会場を提供してくださったTwitter Japanの山本裕介さん(@yusukey)にも良くしていただいて、至れり尽くせりでした!
沢山のノベルティグッズも頂きました!
以下、ハッカソンを通じて学んだことのメモみたいなものφ(`д´)メモメモ...
Finagle(ふぃねーぐる)とは、Twitter製の非同期RPCフレームワークで、RPCのシステムを作るためのフレームワーク。
※ Apache Thriftのように、それ自体がRPCを提供するわけではない
- 様々なプロトコルのServerとClientを簡単に作れる。
- JSONのメッセージングとか簡単に作れちゃう。
- FinagleはだいたいScalaで書かれている。
- JVM上で動作する言語からも利用できるが基本的にScalaがオススメ
Twitter社が出しているEffective Scalaでは以下のように書かれている
Twitterにおいて、最も重要な標準ライブラリはUtilとFinagleだ。Utilは、ScalaやJavaの標準ライブラリの拡張という位置付けで、それらに欠けている機能やより適切な実装を提供する。Finagleは、TwitterのRPCシステムで、分散システムの構成要素の中核だ。
Finagleのアーキテクチャ
- 中ではNettyが動いている
- NettyはJava NIOをラップしている
- ノンブロッキングなI/O操作ができる
- FinagleはJBoss Nettyをラップして使いやすくしたもの
- Filter, Codec, Serviceという概念がある
Twitter Finagle server as an alternate HTTP ser... - Scala Resources - Quora
Finagleの要素
重要な要素はFuture, Service, Filter, Codecの4つ!
Futureクラス
class Future[+A]{ def apply():A }
Service
Finagleにおけるロジックを実装する部分
class Service[-Req,+Rep] extends (Req) => Future[Rep]{ def apply(request:Req):Future[Rep] }
- Req型を受け取ってFuture[Rep]型を非同期に返す関数
- Server
- Serverは任意のプロトコルに任意のServiceを結びつける
//EchoServerの例 val server:Server = ServerBuilder() .codec(Http()) .bindTo(new InetSocketAddress(8000)) .name("ServerName") .build(service)
- Client
- Clientは任意のプロトコルのServiceそのもの
//EchoClientの例 val client: Service[HttpRequest, HttpResponse] = ClientBuilder() .codec(Http()) .hosts(new InetSocketAddress("localhost",8000)) .build()
Filter
FilterはServiceに対して何か変換を行ったりする
class Filter[-ReqI, +RepO, +ReqO, -RepI] extends(ReqI, Service[ReqO, RepI])=>Future[RepO] { def apply (request: ReqI, service: Service[ReqO, RepI]): Future[RepO] }
Codec
- Codecは、NettyにPipelineと密接な関係がある
- Codecは、各プロトコルのencodeとdecodeを司るNettyとのつなぎ役
- Finagleに標準でサポートされているCodec
- HTTP
- Stream(Http chunked transfer encoding)
- Memcached
- protocol buffer
- Redis
- Thrift
- Kestrel
trait Codec[Req,Rep] //Httpの例 val client: Service[HttpRequest,HttpResponse] = ClientBuilder() .codec(Http()) .hosts(address) .build() //Memcachedの例 val client: Service[Command, Response] = ClientBuilder() .codec(Memcached()) .hosts(address) .build()
その他の機能
- Server Support
- Backpressure
- Service Registration
- Native OpenSSL bindings
- Client Support
- Connection Pooling
- Load Balancing
- Failure Detection
- Failover/Retry
- Distributed Tracing(a la Dapper)
- Service Discovery(e.g., via Zookeeper)
- Rich Statistics
- Native OpenSSL bindings
- Sharding
Hello World
- Echoサーバ/クライアントでHello Worldを出力
Server側:HelloServer.scala
import com.twitter.util.Future import com.twitter.finagle.Service import com.twitter.finagle.builder.Server import com.twitter.finagle.builder.ServerBuilder import java.net.InetSocketAddress object HelloServer { def main(atgs:Array[String]){ val service = new Service[String,String]{ def apply(request: String) = Future.value(request) } val server:Server = ServerBuilder() .codec(StringCodec) .bindTo(new InetSocketAddress(8080)) .name("TestServer") .build(service) } }
Client側:HelloClient.scala
import com.twitter.finagle.Service import com.twitter.finagle.builder.ClientBuilder import java.net.InetSocketAddress object HelloClient { def main(args:Array[String]){ val client:Service[String,String] = ClientBuilder() .codec(StringCodec) .hosts(new InetSocketAddress("localhost",8080)) .hostConnectionLimit(1) .build() client("Hello, Finagle!!\n") onSuccess{ result => println(result) }onFailure { error => error.printStackTrace() }ensure{ println("end") client.release() } } }
実行結果
Hello, Finagle!!