おそらくはそれさえも平凡な日々

育児休業を取得しています

というエントリを書こうと思っていたら、あっという間に残り数日になってしまった。

てことで、3月頭から今月いっぱい育児休業中です。去年、id:motemenが短期で取得してたので、そういうのもアリか、と思って僕も取得してみることにした。

年子で大変なので何か手伝えればいいなってのは少しあるんですが、どうせあまり戦力にはならないだろうので、折角の機会なので育児経験をしたいって言うのが一番大きなモチベーション。

朝早起きするのは大変ですが、最近忙しさにかまけて怠っていた料理とかを心置きなくできるのが良い。僕の料理は妻とはちょっと趣向が違うので、1歳半を過ぎた娘が食べてくれるか心配だったけど、物珍しさか結構食べてくれるのは嬉しい。

戦力にはあまりなってない気がしますが、どちらかと言うと僕の我儘で育児休業を取得することを許してくれた妻には感謝しています。おかげさまで楽しんでいます。

会社側は、まあ僕がいなくて回るでしょ、って思ってたら案の定回ってるので、まあそりゃそうですよね、という感じです。育休取りやすくて良い会社です。

YAPC::Kansai 2017 OSAKA の前夜祭で話しています

「突撃!隣の開発環境!」というテーマのお話をさせてもらっています。

今は主に以下のような環境で開発をしています。

何のためにバージョンロックをするか

外部ライブラリに依存する時に、どのようにバージョンロックをすべきかどうかという話。僕個人のスタンスです。

基本的には、開発しているものがライブラリであれアプリケーションであれ、 とにかく依存先の最新についていく のが前提で、その前提に立った場合に、上のような考え方になるかな、と思っている。

特にライブラリ作者は依存ライブラリに非互換変更が入って動かなくなったら、頑張って追随するか、依存を切るかをする。これは、ライブラリを公開している上での責務であり、そこで低いバージョンにロックしてしまうのは悪手。(「責務」って書いちゃうと大変な感じしちゃうけど、まあそのへんはベストエフォートで…)

バージョンロックした場合の落とし穴として、古いライブラリに依存し続けるという問題が起きがち。そこは、依存ライブラリを最新に上げても動かせるかどうかのチェックは随時行ったほうがいい。例えばnightly buildなど。

これは理想の話をしていて、なかなか現実思い通りにはいかないものですけれどもね。現実は厳しい。

`map[string]Obj` だと、 `m["hoge"].Field = "hoge"` できない。 `map[string]*Obj` だとできる

理由とかはこの辺。

以前 map[string]Obj 使ってて嵌ったんだよなーと思ったので、書き留めておく。なんか、 m["hoge"] は常に2つ値返してくれて良いんじゃないかとも思うことはある。

2017年年始

あけましておめでとうございます。2016年年末に無事に子供が産まれて、激動の2016年はきれいに締めくくられました。

去年は概ね良い年だった。けど、さすがに公私共に流石に激しすぎた。状況に振り回されて、ずっと半ば混乱状態だったように思う。そんな中、なんとか乗り切ったと思うが、自分の思い描く最低限のパフォーマンスの1/3も出せなかったように感じている。

今年はもう少し落ち着いてペースを取り戻していきたい。立場も少し変えて、少しチームマネージメントからも離れて、プロダクトに注力していけると良いかな、と思っている。

アウトプットよりインプットの割合を増やしたい。英語も流石にどうにかしてちゃんと学ぶかって言う気持ちになっている。

YAPC::Hokkaido 2016 SAPPORO 行ってきた

妻の出産予定などもあり、参加しようか迷っていたのだけど、スポンサーセッションで話すことになったので、参加してきた。

規模が200人規模だったこともあるのか、結果的にPerl Monger同士の交流的な側面にフォーカスされ、以前のYAPC的な感じもあって楽しかった。

トークの裏でラウンジでtokuhiromがPerlモジュールのメンテナンス始めたりして、つられて僕もコードを書き出したり、懇親会でkazuhoさんにモジュールのメンテナンス権をもらったりなどしたのは、個人的に少し前のYAPCっぽい体験だな、とか思ったりしました。

(個人的には、YAPC::Asia Tokyo 2012でPlack::Middleware::Auth::OAuthのメンテナンス権をhidekさんからもらったのがYAPC原体験の一つだったりします)

あと、懇親会で、techno_nekoさんとお話ができて、Rijiのマイナーな便利機能について質問いただけたりしたのも嬉しかったです。

今回のトークで印象に残ったのは、kazeburoさんとmiyagawaさんのトーク。

kazeburoさん「Perl書いてるとkazuhoさんのコードが読める」っていうのは本当にメリットだよなーと激しく同意でした。もちろん、kazeburoさんのコーソが読めるのも大いなるメリットなわけですが。Perl5がシステムプログラミングに非常に向いている言語だとも改めて感じた。

miyagawaさんのトークはさすがだった。Fastlyはエンジニア向けのSaaSということで、世の中の様々なサービスを下支えする立場で品質を担保しながらデリバリーを早めるかと言う課題について、泥臭い仕事も絡めながらも、どう確実に改善しているかについて話していて面白かった。その姿勢は同じようにエンジニア向けSaaSを開発している身として非常に参考になった。

「CDN作るのって面白いのかな? そう考えていた時期が僕にもありました」ってmiyagawaさんが言ったのが面白かったんだけど、これも僕が手がけているMackerelというサーバー監視・管理サービスを作ることは面白いのかどうかって話に通じる物があるな、と思って共感できた。監視ツール開発って、一見退屈そうに感じるかもしれないけど、実はめちゃくちゃ面白いので。

nekokakさんのクロージングの力強さも良かった。JPAの活動の中でその動きは横目で見ていましたが、nekokakさんとにかく異常にパワフルに動いていて圧倒されました。

今回は29年ぶりの大雪ということで、天候的には波乱でした。その中でちゃんと人数が集まってよかったですね。

僕も行きは、前夜祭の日にさくらインターネットさんの石狩データセンター見学予定を入れていたのだけど、飛行機遅延のため集合に間に合わず無念の不参加となった。一番楽しみにしていたイベントだっただけにこれは残念だった。

帰りも欠航出まくりで、予定していた便も欠航で、振替も翌日以降ってことで絶望してたんだけど、空港でacidlemonちゃんに偶然出くわして、振り替えテクを教えてもらうことができた。運良く振り替えた便がこれまた運良く飛んだのでなんとか帰ってこられた。帰宅は深夜2時40分だったけどまあよし。

ところでノベルティ欲しかった。いつもだったら参加可否に関わらずノータイムで個人スポンサー登録するところなんだけど、一応(名前だけは)JPAのコアスタッフなので、躊躇してたら埋まっていた。残念。

Test::mysqld 0.20をリリースしました

この記事は、Perl5 Advent Calendar 2016 の16日目の記事の穴埋めということにしました。

https://metacpan.org/release/SONGMU/Test-mysqld-0.20

YAPC::Hokkaidoでkazuhoさんにコラボに加えてもらったので諸々調整してリリースしました。大きな機能差分は以下のとおりです。

start_mysqlds 対応が入ったことに併せて、App::Prove::Plugin::MySQLPool 0.06がリリースされています。これに伴いテスト起動時に直列で複数プロセスを起動していたのが、並列で起動するようになり高速化が望まれます。

お試しください。

MySQL5.7.6対応は、Goの方はhttps://github.com/lestrrat/go-test-mysqld/pull/4にてパッチを送って取り込んでもらっていたのですが、本家のPerlの方が逆に対応が遅れている状況でした。

それをYAPC::Hokkaidoの懇親会でkazuhoさんに相談しに行ったらその場でコラボに加えられたていただいた、という経緯。YAPCでこういうやり取りが行われるのはYAPCっぽくて良いですね。

一瞬バージョン0.18を出したのですが、dist nameの関係でパッケージングをミスっており、修正して0.20をリリースしました。報告していただいたcharsbarさんありがとうございました。

Redisアプリケーションパターン

この記事は、はてなエンジニアアドベントカレンダー2016の12日目の記事です。

先日こういうツイートをしました。

言いたかったのは、Redisはキャッシュのためだけのミドルウェアだと誤解されがちなのですが実際はそうではないということです。実際、公式サイト を見に行くと以下の様なことが書かれています。

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker.

つまり、Redisは多彩なデータ構造を保持できるインメモリーのデータストアで、様々な活用法があり、キャッシュとして「も」使える、ということです。

Redisとmemcachedの性能比較記事のようなものがネット上には散見されますが、Redisが単なるmemcached代替のように捉えられてしまうのは残念なことです。Redisにもmemcachedにもそれぞれ良さがあり、使い所はかぶるところがあっても異なります。実際、僕は去年のISUCON5では予選ではRedisを使い、決勝ではmemcachedを使いました。

ここでは、Redisの多彩なデータ構造を活かした、アプリケーションでの活用パターンをいくつか解説します。

前提

Redisはとにかく公式のヘルプが充実しており、読み応えが満載です。まず、Redisの各種データ構造に関しては、以下の解説を読むと良いです。

http://redis.io/topics/data-types-intro

各コマンドの解説についても、 http://redis.io/commands を見ると全ての解説がインタラクティブシェルを交えながら理解することができます。このページの良い点として、コマンドの計算量が載っており、パフォーマンスの目安と出来る点があります。

Strings ~ 普通のKV

Stringsはごく普通のKey-Valueです。文字列をセットすることができます。数値として扱うこともできます。

> SET mykey somevalue
OK
> GET mykey
"somevalue"

以下のようにexpireを指定することもできます。

> SET mykey somevalue EX 30
OK

"mykey" という文字列に、"somevalue"という値を30秒間保持します。

SETコマンドを利用した排他制御

ここまでは普通のKey-Valueですが、StringsにはNXという排他制御のためのオプションが存在します。NXは"not exists" の略で、そのキーに値が存在しない時にのみSETが成功します。例えば、以下のようなコマンドを使えば、"lockkey" という文字列で30秒間排他的にロックを取ることが可能になります。

> SET lockkey "aaa" NX EX 30
(integer) 1 // 値のセットに成功すると1が返る
> SET lockkey "bbb" NX EX 30
(integer) 0 // 30秒間は値のセットができないのでセットに失敗して0が返る
> GET lockkey
"aaa"

expireを待たずにロックを解除するにはDELを発行すればよいのですが、ロックを取る時に利用した文字列と一致しているか比較をしてからDELを発行するのが安全です。その場合以下のようなLUAスクリプトをEVALで実行するのが良いでしょう。

if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end

これは、 https://redis.io/commands/set のページに説明が書いてあります。

また、余談ですが、RedisにはSETNXやSETEXなどのコマンドがありますが、これらは非推奨となっており、上記のように、SETのオプションとして、NXやEXを組み合わせて利用するのが推奨される使い方となっています。上記のsetコマンドのドキュメントに以下のように書かれています。

Since the SET command options can replace SETNX, SETEX, PSETEX, it is possible that in future versions of Redis these three commands will be deprecated and finally removed.

Sorted Set ~ 順序つき集合

Sorted Setは、Redisで扱える強力なデータ構造であり、Redisの便利さの代名詞としてよく取り上げられす。例えば、以下のようにすれば、ハッカーの生誕年順にデータを格納し、取り出すことができます。

> ZADD hackers 1940 "Alan Kay"
(integer) 1
> ZADD hackers 1957 "Sophie Wilson"
(integer) 1
> ZADD hackers 1953 "Richard Stallman"
(integer) 1
> ZADD hackers 1949 "Anita Borg"
(integer) 1
> ZADD hackers 1965 "Yukihiro Matsumoto"
(integer) 1
> ZADD hackers 1914 "Hedy Lamarr"
(integer) 1
> ZADD hackers 1916 "Claude Shannon"
(integer) 1
> ZADD hackers 1969 "Linus Torvalds"
(integer) 1
> ZADD hackers 1912 "Alan Turing"
(integer) 1

Sorted Setとスコアランキング

Sorted Setはスコアランキングなどを格納するのに非常に便利です。上位の一定数のみを残したい場合などは、 ZREMRANGEBYRANK を使って、集合の中の要素の数を削るのがセオリーです。たとえば上記の例で生年が古い順に5名のみを残したい場合は以下のようになります。

> ZREMRANGEBYRANK hackers 5 -1
(integer) 4

Sorted Setを扱う上で留意が必要なのが「同率問題」です。これは、同じスコアの複数要素がある場合、その並び順が取得され、順位が取得されるわけでは無いという問題です。

> ZADD numbers 2 two
(integer) 1
> ZADD numbers 2 ni
(integer) 1
> ZREVRANK numbers ni
(integer) 1
> ZREVRANK numbers two
(integer) 0

同率のスコアがある場合は、キーの辞書順に要素が並べられることが保証されています。なので、RDBMSのように、同一値の場合に並び順が不定にならない点では安心と言えます。

また、同率スコアを考慮した上で正しい順位を取得したい場合は、 ZCOUNT を使いそのスコアより大きい要素の数を数えた上で、それに1をプラスするのがセオリーです。

Sorted Setとタイムライン

Sorted Setを利用したパターンとしてランキング以外によく使われるのは、タイムライン的な機能です。この場合、epochなどをスコアにしてSorted Setに情報を格納することにより新しい順(epochの大きい順)にデータを取得することができるようになります。

Set ~ 集合

RedisというとSorted Setばかり取り上げられますが、個人的にはそれと同じくらい便利だと思っているのがSetです。Setは重複しない集合を扱うことができ、様々な集合演算をおこなうことができます。

直近のログインユーザーの取得

属性ごとに直近の1時間のログインユーザーを取得するようなことをしたい場合、例えば10分毎に別のSetに格納しつつ、SUNIONSTORE で結合することで、ある程度リアルタイムで直近のログインユーザーの集合を属性ごとに作ることができます。

集合からのランダム取得

Setからランダムに値を取り出したい場合に、SRANDMEMBER を利用できます。ランダム取得は、ゲームのマッチング処理などで重宝しますが、RDBMSでは難しい処理なので、Redisならではの威力を発揮できる部分です。ランダムで取得しつつ、集合から削除したい場合には、SPOPが便利です。

List ~ リスト

Listはそのままリストですが、それを扱うための様々なコマンドが揃っています。

Listをキューとして使う

その中でも僕が好きなのが BRPOPLPUSH です。

BRPOPLPUSHは blockingなインターフェースなので先頭に"B"が付いています。具体的には、あるリストの末尾から値を取り出し(RPOP)、その値を別のリストの先頭に追加(LPUSH)します。取り出せる値がない場合には、値が入ってくるまで待ち受けてブロックする(B)というコマンドです。なのでBRPOPLPUSHという名前になっています。Redisの複雑なコマンドの名前は略語を区切り文字無しでつなげることもあり、呪文のようになっていることが多いのですが、BRPOPLPUSHは勢いが感じられてかなり好きです。

BRPOPLPUSHはジョブキューのようなものを作る上で有用です。リストにジョブが投入されるまで待ち受けて、ジョブが投入されたら、ジョブを取得しつつ、別のリストに実行中のジョブとして投入することができるからです。ジョブの実行が終わったら、LREMコマンドを利用して、実行中ジョブのリストから当該ジョブを削除します。

> RPUSH jobs "one"
(integer) 1
> BRPOPLPUSH jobs inprogress 30
"one"
// なんか作業
> LREM inprogress -1 "one"

実際には、実行中ジョブリスト"inprogress"から定期的にタイム会うとしたジョブの削除や"job"への再投入などが必要になりますが、そのための判定として、ジョブ用の文字列に時刻を含んだJSONなどを格納しておくことが良いでしょう。

このあたりの話は、 RPOPLPUSH のページに、"Reliable queue pattern" として書かれているので読むと良いでしょう。

まとめ

ということで、Redisの活用パターンを幾つか紹介しました。Redisにはまだまだ活用方法がありますし、公式のヘルプには読み応えのある有用情報が詰まっているので読んでみると良いでしょう。

怒涛の2016年を振り返る

早めに振り返っておく。今年はとにかく怒涛だった。完全にキャパオーバーしてたし、色々遅くなったりして各方面に迷惑もかけたりもして、申し訳なかった。

Mackerel 好調

おかげさまでMackerelが好調である。このフェーズのプロダクトのディレクターをさせてもらえているのはめちゃくちゃ幸せなことだと思う。

なので忙しいのはかまわないし、寧ろ良いことなのだが、やりたいことが無限にあってとにかく手が足りない。その割には僕自身はあまり手が動かせてない。チームメンバーも増えたのでマネージメント的な仕事も増えている。

なんか、完全に管理職のジレンマに陥ってきているのだが、とは言え慣れてない仕事をするのは楽しい。パフォーマンスもっと出せるやろ、って自分を叱咤しながら「ピーターの法則に負けない」って思って生きている。

Mackerelを開発していて思うのは「世の中の変化の速度よりも早い開発スピードを出さないと終わる」ということ。Mackerelは特に変化の早いインフラ界隈に纏わるソフトウェアなので、特にそう感じるのだけど、別に他の業界でも世の中の変化速度以上の開発スピードを出せなくなったところから淘汰されていくんだろうな、と思う。

ちなみに、今Mackerelチームで働くのはものすごく楽しいので、興味のある人は是非応募してください。エンジニア全職種お待ちしております。応募前に話聞きたいとかでも僕に連絡くれれば話の機会を作ります。

http://hatenacorp.jp/recruit/

子供

子供は可愛い。去年の6月に生まれたので、もう1歳半だ。どんどん成長する。赤子だったのがもう子供という感じになった。

同僚の id:mtakano さんの以下のエントリを見て、これは素晴らしいと思って真似した。妻が実家から戻ってきた翌日から今でもほぼ欠かさず毎朝子供を風呂に入れている。

最近はたまに一緒に近所の公園めぐりをしたりしている。普段は動きたがるのだが、抱っこ紐で僕に抱っこされるのは快適らしく、特に文句も言わずおさまってくれている。

子供はかなり発育がよく既に12kgを超えている。抱っこしながら散歩するといい運動になってよいのだが、ちょ氏のサイトに以下のようなことが書いてあって震えている。

ところでみなさん、エルゴの耐荷重の最大値は「おんぶ」状態のものであることはご存知でしたか? 前抱きの場合は 12.2kg が最大なんですよ。

エルゴが壊れた - 氾濫原

ISUCON6

とにかくしんどかった。今年一番の頭痛の種はこれでした。「仕事忙しいのにISUCONとかやってる場合じゃない」とか言ったりしていた。

やるからには、ちゃんとはてなでやってますアピールをするべきだったんだけどあまりできなかったことも悔いが残る。ISUCON6に関するエントリは別途書きます。

マンション購入

買ってしまった。割りと勢いで買った。ローンの審査を出したのがはてな上場承認の一週間前で、知ってはいたがもちろん口には出せず「来週だったらまた状況違うのかもなー、ストックオプションもあるしなー」とか内心思ったりしていた。これも後日別途エントリ書ければ。

はてな上場

そういや上場しました。IRチームがめちゃくちゃ優秀で、はてなの文化を理解して維持したままできれいに上場したのはすごい。上場前後で嫌な変化は全くない。

僕ははてなが好きだし、良いことをやっている会社だと思っているので、それを小さな世界でやってるのではなく、ちゃんと公器として成長させていこうという点で、株式公開は喜ばしいことだと思っている。

みんなのGo言語

執筆に参加しました

この話はもらったときは、案件が降ってきすぎで「完全にフィーバーだな」とか思ったけど、それを面白がる余裕がまだあった。

JPA参画

はてなとしてJPA(Japan Perl Association)の新体制に関わっている。会合に出席したりはしているがあまりコミットできていない。本当はもっとコミットしたいと思っているのだが…。

Perl Hackers Hub執筆者探し

実は去年の7月から技術評論社のWEB+DB Press誌のPerl Hackers Hubの執筆者探しを担当しているのだけど、毎回執筆者探しは難航している。もう少し早めに声かければ良いのだが毎回ギリギリになってしまっていて良くない。

Perl Hackerの皆様は、声をかけると大体前向きに返事をしてくださるので助かっております。

1000ブクマ

以下のエントリが1000ブクマ行った。1000ブクマ超えは初めてのことだったので嬉しかった。

読み返してみると、チグハグな部分もあって書き直したいところもある。これでも休みを丸一日潰して書いたくらいなので、文章書くの早くなりたい…。

ハッカーズチャンプルー

ハッカーズチャンプルー2016 にお招きいただいて「Mackerelは至る道」というトークをしてきた。

こういうお声がかかることはありがたいことだし、沖縄行けたのも良かった。ハッカソン合宿からの参加で、仕事関連のコードをぼちぼち書いた。数日オフィスの外で仕事するとだいぶはかどりますね。MTGが無いのが良いし考え事もできる。来年もそういう機会を作りたい。

CTO交代

まさかの id:stanaka さん退職からの id:motemen CTO就任。所感はこちら → はてなに入って2年くらい経ちました。CTOとかMackerelとか

僕もチーフエンジニアとして motemen CTOをもっと盛り立てていかないとなーとか思いつつ、できていないので頑張りたい。

そして二人目の子供

なんと、二人目の子供が妻のお腹の中にいて、予定日は12月30日です。まさしく今年の怒涛を締めくくるにふさわしい行事ですね。

「みんなのGo言語」の執筆に参加しました

みんなのGo言語【現場で使える実践テクニック】

「みんなのGo言語【現場で使える実践テクニック】」の執筆に参加させてもらいました。僕は第1章の「Goによるチーム開発のはじめ方とコードを書く上での心得」を担当しました。

主に、Goを始めたばかりの人に向けてのお約束や普遍的な考え方について個人のアレンジも加えながら書きました。このあたりはネット上には雑多な情報が混在しており、独自のやり方で回り道をしてしまっている人も多く見受けられることに課題意識があったので、このあたりの「レールを敷く」ことを意識しました。Goは思想的なところの説明も含めて公式ドキュメントが充実しており、そちらに同じようなことが書いていることも多いのですが、そこから一歩踏み込んだ実践的な内容になるようにしました。

雑誌以外の書籍執筆は初めてで良い経験をさせてもらいました。自分の名前がついた本が書店に平積みされているのを見るのは感無量です。改めてこの素晴らしい執筆陣の中で本を書けたのは幸せなことだと感じています。

豪華執筆陣によるバランスの取れた構成の本になっています。ちょっと興味のある方にも、一歩踏み込んだことを知りたい方にも有用な内容が含まれているかと思います。Go言語に興味のある方は是非お手にとってお買い求めください。

メールや、執筆に利用したGitHubリポジトリのログを見ると以下のようなスケジュールでした。

すごい人達との共著ということで、各種締切には緊張感がありました。単著ではこの締切は守れなかったと思うので、単著書ける人はつくづくすごいですね。

相互レビューが楽しく刺激的でした。他の人の担当分を読むことも、自分の担当分への的確なフィードバックも学びが多かったです。

話題の表紙ですが、そのラフが上がってきたときには、その奇抜なデザインに正直ちょっと驚いたのですが、その後配色されたものが共有されたときには、当たり前ですが「プロはさすがだな」と驚嘆したことを覚えています。

個人的にも貴重な経験をさせてもらいましたし、良い本に仕上がっていると思いますので、再度となりますが、ぜひお買い求めください!

みんなのGo言語【現場で使える実践テクニック】