9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

ID(採番)生成戦略

Last updated at Posted at 2018-08-29

概要

RailsでSNS系サービスを作る時に、タイムライン型でページネーションを実現するためにはというメモ。
通常通りソートして、カウンティングするだけでは解決できなかった話と、解決策の話です。

結論

結論から言うとUUID version1のような時間型で衝突しないid生成がなされていればOK。
あくまでRailsから外れずコード管理のみで考えた時に時系列で並ぶulidの実装に落ち着きました。
https://github.com/ulid/spec

実装の提案

兎にも角にも実装例を見せないと始まらないので、以下に落ち着きました。
cursor型ページネーションの実装になります。
https://gist.github.com/penguinwokrs/45a7cfed3c31698da9b3e2409d83cffe
キモの解説ですが、UUIDをつけてUUID同士を比較して超過以降を抽出しているだけです。

klass.where("`uuid` < '#{cursor}'") # cursorの部分もuuidです。

(...たったこれだけです...ulid...すごい...)

既存の問題

ツイッターのようなサービスでページネーション実装を考えた時に、作成時間を元にソートしてから20件ずつカウンティングすると、偶然にも同時刻でツイートされる可能性は大いにあるため、1ページ目と2ページ目に重複したツイート内容が出てくる可能性がある。
SQL的には、以下のような実装が対応として回避可能である。
Pagination(ページネーション)がずれる、抜ける問題を解決する

採用しなかった理由としては、以下の通りです。

  • ミリ秒単位での制御が考慮されていない。
  • SQL的にチューニングとメンテが厳しそう。(低コストでできる方法を実現させたかった)

参考文献

所感

大規模なサービスほどスケールする時にどうするかをすごく考えていて、参考なりますね。
MastodonはオープンソースとしてTwitterが作成したsnowflakeを採用していて良いと思ったが、実装をストアドプロシージャで管理していた。
snowflakeの実装はいいと思うが、専用サーバ用意したりストアドプロシージャは現代で考えるとコストが高く感じるのは自分だけだろうか。 :thinking:

トレンド的にGraqhQLがプロダクトへ投入され始めているので、こちらのEdgeとNodeも学んでいきたいところです。

P.S.
実装の提案で補足なのですが、headerの部分でgithubみたいにRFC風に則りやりたかったが、APIを利用する開発陣営との折り合いがつかず、独自実装になりました。

9
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?