ユユユユユ

webエンジニアです

放送大学に入学してみよう

 連休の終わりに、大学にいこうかな? とカジュアルに思いついたのが昨日のこと。それからいちにち考えてみて、基礎的なことを体系的に「お勉強」するのなら放送大学教養学部に入るのがうってつけという結論にいきついた。教養学部というから、学部1-2年生の気分で自由に学問ができるイメージでいる。

 モチベーションの管理が厳しいという独学特有の問題も放送大学にはつきまとうようだが、まあいままでもそうやって独学してきたのだから、これはなんとでもなる自信はある。仕事を辞めて4年生大学に編入するくらいの覚悟さえ持つほど思いつめかねなかったところ、二足のわらじになるとはいえ仕事と両立させられるパスがあるのは嬉しいことこの上ない。

 ここで微積線形代数、解析なんかを1年かけてじっくりお勉強しようという気持ちが育っている。そのさきでなにをしたいかはわからない。なぜならまだ知らないことが多すぎて、自分にどんな可能性があるのかすらわかっていないのだ。ただ、少なくともここでの学びの先に新しいパースペクティブが広がっているだろうという昂揚感はたしかにある。導入科目群をきちんと追えられたら、物理ほか自然科学の世界にもそのままアクセスできそうだったり、はたまた芸術と哲学の方面に趣味の勉強の食指を伸ばしてもいいわけだ。まさに新大学生のようにワクワクしている。そしてこうしてワクワクできる対象があることこそ、暗い世界にあって何より幸せなことだとおもう。

 大学であるので、入学時期は4月と10月に限られている。そしていまちょうど5月がはじまったところである。10月入学が許可されるという新しい文化に感謝しつつも、あと半年弱は手も足もでない。ただ入学の準備をするだけである。まあとりあえずということで、資料は請求してある。そしてもう数ヶ月はいままで通りの独学に集中しよう。厚めの専門書をもう一冊読むくらいの時間はあがなえる。

 以下は補足として、「放送大学とはこういうものか」という見取り図を与えてくれたのはこちらの記事。とりわけ後者の講義レビューは履修イメージも含めてなんとなくの手触りをえた。これだけのことができるなら十分満足できるだろうとおもうことができた。

 それから、「社会人の学び直し」という観点ではこれらのエントリも拝見させていただいた。年齢がひとまわり離れていたり、子供も配偶者もいない気楽さもこちらにはあるけれど、だからこそいまいっそう頑張るぞと熱い気持ちは与えられている。

 上のエントリはいずれも学位取得をゴールにおいていたが、僕はあくまで学位は追いかけない。別にすぐに学士が欲しいわけでないし、必要になれば取りにいけばいいというだけの単純な皮算用である。海外の修士コースで勉強するという選択肢もあるようだし、いろんな選択肢があることをありがたく思う。あくまでこの先の僕自身が自分から何を引き出せるかによって道は変わるはずだから、まずは地に足をつけて知るべきことを知るべしというスタンスでいる。

大学にいこうかな?

 世界がいまより平和になったらやりたいことがある。それはそうとして、いますべきことはなにか?

 大学にはいりなおすということを考えたことがある。ベルリンから帰国して、途方にくれながら次になにをしようか考えていた頃のことである。直接的な刺激になったのはこの記事だったかとおもう。

僕の会社のとあるプロジェクトで、スケジュール管理を扱う新サービスの検討が始まったとき、CTOを含む複数のエンジニアが即座にホワイトボードでアルゴリズムの議論を始めました。スケジュール管理は複雑な組み合わせ問題になることが多く、また我々が考えていたシステムが少し特殊な制約を持っていたので、計算結果の単純なキャッシュがしづらい難問であることは明白でした。 複雑な現実課題を解決するソリューションには、ありもののライブラリやフレームワークなどというものは存在しません。それぞれが自分の中に持った基礎的な道具を持ち寄って、その場でしか使えない「特別な鍵」を作り出す必要があります。基礎力のない応用はありえないのです。

「ありもののライブラリやフレームワーク」を使うのが仕事であると言わざるをえない自分自身の無力と向き合っていた時期であったので、とかく深く心に刺さったのだとおもう。

 その後、 Nand2Tetris とか DDIA を読んだり、競技プログラミングもたしなむようになり、いくらか視野は広がった。しかし一年でこれしか進歩していないとおもうと、もっと頑張れるはずとも思っている。

 仕事では「ありもののライブラリやフレームワーク」を使った仕事をあいかわらずやっているわけで、そこに物足りなさを感じる瞬間がないとはいえない。とはいえ霞を食べながら勉強するだけの覚悟はなかったわけで、そこを嘆いても仕方がない。

 こうして言い訳めいた言葉が出てくるということ自体からして、勉強がしたいという熱情は否定しがたいのだとおもう。知識に投資するのであれば早いに越したことがないのは真理である。

 もう少しお金がたまったら...とか、先延ばしにする理由づけには事欠かないのだが、それではいけないだろうと自分を戒める。大学に再入学するプランを立ててみよう。実際に入学に漕ぎつけられるかどうかは別として(入試をパスできるかどうかすらもわからないのだし!)、どうやって学校選びをして、どうやってその後の進路をデザインするか、まで考えてみよう。考えるだけなら無料であるわけだし、それによってやることがはっきりすれば、いまなにを勉強すべきなのかもよりクリアにみえ始めるはず。

世界に

 世界中を見てまわりたい。一年とすこし前まで、事実そういう生活をしていたことがすっかり遠い過去のことに思える。

f:id:jnsato:20210504171742j:plain
部屋からちょっと歩くだけでこんな名跡を眺められるなんて夢のようだった

 ベルリンにいた僕は COVID-19 がヤバイと聞いて早めに撤退したのだった。あとになってこれは英断だったとよく褒められるし、事実これ以外ありえない決断だったと評価している。とはいえ、ここまでひどいことになるとは思っていなかった。しばらく落ち着いたらふたたび繰り出そうと思っていたところ、国外どころか狭い狭い家の外にすら出られない生活で息がつまりそうだ。

 世界のほんの片隅しか知らない。そうと知りながら、その片隅でぼんやり暮らすのは苦しい。広い世界があると知っているのに、そんなものなどないというふりをして生きていきたくはないし、もっとアクティブに世界を飛び回りたい。それができる職業についているのは幸運である。世界が安全といえるようになったら、いつでもその生活に舵を切れるように準備だけはしておきたい。

 そういう熱い気持ちのことを、このエッセイを読んで思い出したので、忘れないように書いておく。

プログラマが変わっていると思うのは、遠隔地や旅行中でも容易にできる仕事でありながらみんなそうしないということだ。もちろん例外はあるだろうけど、この旅行中に同じようなことをしているプログラマには一度も出会わなかった。残念なことだと思う。プログラマ仲間への僕のメッセージは、言い訳するのをやめて実行しようよ、ということだ。人生一度しかないんだから。素晴らしい体験になるだろうことだけは請け合える。

会社員は会議がおおい

 新入社員になってきょうで丸3ヶ月となる。入社の折に書いたエントリを読み返すと、かなり肩に力がはいってしまっていたことがわかる。よほど自己肯定感が低かったとみえるが、実際働きはじめてみると、まったく問題なく戦力となれている実感があるし、自信を折られて萎縮することなどはまったくない。尊敬に値するチームメイトと一緒にいても、自分には自分の強みと特性があるからと、力強く振る舞えているように思う。

 手を動かして開発をする時間は以前よりもすこし減っている。「すこし」とぼんやりと書いたところで、そういえば rescuetime で活動時間のログをとっていたのだと思い出し、集計してみた。

 それがこれである。ざっくりいうとエディタとか GitHub を触っている時間が development で、ビデオ会議とか Slack をしている時間が communication である。開発時間が減少傾向にあるのは事実のようだが、それよりも目を引くのはコミュニケーションに割かれるようになった時間の急激な増加である。

f:id:jnsato:20210430102714p:plain

 すべての会議がただちに無駄とは言わない。以前の職場においてコミュニケーションが少なすぎた、ということも言えるだろう。設計を議論するなどの健全で生産的な会話は前の職場よりも増えているし、それは嬉しく思う。

 ただ、一日の半分がミーティングで埋め尽くされているカレンダーを眺めたりすると「本当にこれがあるべき姿なのか?」とうなだれてしまうのもまた事実である。それが求められる職務であるといえばそれまでなのだが、さみしい気持ちにはなる。

 この3ヶ月は手探りの期間だったので、よくわからない会議にとりあえず呼ばれて置き物になる、みたいなムーブもあったように思う。そしてそのために集中力が散漫になっている直感があったが、この直感は正しかったようだ。

 会議に出るか出ないかは自分で決める、という線で振るまってみよう。それが波風をたてる職場であるとは思わないし、それによって仕事が進まなくなるというのなら、それはおかしくないか? と問題提起しよう。実際、3ヶ月前まではいまの半分未満のコミュニケーション時間で済んでいたのだから、できないことはないはず。

AtCoder のレートが緑色になった

 週末の ABC199 で緑コーダーになれた。29回目のコンテストでの昇格である。

 茶色に昇級したときのエントリを読み返した。これが去年の9月半ばのことであるから、緑色に到達するまでに要したのは7ヶ月ということになる。

 正直に告白すると、この期間アルゴリズムの学習はほとんどしていない。過去問を解くこともほとんどできていない。それに割くだけの時間が作れないのである。ただコンテストにだけは愚直に参加し続けている。毎週末の2時間に集中して解く。解けなかったものはその場で復習して寝る。そういうルーティン化された毎週を送っていただけであるので、昇級したという感慨は思いのほか小さい。

 週末のコンテストにしても、解ける問題を速解きした結果、たまたま高いパフォーマンスが出てしまっただけであって、どうも棚ぼた感はある。たまたま転がり込んできた結果でしかないので、またすぐに陥落するのではないかと思うと無邪気に喜ぶことはできない。

 まあ、およそこのあたりのレーティング帯で長く推移しているので、これが正しく自分の実力というものを表しているのだろう。きちんと勉強と精進を積めばもうすこし成長できると思いつつ、緑色並の実力という自画像に納得してしまっているところもある。もっと高いレベルに立つとなにが見えてくるのかに興味はあるが、あいにくもっと興味のあることが他にある、ともいえる。

 よって、次の目標として水色を目指すと言うことはできない。レーティング1000を目指すともあまり表明する気にならない。いま持てる実力より高い目標を立てても、それに邁進するだけのリソースがないのである。できない目標を掲げることになってしまえば、 atcoder と言うゲームそのものがつまらなくなってしまう。

 そこで僕は目標として、次回からも変わらずコンテストに参加し続けることを目標にしたい。あるいはふたたび茶色に陥落することも十分にありえるが、それでもめげずに毎週2時間だけはこれに集中しきりたい。運動の習慣と同じようなもので、週に1度だけでもしっかり集中してセットをこなすことで、すこしずつ成長できるはず。すくなくとも衰微を遅らせることだけはできるだろう。

 自分が特別な才能の持ち主ではないということを教えてくれたことについて、 AtCoder には感謝しきれない。正直にいって、もっとチョロいゲームだと思っていた。しかし茶色レーティングではやくも足踏みを食らわされたことで、自分がいかに凡庸であるかを知ることができた。もちろんその事実と向き合い、受け入れることには痛みを伴ったし、おおきな時間もかかった。でも最終的にはこの試練を通して、僕はつまらない自尊心を克服して、小さな人間として一皮むけることができたと思っている。そしてそれはプログラミングスキルよりもずっとおおきな収穫だ。

 いまからトップティアを目指すわけでもあるまいし、競争的結果に一喜一憂するよりも、生涯のアマチュアとして、楽しく参加すること。そうして人生を豊かにすること。それくらいの気持ちで細々と付き合っていくことができればじゅうぶん幸せといえるだろう。将棋や囲碁の愛好者がいるように、僕は競技プログラミングの愛好者として楽しむ。いまはそれでいいと思っている。

分散データベースのレプリケーション: Designing Data-Intensive Applications 第5章より

 ネットワーク越しにつながった複数のマシンに、同じデータのレプリカを作成して保存する。「ネットワーク越しに」というのが難しいところで、ネットワーク障害が起きたり、コピー先のマシンが死んでしまったり(ネットワーク越しに生死を確認するというのもまた難しい問題になる)、データセンターが核攻撃されて消滅してしまうまで、あらゆる問題は現実に起こりうる。もし明日、太陽が急膨張して地球を飲み込んで人類の遺産が根こそぎ蒸発するのであればデータの行方がどうなろうと知ったことではない。しかしそうでもなければ有事に備えてデータの完全なレプリカを保持することが要請されるだろう。

 これは分散データベースの問題である。レプリケーションにまつわる議論は70年代から存在していたものの、現実に分散データベースが構築されるようになったのは比較的近年のこととなる。主流の考え方は次の三つといえよう。

  1. 単一リーダーレプリケーション
  2. 複数リーダーレプリケーション
  3. リーダーレスレプリケーション

 これらの分類に加えて、さらに考慮すべきトレードオフが存在する。「結果整合性」というコンセプトも関わってくる。そうした最低限の知識のイントロダクションとして、数回にわたって一連のノートを書く。個別のトピックは独立した記事にまとめることにして、以下のセクションにはインデックスとしてリンクをおいていくことにする。

 ノートの参照元DDIA である。完全な翻訳を掲載する権利も意思ももとよりなく、あくまで個人による要約である。同書を読んでいるひとはこれらを読む必要はないし、そうでない人にとっても、正確な情報としては正式な翻訳を参照いただくのが好ましい。

