Skip to content

Instantly share code, notes, and snippets.

@shouichi
Last active December 25, 2015 07:00
Show Gist options
  • Save shouichi/a9a8184455c60c7f96e2 to your computer and use it in GitHub Desktop.
Save shouichi/a9a8184455c60c7f96e2 to your computer and use it in GitHub Desktop.

Finatra + MySQL + Protobufのススメ

神谷翔一

東大情報科学科出身のエンジニア

主にbackendを書く事が多い

今日伝えたい事

  1. MySQLの少し変わった使い方
  2. Finatra便利

MySQL + Protobuf

一言で言うとMySQLをKV storeとして使う

Tableは基本的にはidとbytesの2 columnのみ

bytesにprotobufのmessageをserializeして保存する

Index/constraintが必要なfieldのみ専用columnとして切り出す

-- eamilは一意性を保証したいので専用columnを用意してindexをはる
CREATE TABLE users (
  id BIGINT,
  bytes blob,
  email varchar(255)
);

CREATE UNIQUE INDEX users_email ON users(email);

KVとして使うが必要に応じてindex/constraint/transactionが使えるのでただのKVより便利

Pros

  • 豊かな表現力(array, nested message)
  • 多くの場合はProtobufの定義を変更するだけなのでmigrationをする事が少ない

Cons

  • JOINは手動
  • binaryが保存されてるのでSELECT * FROM fooしてもデータが読めない

Finatra/Finagle

Twitter製のNetty wrapperでhttp/dbへのアクセスが同じinterfaceで抽象化されている

Request/responseのjson mappingは全自動でvalidationもしてくれる

class Tweets @Inject()(
  idService: IdService,
  tweetsService: TweetsService) extends Controller {

  get("/tweet/:id") { request: GetTweetRequest =>
    tweetService.get(request.id)
  }

  case class PostTweetRequest(@Size(min=1 max=144) text: String)

  post("/tweet") { request: PostTweetRequest =>
    for {
      id <- idService.create()
      tweet = buildTweet(id, request)
      _ <- tweetService.create(tweet)
    } yield {
      response
        .created(tweet)
        .location(tweet.id)
    }
  }
}
class TweetsService @Inject()(mysql: MySQL) {
  private[this] val query = "INSERT INTO tweets (id, bytes) SET (?, ?)"

  def create(proto: Proto.Tweet): Future[Unit] = {
    mysql.prepare(query)(proto.id, proto.toByteArray)
  }
}

TweetsServiceはProto.Tweetを受け取りFuture[Unit]を返すserviceとして抽象化されている

TweetsServiceを別のserviceとして切り出してもinterfaceは不変

class TweetsService @Inject()(http: httpClient) {
  def create(proto: Proto.Tweet): Future[Unit] = {
    http.post(...)
  }
}

流行りのmicro serviceにも比較的楽に対応出来る

その他service discovery, metricsなどtwitterが実際に使用してる便利機能満載

おまけ

以上と似た仕組みで社内で動いてるもの

  1. 広告
  2. Recommendation engine
  3. Game server
  4. Push notification server
  5. Android/iOSのbackend server

この中で特に広告は普通ではされていない工夫がしてあって面白いので興味がある人は弊社にwelcome

Reference

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment