帰省
昔、僕の実家はもっと土地を持っていたんだと父が言っていた。
僕の実家はそれなりに歴史のある家系らしく、地方の小さな地主のような立場だった時代があったのだと思う。今でこそ富裕層と呼べるほどの資産があるわけではないが、曾祖父のさらに上の代あたりでは、今で言うところの地域の世話役、あるいは村長のような役割を担っていたらしい。
地元の神社や寺が財政難に陥った際、田んぼを寄付したこともあったと聞いている。細かい話は口伝の中で失われてしまっていそうだが、名前が記録に残っている先祖もいるらしい。実家の近くの神社には、そのことを示す石碑が立っていた。
19世紀の日本では、制度としては金・銀・銭が通貨だったが、慢性的な貨幣不足に悩まされていた時代でもある。現金よりも、安定して価値を生み続ける農地の方が、よほど信用できる資産だったのだろう。田んぼを寄進したという事実が石碑として残っているのを見ると、当時の価値観が垣間見れて面白い。
また、当時の貨幣制度については、日本の貨幣紙を眺めると雰囲気が掴みやすい。
祖父はかなり博識で、地元の歴史にも詳しかった。生きているうちに、もっといろいろ聞いておけばよかったなと、今になって思う。亡くなる直前まで認知症になることもなく、ともすれば当時の自分よりも記憶力がよく、細かい出来事までよく覚えていた。
大学院に進学することを伝えたとき、心から喜んでくれたのを覚えている。けれど、もう6年前に亡くなってしまった。当時の僕は大学生で、勉強や遊びに夢中だった。地元にはそれなりに帰ってはいたものの、自分の将来のことで手一杯だった。
この歳になると、いろいろなことに余裕が出てくる。同年代には結婚や子育てをしている人も珍しくないし、仕事も目の前のタスクであればある程度こなせるようになる。抽象度の高い話や、物事を俯瞰して考えることができるようになって、若い頃の余裕のなさを振り返っては少し恥ずかしくなる。
一方で、今もなお見えていないことはきっとたくさんあるのだろう。5年前の自分は、いつだって子供に見える。
話を実家のことに戻そう。
父の話では、ある時代に土地を没収されたことがあったらしい。父はそれを「日本が社会主義だった時代」と表現していたが、自分の知識が正しければ、日本が社会主義国家だった時代はない。
ただ、戦前や戦時中には全体主義的な空気が社会を覆っていたはずだし、政策もそれに近い形で進められていた。あるいは、戦後のGHQ占領期に行われた農地改革によって農地を手放すことになった、という話なのかもしれない。可能性が高いのは後者かな。
今となっては、正確なところはわからない。わからないことがわからなかった自分の過ちを、ただ恥じるばかりである。父に聞いても「じいちゃんに聞いておけばよかったなぁ」と、同じ後悔を口にするだけだ。
「無知の知」を唱えたのはソクラテスだっただろうか。「自分は知らないということを知っている」という態度は、正直なところ、かなり鼻につく人物だっただろうなとは思う。(実際、ソクラテスの弁明を読んだ時はイライラして途中で読むのをやめてしまった)
けれど、教養が大事だというのもまた事実だ。無知であることは損をするし、無知であるがゆえに取り返しのつかないことをしてしまうこともある。僕には、まだまだ教養が足りない。
年末に書いたブログは、仕事を主題にしたものだった。
https://mimatasanmata.hatenablog.com/entry/2025/12/31/173012
人生は仕事だけではない。お金を稼ぐこと以外にも、素晴らしいことはたくさんある。教養があれば見える世界は広がるし、幸せのあり方を自分で選び取れるようになる――ような気がする。しらんけど。
東京で暮らしていると、とにかくお金がかかる。特に住居費だ。子育てを考えると3LDKに住みたくなるが、今住んでいる街で新築の3LDKを用意しようとすると、なかなかの金額になる。買うなら資産性を考えた上での戦略的な中古だろう、という判断になる。不動産の話をし始めるといろいろあるが、自分は購入派だ。
本気で50年ローンを組むことも視野に入れているし、資産の最大化やインフレへのリスクヘッジを考えると……と、この辺でやめておこう。書き始めると、どうしても数字の話ばかりになってしまう。
お金のことを考える時間は多い。資産運用と向き合うのは楽しいし、豊かさでもある。ただ、金のことばかり考える人生は、それはそれで少し嫌だな、とも思う。
「暮らしのことを考える → お金のことを考える → 仕事に向き合う」
自分の人生は、だいたいこの力学で動いているように感じる。これらと向き合うことは大事だが、それ以外にも大切なものはあるはずだ。自分のルーツが失われてしまっているように、気づかないうちに見落としてしまうものがある。
今になって後悔しても遅い。今を生きる自分が世界を見るとき、その見え方を形作るのが教養なのだと思う。仕事やお金に関する知識だけではなく、もっと幅広い分野の知識を取り入れていきたい。
大学生の頃の自分は、今思えばかなり立派だった。目的もなく、さまざまな分野の本を多読・乱読していた。「目的を持って読書をしろ」という言説もあるが、それは「わからないことが何かわかっているとき」にしか有効ではない。
わからないことが、わからない。そんな状況はよくある。ソフトウェア開発の文脈では Unknown Unknowns という言葉があるが、人生もまた、そんなことばかりだ。知らないことに気づかせてくれるものを、大切にしたい。
今年は、仕事やお金に直結するものだけでなく、人生を豊かにしてくれる本をたくさん読む年にしたい。
文筆:毎年内省しては三日坊主になってしまう三股
2025年の振り返り
2025年、年末にして1本目のブログ投稿になります。あまりにも怠惰すぎる。
今年はキャリアの中で環境変化が激しい1年だった。新卒から担当した事業のクローズ、部署異動、そして再度の異動(実質的な転職)。
院卒4年目、28歳。30歳も目前に迫る一人の社会人として、何を考えどう動いたのかを整理しておく。
新規事業のクローズ
8月、新卒から3年間開発してきたクイックコマース事業がクローズした。昨年はピボットもあり、新規サービスの設計・ローンチも経験できたため、エンジニアとしては濃密な時間だった。
「巨大なサービスの裏側を知りたい」という動機でこの会社を選んだ。ベンチャーでは経験できないスケール感や資本力、その負荷に耐えうる設計スキルを求めていた。 配属先は立ち上げ直後の新規事業だったため、当初の志向とは異なっていたが、結果としてこれは得難い経験となった。
特に印象的だったのは、大企業のアセット活用だ。通常、ECを一から立ち上げるには決済や商品、在庫管理、検索、販促基盤、etc...など複雑かつ膨大な機能が必要だが、社内には既に巨大なEC基盤があり、それらをPlatformとして利用する設計になっていた。「車輪の再発明」を避け、既存資産を使ってビジネスを作る構造を肌で感じられたのは大きかった。
ピボット後には、Apache Pulsarを用いた大規模MQで流量制御を行うシステムを構築し、サービスローンチのための負荷試験もリードした。これらが大きな障害なく稼働し、サービス終了まで運用しきれたことは、エンジニアとしての自信になった。
異動
事業クローズに伴い、10月から別のサービスへチームごと異動した。歴史ある大きなサービスで、トラフィックも凄まじい。大規模トラフィックに触れられることを期待していたが、そこで待っていたのは組織的な課題だった。(生々しい話が聞きたい人は飲みにでもさそってください)
ここで「自分は何を積み上げられるのか」を考えた。文句を言うのは簡単だし、時間をかけて改善に取り組む道もある。だが、自分にはコントロール不能な変数でパフォーマンスが抑制される感覚が強く、20代後半の重要な時期をこの調整に費やすことへのリスクを感じた。
転職
この時期、社外の友人やエージェントから声をかけてもらい、転職も真剣に検討した。年収を上げるなら外に出る選択肢もあったと思う。最終的に選んだのは社内公募を利用したLINE公式アカウントのバックエンド開発組織への異動だった。
合併したとはいえ、まだまだ文化も技術スタックも異なるため、実質的な転職に近い。ここを選んだ理由は「技術的な深さ」だった。新卒入社時の動機であった「大規模トラフィックを捌く」という経験が得られるポジションが、ちょうどまさに目の前に現れた。
技術とビジネスの接続
LLMの登場で越境の敷居は劇的に下がったように思う。簡単なスクリプトならプログラミング未経験者でも簡単に書ける時代だ。マーケターや営業職が業務効率化のChrome拡張を自作する事例も珍しくない。(保守運用やセキュリティ的な課題が出てくるのではないかという懸念はあるが、それでもできることは劇的に増えている事実に変わりはない)
自分の身の回りでもエンジニアに現状の仕様を聞いていた同僚が、ClineやClaude Codeを使ってGithubのリポジトリを解析し、仕様を自分でキャッチアップするようになっている。
「技術」という聖域は、もはやエンジニアだけのものではない。 では、自分はどうだろう?専門性にあぐらをかいて、自分たちの領域に閉じこもってはいないだろうか。
LLMの登場以前から「スペシャリストかジェネラリストか」というキャリア論は語られてきた。技術だけに目を向けていたいという逃げの選択としてスペシャリストに憧れてしまう自分がどうしてもいる。それはビジネス、組織の複雑さからの逃避なのだと思う。スペシャリストとして生きている人はそんな逃げの姿勢できっと生きていない。
技術のコモディティ化が進む今、得意でないことから逃げていてはエンジニアとしての成長はあと数年で止まるだろう。
「仕事を前に進めるためならなんでもやる」
その覚悟を持てるかどうかが自分の分水嶺だと感じている。
次の環境では、技術的な深さを追求するのは大前提ではある。だが、そこで終わらずチームリードやより抽象度の高い課題解決にも踏み込んでいきたい。2025年は悩みの多い年だったが、ようやく視界が開けた感覚がある。新しい環境でも泥臭くやっていこうと思う。
DynamoDBの論文を読んだ
DynamoDBを開発で使う機会があったので、DynamoDBの論文を読みました。1 今回読んだ論文は2007年に書かれたものです。2022年にどう発展したのかの論文が出たのでそちらも読みたいですね。
2007年の論文:https://www.amazon.science/publications/dynamo-amazons-highly-available-key-value-store
2022年版の論文URL:https://www.usenix.org/system/files/atc22-elhemali.pdf
1. ざっくりまとめ
箇条書きで3点
- amazon DynamoDBの論文
- 既存技術の組み合わせで作られている
- コンシステントハッシュ法によるパーティショニング
- オブジェクトのバージョニングによる一貫性の提供
- クオラム書き込みによる一貫性の提供
- ゴシップベースの分散障害検出
- always writable!
2. 背景
ビジネス的な背景が以下のように述べられています。
ビジネス的な背景
- Amazon.comは数百のマイクロサービスの集合体
- 各サービス状態を管理していることが多い。
- 状態管理に関して、主キーでアクセスして状態を読み書きするものがほとんどで、複雑なデータ構造はあまり必要ないことが大半
- RDBMSでスケーラビリティを確保するのは構築・運用コストが高い
システムの前提となる制約
これを受けて、dynamoは以下を前提としてシステムを構築しました。
- 単純なクエリモデル。リレーショナルな何かは提供しない。
- joinとかはできないってことかと。状態管理をしてるシステムはpartition keyでアクセスすれば十分って背景と合ってますね。
- ACID特性の緩和
- Iは補償しない
- 効率性
- 高価なマシンとかじゃなく、普通のハードウェアで頑張る。99.9%ileのlatency補償がSLAとしてあるので、ここを満たす。
- その他の制約
- 社内のアクセス限定。認証認可は頑張らない。
- 数百くらいまでのスケーラビリティを想定
レプリケーションと一貫性についての前提
その他にもシステムを設計する上での重要な事項が述べられています。データのレプリケーションと、競合の解決についてです。よくあるレプリケーションプロトコルは同期的に動作し、書き込みの際にレプリカ間のデータの一貫性を保証します。読み取り時の複雑性を下げるためです。一方で、dynamoは読み取りの際に一貫性をサポートするモデルを採用しています。カートに商品を追加するときに失敗したりとかはUXとして望ましくないので、always writebleを標榜しています。ここがこの論文の面白いポイントな気がします。
以下、引用です。
An important design consideration is to decide when to perform the process of resolving update conflicts, i.e., whether conflicts should be resolved during reads or writes. Many traditional data stores execute conflict resolution during writes and keep the read complexity simple [7]. In such systems, writes may be rejected if the data store cannot reach all (or a majority of) the replicas at a given time. On the other hand, Dynamo targets the design space of an “always writeable” data store (i.e., a data store that is highly available for writes). For a number of Amazon services, rejecting customer updates could result in a poor customer experience. For instance, the shopping cart service must allow customers to add and remove items from their shopping cart even amidst network and server failures. This requirement forces us to push the complexity of conflict resolution to the reads in order to ensure that writes are never rejected.
また、読み取りの際に解決するなら、どこで解決するかという話も展開されています。Database側で保証する場合はlast write winを採用しますし、そうでない場合はapp側で競合を解決することも提案しています。データスキーマによっては確かにapp側で判断できることもある…んですかね。
3. 関連研究
関連研究として挙げられているのは以下でした
- P2P
- 分散ファイルシステム・分散Database
分散ファイルシステムの先行研究として、GoogleのGFSやBigtableなどの有名なものも含まれていました。これらとの差分について論文の中では以下の4点を挙げています。
「常に書き込み可能」なデータストア
上で述べた通り
単一管理ドメイン内での運用
すべてのノードが信頼される前提
ファイルシステムで標準的とされる階層的名前空間や、従来のデータベースが提供する複雑なリレーショナルスキーマを必要としない
厳しいレイテンシ要件
99.9%ileで数百msのlatency要件があります。このSLAを達成するために、ルーティングを実行する際にマルチホップは採用してないとのことです。各ノードがルーティング情報を保持することでzero-hopを実現するんだとかなんとか。
4. 設計
データベースを支える技術を取り上げるとトピックは多岐に渡ります。以下、挙げられてる項目です。
- 負荷分散
- メンバーシップと障害検出
- 障害回復
- レプリカ同期
- 過負荷対応
- 状態転送
- 並行性とジョブスケジューリング
- リクエストのマーシャリング
- リクエストルーティング
- システムの監視とアラーム設定
- 構成管理
多すぎてフルペーパーでも流石に尺が足りんので以下に絞って触れられています。
- パーティショニング
- レプリケーション
- バージョニング
- メンバーシップ管理
- 障害対応
- スケーリング
各種課題に対してどのようなアプローチをとっているのかが論文中で表にまとめられていたので引用します。

4.1 システムインターフェース
Dynamoのインターフェースは、シンプルな2つの操作で構成されています。
get(key):キーに関連付けられたオブジェクトを取得し、競合する複数のバージョンがある場合にはそれらのリストとコンテキストを返す。put(key, context, object):キーに基づいてオブジェクトのレプリカを適切なストレージノードに配置し、保存する。
4.2 パーティショニング
コンシステントハッシュ法を採用していることを紹介しています。コンシステント法を拡張して仮想ノードを割り当てることをやったよって書いててびっくりしました。この時ってまだ仮想ノードの概念なかったんですね。めっちゃわかりやすいブログを日本語で書いてくださってる方がいらっしゃるのでリンクを貼っときます。
https://christina04.hatenablog.com/entry/consistent-hashing
4.3 レプリケーション
可用性と永続性を保証するためにN個のホストへレプリケーションします。コーディネータというあるキーに対してのメインの処理担当がいて、書き込みの一時受けを担当します。自身に書き込みするだけだと可用性を担保できないので、残りのN-1個のレプリカに対しても書き込みを要求するリクエストを送信します。以下のようなイメージ。
- クライアントがキー
kを使ってデータを書き込みリクエストを送信。 - Dynamoはキー
kのハッシュを計算し、リング上の該当ノード(コーディネータ)を特定 - コーディネータはリクエストを受け付け、自分自身にデータを書き込む
- コーディネータは、時計回りに続く N-1個のレプリカノード にデータを伝播させ、これらのノードもデータを書き込む
4.4 データバージョニング / ベクタクロック
dynamoでは結果整合性が採用されていて、書き込み時に保証するモデルでないことは何度も言及されてきました。そこで読み取り時に複数のバージョンを返却するアイデアが実装されています。
ベクタクロック
データのバージョン管理に使うリストで、各ノードが「どのノードが何回データを更新したか」を記録します。
因果関係の判断
ベクタクロックを比較することで、2つのバージョンが因果関係にあるか、競合しているかを判定可能。以下の図で言うと、ベクタクロック D3とD4ではベクタクロックが一致してないことがわかります。( = 競合の検知)
統合(リコンシリエーション)
競合した複数のバージョンをクライアントが統合し、新しいバージョンを作成。