単一リーダーレプリケーション

 複数のノードのうち任意の一台をリーダーとして選出して、リーダーノードがすべての書き込みを受け付ける。残りのノードはリードレプリカとして、読み込みリクエストのみを受け付ける。フォロワーはリーダーからレプリケーションログを介して変更差分の通知を受け取る。レプリケーションログに沿って、リーダーログの書き込み履歴を完全に再現して実行し直すことで、データの複製を構築する。

 任意の一台が排他的に書き込みを受け付け、書き込みログをリードレプリカに伝播させる。この方式はもっともシンプルで代表的なレプリケーション方式である。主要な RDBMS はこのレプリケーション方式をサポートしているし、 MongoDB や RethinkDB といった NoSQL 製品から Apache Kafka や Rabbit MQ といったメッセージブローカーまで、採用例は多い。

複数リーダーレプリケーション

 基本的には単一リーダーレプリケーションボトルネックを解消する目的で提案されるレプリケーション方式であると言える。この設定下においては、クラスタ内の複数のノードがリーダーとして書き込みを受け付けることが可能であり、それと同時にリーダー間で非同期にレプリケーションを行うこととなる。

 結論として、複数リーダーレプリケーションは発展途上のパラダイムであり、安直な技術選択によって導入できる類のものではない。実用としては避けるのが望ましい。

リーダーレスレプリケーション

 リーダーだけが書き込みを受け付けるという点において、単一リーダーレプリケーションと複数リーダーレプリケーションは同じパラダイムに属しているといえよう。対して、リーダーという地位を廃止してレプリカが自身の裁量で自由に書き込みを実行するリーダーレスモデルというものがある。分散ストレージ研究の歴史においては根強い伝統を伴ったコンセプトであるものの、リレーショナルデータベースの時代には忘れられかけた技術であった。

 Amazon の DynamoDB がその状況を突破し、新しい風を吹き込んだ。 Riak, Cassandra, Voldemort といった製品が後に続いたことで、リーダレスレプリケーションというモデルが再び日の目を浴びるようになった。というと素晴らしい話のように聞こえるが、もちろん新しい毒も伴うことになる。設計の違いはデータベースの使われ方にも本質的な転換をもたらした。

並行書き込みを検知する

 リーダーレスデータベースは書き込み時コンフリクトに対してひどく脆弱である。クオラムが満たされていても並行書き込みによるコンフリクトは起こりうるし、リードリペアの際にもコンフリクトしうる。さらには書き込み可用性を高めるためにクオラムをぞんざいに扱うというオプションも存在し、こうなると書き込み結果の不整合はどうしようもなく拡大する。

なにをもって並行とするかは認識論的にしか定義しえない

 並行とはそもそもなにか。任意のふたつのリクエストについて、客観的な立場からそれらが並行しているか直列であるかを言い当てることは原理的に不可能である。リクエストを発する主体が、異なる処理の結果を知った上で書き込みをおこなえばそれは直列であるし、知らずに書き込みをおこなえばそれは並行することになる。つまり認識の位相の問題であるわけである。

 こう言い換えることもできる。すなわち並行性とは時間によって定義されるものではない。物理的思考においてこれは正しいが、計算機的思考においてこれは成立しない。なぜならネットワークは無制限に遅延するものであるため、リクエストが送信した時刻やリクエストが処理された時刻を点として観察することにはなんの意味もないためである。

 その上で、並行関係を補足するためのアルゴリズムを考えてみよう。

並行関係を補足するためのアルゴリズム

 簡単のためにレプリカがひとつしかないとする。例えば、リクエストとレスポンスにバージョン番号を含めることで、「クライアントはどこまで知っているか?」を追跡することができるようにできる。

 これにより、書き込みリクエストとして送信されたデータを消失させてしまうことは常に避けられるようになる。その一方で、ひとつのバージョンに複数の値が含まれることが起こりえ、それをマージする必要も生じる。競合する値を union して返すのがもっともシンプルな実装になるが、その場合でも削除操作をどう記録するかを考慮する必要はある。削除フラグ( tombstone )を含めて union できるようなアルゴリズムを用意するのがよいだろう。

 この考え方を複数レプリカ間でのコンフリクト解消に拡張してみよう。同じようにデータのバージョン番号をリクエストとレスポンスに含めてやりとりする方針は有効である。ただしバージョン番号はレプリカごとに割り振られるものとして管理しなければならない。言い換えると、レプリカごとにバージョン管理ができていれば、あるノードから読み込んだ値を別のノードに書き込んだとしても、データの損失は発生しないということになる。この仕組みのことをバージョンベクターという1