4.5 getとputの実行
障害が起きてない環境でのgetとputの実行方法について紹介されてます。
getとputを送信する方法は2つある
- load balancerが受け付けてnodeを決定する
- clientライブラリ側でルーティングを決めてリクエストを送る
ルーティング
読み書き操作を処理するノードは「コーディネータ」と呼ばれます。リクエストがロードバランサを介して送信される場合、キーにアクセスするリクエストはリング内の任意のノードにルーティングされます。仮にリクエストを受け取ったノードが不適切だった場合はルーティングテーブル的なものから適切なノードにリクエストを転送。
一貫性
クオラム読み書きの話が出てます。
- R: 読み取り操作が成功するために必要なノードの最小数。
- W: 書き込み操作が成功するために必要なノードの最小数。
- N: データのレプリカ数
R + W > N となるように設定すると一貫性が担保されますが、dynamoDBではlatency制約がきついのでR + W < Nになってるらしい
4.6 エラーハンドリング / sloppy quorumとhinted handoff
sloppy quorum
従来のクオラムアプローチを採用すると可用性が下がりかねない(?)ので、sloppy quorumを採用してるらしい。リクエストを送信する際に厳密にこのノードから読み取ると事前に決めるわけではなく、正常な上位n nodeからレスポンスが返ってきたらokってもの。 そもそも従来型のクオラムって厳密にnode特定して読み書きしてるのか?当時の一般的な実装では障害があったら動的にルーティングしてたりしなかったのかな。
hinted handoff
ノードAがdownしているときに書き込みが到達不能になったとします。この場合、sloppy quorumモデルでは変わりのノードDにリクエストを転送し、ノードDでは「ノードAに書き込まれる予定だった書き込み」であることをヒントとして残した上でlocalに保存します。ノードAが復旧したことを検知すると、本来ノードAに保存するべきだったリクエストの転送を試みます。ノードAに無事レプリカが書き込めたら、ノードD上からはデータを消去します。
この一連の仕組みをhinted handoffと呼ぶようです。システム全体でレプリカ数を減らすことなくデータを維持でき、ちょっとした障害程度であれば書き込みが失敗することはありません。
4.7 永続的な障害への対応 / レプリカ同期
hinted handoffはノードのメンバーシップに変化が少なく、障害が一時的な場合はうまく動作します。しかし、hited handoffが元のレプリカノードに戻される前に利用不能になるケースもあります。つまり一時的な障害以上の問題が出てきたらどうするの?という問いですね。
この課題を解決するためにアンチエントロピープロトコルというものを実装し、レプリカ間の同期を維持する話が書かれてます。要するにバックグラウンドで異常がないかを定期的にパトロールして、問題があったら同期を取る仕組みのようです。マークルツリーを活用して効率的に同期が必要なキーを特定し、必要であれば同期を行います。
4.8 メンバーシップと障害検出
コンシステントハッシュにおけるノードの追加・削除やリバランスについての話題です。ちょっとした障害くらいでリバランスとかが起きると面倒なので、メンバーシップの変更は手動で行なっているようです。コマンドライン、またはWebUIから操作すると記述があります。
メンバーシップの変更はゴシッププロトコルを通じて伝播されメンバーシップの一貫性も保たれるようになっているとのことです。各ノードは1秒ごとにランダムに選ばれたピアノードと通信し履歴を同期しているらしい。
4.9 ノードの追加と削除
コンシステントハッシュ法に基づいた仕組みについて書かれています。より詳細に紹介されていますが割愛。
5. 実装
実装はJavaで書かれてるらしいです。それからstorage engineについても言及がありました。プラグイン形式で特定のエンジンに依存してるわけではなく、いくつか利用可能なオプションがあるようです。
Storage Engine
- MySQL
- Berkeley Database (BDB)
アクセスパターンに応じて何使うかは決めてるらしい。大抵の場合はBDBらしい。RDBだとスケールしないから分散DBを作ったって文脈で、各ノードで動くものはMySQLの場合もあるって言うのがちょっと驚きでした。
書き込み負荷分散
- プレファレンスリスト内の複数ノードで書き込み調整を可能にし、負荷の偏りを軽減。
- 読み取り直後の書き込みに最適化された設計により、性能と一貫性を向上。
6. 実験
dynamoDBの設定や構成によって整合性の復旧アプローチやクオラム特性に違いが出てきます。
ビジネスロジック側で判断し復旧させるアプローチ
popularらしい
timestampで判断 / last write win
顧客のセッション管理とかはこれらしい
ハイパフォーマンスな読み取りエンジン
readが大半でwriteがほとんどない場合、Rを1にして超高速にresponseを返す
クオラムの設定例
クオラムの一般論が記述されてます。
典型的な設定例:
N=3: オブジェクトの耐久性を確保。R=2、W=2: 一貫性、可用性、耐久性のバランスを実現。
6.1 パフォーマンスと 耐久性のトレードオフ
タイトルの通り。基本的にはSLAは99.9%ileで300msらしいが、さらにパフォーマンスをあげる必要がある場合は耐久性を落とす設定をしてたりするらしいです。
図4の説明をしている節
6.2 負荷分散
小ンシステントハッシュ法を利用してるのでキーの数が一定以上あればリクエストは分散されます。特定キーへのアクセスが集中するホットキーが存在しても、それが複数存在してれば同様の論理でリクエストは分散される。
どのくらい分散してるかを調査した実験結果がまとめられています。長い。
負荷不均衡の測定
- 各ノードが受け取るリクエスト数を24時間にわたり計測し、30分間隔で分析。
- 負荷分散効率の定義: 各ノードの平均リクエスト数を最も多くリクエストを処理したノードのリクエスト数で割った値。
- ノードが平均負荷から15%以内に収まる場合は「均衡状態」とみなし、それを超える場合は「不均衡状態」とみなします。
- ノード数 S=30 / レプリカ数 N = 3
3つのストラテジー
3パターンのパーティショニング戦略で実験を行い、それぞれの結果をまとめています。
結果
- 負荷が低い場合、不均衡比率は最大20%。
- 負荷が高い場合、不均衡比率は10%以下。
- 負荷が高いと、多くのホットキーがアクセスされるため、キー分布の均等性により負荷が均一化。
6.3 バージョン分岐の発生数
dynamoは一貫性を犠牲にしてるので複数のバージョンがレスポンスとして返ってくることがある。ベクタクロックの話ですね。実験ではどのくらいの数発生したのかをまとめてくれてます。以下は結果
- 99.94% のリクエストでは、1つのバージョンしか返されない。
- 0.00057% のリクエストで2つのバージョンが返される。
- 0.00047% のリクエストで3つのバージョンが返される。
- 0.00009% のリクエストで4つのバージョンが返される。
6.4 クライアントサイドとサーバサイドのコーディネーション
stateマシンでリクエストをどのnodeが処理するか決めてる話があります。サーバーサイドで決めるアプローチもあればクライアント側でstate machineを持つこともできます。client側でstate machine、つまりルーティングテーブルを持った場合はロードバランサーが不要という利点があります。ただし情報が古いと最新化の必要が出てくる欠点も存在します。論文の中では10sに一回ルーティングテーブルが更新されていると述べられています。
どっちが早いかで言うと、当然クライアントサイド側で持った方が早く、99.9%ileで30msの改善があるようです。
6.5 バックグラウンドとフォアグラウンドのタスク
put/get操作(フォアグラウンドタスク)に加えて加えてレプリカの同期などのバックグラウンドタスクもあり、バックグラウンドタスクの影響でput/getのパフォーマンス問題があったらしく、それをアドミッションコントローラという仕組みで解決したと述べられています。
感想
久しぶりに論文読んだのでめっちゃ体力吸われました。always writableな設計思想が肝になっており大変読み応えのある論文でした。コンシステントハッシュ法やクオラムに関してはデータ指向アプリケーションデザインを通読していたので事前に知識があったため、ちょっと助かりました。ベクタクロックやsloppy quorumやhinted handoffは初めて知った概念で、理解に時間がかかったなぁという感想。
次に読む論文
2022年版の論文URL:https://www.usenix.org/system/files/atc22-elhemali.pdf
賃貸 vs 持ち家論争
ずいぶん前回の投稿から時間が空きました。それなりに元気にしてます。
今回のブログのテーマは家についてです。家について書こうと思ったのは京葉銀行が50年ローンの提供を開始するというニュースを見たからです。
センセーショナルな見出しでXでも話題沸騰です。自分の中で賃貸に住み続けるべきなのかローンを組んで家をかった方がいいのか、意見がまとまりきってないのですが、この際ちゃんと勉強してみよう、となった次第です。
不動産屋の営業トーク
よくある不動産購入を勧めてくる営業マンの言い分はこう。
- 賃貸で払う家賃は基本的に掛け捨てである。
- 家賃20万円の家に35年間住んだ場合、単純計算で合計で8400万円払うことになるが、これは返ってこない
- 一方、住宅ローンを組んで月々20万円返済していった場合金利を除いた分の金額は資産として積み立てることになる。8000万円の家をかって35年後にローン返済が終われば、家が資産として残る。(金利0.4% / 返済期間35年だと大体8000万円の融資で20.4万の返済になる)
- よって住宅ローン返済は積立と捉えることができるので家は買った方が良い。
- さらに60歳以降は定職がないので賃貸を借り続けることも難しくなる。一方持ち家を持っておけば終の棲家を得られる。
というもの。
- 金利0.4%は変動金利の利率。固定金利と比較して、変動金利はどの程度のリスクがあるか
- 築年数がたった物件の価値は当然下がる。不動産価格はどの程度落ちるものなのか
- マンションの場合は修繕費積立金があるはず。これは見積もりに入ってないのではないか?
- 固定資産税はどうなのか?
- その他諸経費は?
あたりが気になってたポイントでした。不動産Gメンの滝島さんという有名な方がいらっしゃいますが、この方は「金持ちになりたいなら家は買うな」とまで言ってます。どっちが正しいのでしょうか。
動画で語られてる内容はどれも理解できるものです。細かいところだとエアコンの交換とか賃貸だったらタダでやってくれたりするのはありがたいですよね。 賃貸に現状住んでる自分としては、現状を肯定された気になってつい賃貸の方がお得だ、という意見を聞き入れたくなってしまってたのですが、反対意見も取り入れてより強固な論理を自分の中に持ちたいと思い書籍を買いました。
金利が上がっても、 住宅ローンは「変動」で借りなさい
大変学びのある書籍でした。
- 変動金利が多少上がったとしても、できるだけ長期間(35年、できることなら50年)のローンを変動金利で組む姿勢を変える必要はない
- 住宅ローン減税の0.7%は変動金利の利率0.2 - 0.4%よりそもそも高い。金を借りると利子以上の税金が戻ってくるので借りるだけ得。
- 団信は効率のいい生命保険
- 頭金を用意したり、繰上げ返済をすることは資本効率を悪化させるだけで意味がない。
- 与信が最大になるのは40歳前後だが、賃貸は家賃の掛け捨てであり資本効率が悪いため、早め早めに家を買うべき。
- 年収の5倍 - 7倍が無理なく返済できる金額である。8倍はギリギリ。
- デフレからインフレへの転換をすることを考えると不動産を含めたあらゆるものの価格は上がる。逆にインフレ経済下ではローンで借り入れた金額の実質的な価値が下がることになるのであんま怖がらなくて良い。逆にデフレ、高金利な環境下ではリスクが上がるので注意すること。
感想
今自分は都心に住んでいて結構な家賃を毎月払ってるが、これで本当にいいのか、次引っ越す時は購入を検討すべきなのか否か、などのモヤモヤがあったのですが、最近見通しがクリアになってきました。ちょっと前は賃貸推奨派の意見の論理を聞きつつ賃貸に住み続けてる現状を肯定しようと思ってたのですが、逆の意見にも触れてフラットに物事を見ようと努めてみました。
買った方が資本効率いいじゃんとなりつつあるのですが、賃貸のメリットとかももうちょっと冷静に分析しようと思います。
諸々の事情で引っ越しは2-3年後、30手前でしようと思ってるのですが、それまでにリテラシーを高めつつ、本業の年収をできるだけあげたり、副業収入を安定させ与信にプラス評価を与える要素を複数用意しようと思います。
実際に家を購入するべきなのか、それとも賃貸のままでいるのかは3年後の自分に任せるとして、買おうとなった時に困らないよう目の前の仕事に誠実に取り組みます。
読書メモ:システム設計の面接試験②
この記事の続き
目次
6章:キーバリューストアの設計
正直かなり微妙な章でした。RedisやCassandraなどの内部設計が頭に入ってれば読みとばして良い気がしました。
- 日本語訳が微妙
- CAP定理などの微妙な定理をいまだに利用して分散システムを考える
前者は内容というより訳者の問題でしょうか。和訳だと「結果整合性」と訳すべきであろうところを「最終的な一貫性」と訳してる部分があって、一般的に利用されている訳語があるならそっちを使うべきかなと…
後半は内容的な話です。この本は分散システムに関しての書籍ではないので分散システムの解説に多くの書面を割く必要はないのだとは思いますが、やっぱこの紙面だと微妙な内容にならざるを得ないのかなと感じました。
出てくるトピック
- CAP定理
- クオラムの話
- ハートビートの話
- SSTable(ほぼ単語が出てくるだけ)
この辺の話は分散システムの非常に奥深い話が入ってくる部分で、真面目に勉強するならデータ指向アプリケーションデザインを読むのがよさそうだと感じました。
7章:分散システムにおけるユニークIDジェネレータの設計
DatabaseのPrimary Keyをどう作るのか?と読み替えてよさそうな章です。短い章。紹介されてるアプローチは以下の4つ。
マルチマスタ
1点目に関して、なんかこれマルチマスターっていって紹介していいんだっけ?となりました…(実装によって違うという認識を自分は持っているので)この書籍の中で紹介されていたのは、offsetを利用するアプローチです。
- nodeは2つ
- node1が奇数番、node2が偶数番を採番する
- 1, 3, 5, 7….
- 2, 4, 6, 8…
- (ここは書かれてないが)ラウンドロビンでリクエストがバランスされるので、ええ感じにrecordが生成されまっせ、というものかと
このアプローチ以外にも1 - 10000, 2 - 20000…といった具合にsegmentを分割してあげる、みたいなこともマルチマスターでは採用されてたりします。自分が調べた限りだと、PostgreSQL-BDRではこのアプローチを使ってマルチマスタでシーケンスを生成しています。
PostgreSQL BDR (Bi-Directional Replication) を使ってみた - Qiita
uuid
よくあるやつ。割愛。
チケットサーバ
中央サーバとして連番を返すやつを用意する。単一障害点になるのがneck。
twitterのsnowflakeアプローチ
初めて聞きました。timestampとノードのID、シーケンス番号を組み合わせて番号を生成するというものらしいです。
感想
平日で仕事があったのであんま読む時間を確保できず。今週中には読み終えたいです。
読書メモ:システム設計の面接試験①
先日購入した以下の書籍の読書メモです。アフィリンクとかじゃあないです。
https://amzn.asia/d/5AeSGTfamzn.asia
1章:ユーザー数0から数百万人へのスケールアップ
以下のような基本的な内容を扱っています。
- 単一サーバーをホストした際のリクエストの流れ
- データベース
- 垂直スケール / 水平スケール
- ロードバランサ
- データベースのレプリケーション
- キャッシュ
- CDN
- ステートレスとステートフル
- データセンター
- メッセージキュー
- ログ
- データベースのスケール
- シャーディングの話とか
一番最初は非常にシンプルな構成で、Webアプリ、データベース、キャッシュなどの全てが単一のサーバーに置かれてる状況を想定して、どんどんリッチでスケーラビリティを持つ、今っぽい構成に変えていく…って流れで構成された章でした。バックエンドエンジニアなら基本的に抑えてるであろう内容だったりするので自分は流し読みしました。
一番最後にデータベースのシャーディングの話が出ているのですが、セレブ問題(特定のデータにやたらとIOが集中する問題でホットスポットキー問題などの名前がついてるらしい?)など、高度なトピックもちょろっと紹介されていたりしました。
2章:おおまかな見積もり
Googleの超天才エンジニア、ジェフ・ディーンの有名な図を引用しながら見積もりの話が導入されています。
内容的には以下のサイトに載ってるもので、ざっくり各処理にどのくらいのレイテンシが期待されるかを示したものです。
Numbers Every Programmer Should Know By Year
プラスでSLO/SLAの考え方が紹介されてました。
3章:システム設計の面接時のフレームワーク
面接時の心構え的なものを説明しているのがこの章です。似たような内容の話をnoteだかMediumだったかで読んだ覚えがあります。面接官と一緒にディスカッションしながら進めようね、あとこういうふうにしちゃダメだよ、という実践的なことが書かれてる印象でした。
「言うは易し、行うは難し」という印象で、モブ面接的なことをやらないと多分自分は身につかない気がしたので転職する際にここで書かれていたことを気にしながら訓練しないとなぁと感じました。
4章:レートリミッターの設計
Ratelimitのアルゴリズムを紹介する章です。スライディングウィンドウは仕事でも利用したことのあるアルゴリズムだったので知ってましたが、rate limitにいろんなバリエーションがあるなんて知りませんでした。紹介されていたのは以下のアルゴリズムです。
- トークンバケット(Token Bucket)
- リーキーバケット(Leaky Bucket)
- 固定ウィンドウカウンタ(Fixed window counters)
- スライディングウィンドウログ(Sliding window log)
- スライディングウィンドウカウンタ(Sliding window counters)
それぞれ得手不得手があるのでユースケースによって使い分けることが重要。実務上ではAPI Gatewayなどの機能やプラグインとかで実現することが多い気がします。
5章:コンシステントハッシュの設計
この章に関して、自分は以前以下のブログを読んでたので頭に入ってきやすかったです。このブログを読めばこの章で書かれてることは大体理解できる気がします。
Consistent Hashing (コンシステントハッシュ法) - Carpe Diem
シャーディングやパーティショニングといったDatabaseのスケール戦略を考えるにあたり、単純にkeyをhash化したものをサーバーの台数で割ってあげて、どのサーバーに割り当てるのかを計算する、というのが素朴なシャーディングの発想です。以下の数式で表現されるもの。
Nはサーバーの台数で、keyというのがDBに保存されるレコードのイメージです。一見よさそうに思えますが、サーバーをスケールさせたり、障害が発生して台数が減ったりした際、つまりNが変化した際にどのようなことが起こるのかを考えてみましょう。
大抵のkeyは別のサーバーに割り当てられることになります。この課題を解決するのがコンシステントハッシュと呼ばれるアルゴリズムです。
ハッシュ空間をリング上に捉え、ハッシュリング上にノードをプロットします。recordを保存するノードを選択する際に、keyをhash化し、このリング上でどこにプロットされるのかを考え、プロットされた点から時計回りに見て一番近いノードに保存する、みたいなことをやるアルゴリズムです。Wikipediaのイメージ図を拝借します。
ノードを追加する場合も削除する場合も、リバランスを考えなきゃならないobjectが少なく済むので楽でいいよねって発想です。
ただ2つ課題があって削除と追加を繰り返してると以下のような状況になり得ます。
これらの課題を解決する仮想ノードの紹介もされています。
1つのノードに対して、ハッシュリング上に複数のプロットを行うことで上記の課題を解決することができます。
感想
あまり「就活対策本」みたいな類の本は普段読まないし、就活をゲーム化する感覚が好きじゃあないので、感覚的には ウッとなるタイトルではあるのですが普通に勉強になるので買ってよかったです。今回読んだ前半部分に当たる章では基本的な考え方や普段利用しているComponentのアルゴリズムの紹介的な章がメインで、後半になるにつれてシステム設計っぽさが出てきます。Youtubeを設計するには?みたいな切り口で議論を展開する章とかもあるので読むのが楽しみです。
JPAは組み込みDBを利用する際にテーブルを自動生成する
0. tl;dr
- JPAは組み込みDBを利用している場合にEntityの情報などからDBとtableを自動で生成する
- application.properties(application.yaml)のspring.jpa.hibernate.ddl-autoというプロパティで自動生成する / しないが制御される
1. はじめに / 背景
Spring Bootを利用したプロジェクトにおいて、Integration Testの実装の際にH2(組み込みのin-memory DB)とJPAを利用しているのですが、H2の初期化のために書いていたDDLのスキーマと、JPA用のEntityのスキーマの整合性が取れていないにも関わらず、Testがpassしていてファ!?ってなりました。DatabaseのTableと、JPAのために記述しているEntityとの間で整合性が取れないとapplication contextの生成に失敗してしまうはずなのですが、application contextがうまく生成されるだけでなく、JPA経由でDBに値を入れたり、参照したり、というのが普通に動いてしまってました。
2. spring.jpa.hibernate.ddl-autoの設定について
結論としては、application.yamlで制御できるhibernateの設定で、自動でテーブルが生成される設定がonになっていたのが原因でした。(そんな設定があるの知らなかった)
以下、Documentより引用
By default, JPA databases are automatically created only if you use an embedded database (H2, HSQL, or Derby). You can explicitly configure JPA settings by using
spring.jpa.*properties. For example, to create and drop tables you can add the following line to yourapplication.properties:
spring.jpa.hibernate.ddl-auto=create-drop
(DeepL訳)デフォルトでは、JPAデータベースは、組み込みデータベース(H2、HSQL、Derby)を使用する場合にのみ自動的に作成されます。JPAの設定は、spring.jpa.*プロパティを使用して明示的に設定することができます。例えば、テーブルの作成と削除を行うには、application.propertiesに次の行を追加します。
JPAはH2などの組み込みデータベースを検出すると自動でデータベース(とテーブル)を生成してくれます。
以下はやや古い資料で正確性が怪しいですが、組み込みDBだとdefaultでcreate-dropが設定されているようです。create-dropではその名の通り、アプリケーション作成時にEntityに対応するテーブルがなければ作成し、セッション終了時にスキーマを削除します。
組み込みDBが検出されない場合はdefaultでnoneが設定されるので何もしません。
3. どう設定するか
下記のようにapplication.yamlでcreate teble文を記述したsqlへのパスを指定してtableを初期化するアプローチをいままではとっていました。
spring: sql: init: schema-locations: classpath:h2/schema.sql
DatabaseのDDLを管理しているリポジトリは別で存在し、schemaが更新される際にJPAのEntityも更新しますが、その際にH2の初期化用のDDLも更新する必要が出てきて、DDLの二重管理(場合によってはn重管理)みたくなってめんどくさい思いもあります。RepositoryのIntegration Testという文脈で捉えるなら初期化用のDDLを定義してもしなくても、依存はリポジトリの中に閉じていて本番のDBの状態からは切り離されてしまいます。
どうせ外部環境に繋がないなら自動生成をonにして、初期化用のddlなんて用意しなくて良いのでは?というお気持ちになりました(ライブラリの作者もそう思ったからdefault設定しているのでしょうし)
また、JPAの設定と実際のDBのスキーマの齟齬から疎通で失敗することの検証に関しては後続で結合試験を実施すれば検知できる課題だと思うので、個人的には自動生成に頼ってしまってDDLの管理はサボりたいなと感じました。
以上
4. Reference
spring.jpa.hibernate.ddl-auto に設定可能な値 - Qiita
