あらゆる DB を KVS 化 する Keyv を試してみた。

こんにちは k-jun です。今日は Redis の interface を持ちながらも、backend として MySQLPostgreSQL、Redis、MongoDB など様々な DB を活用できる Keyv を試してみます。

https://github.com/microlinkhq/keyv

最初読んだときには、Redis が backend で MySQLPostgreSQL など 様々な DB の interface を提供している化け物 Library とか思っていました 笑。 そんなものがあったら star が 100 (2021/08/21) で収まるわけないんですよね。

ではでは試していきます。ひとまず RDS、NoSQL、KVS を見れば大体どのように対応しているのかわかるので、MySQL、Redis あたりが見れれば十分でしょうか。

$ npm install -d npm install -D @keyvhq/core @keyvhq/redis @keyvhq/mongo @keyvhq/mysql

デフォルトは 普通に in-memory のキャッシュをしてくれるみたいです。

import Keyv from "@keyvhq/core"

async function main() {
  const keyv = new Keyv();
  if (!await keyv.set("name", "k-jun")) {
    console.error("error happended")
  }
  const name = await keyv.get("name")
  console.log(name)
}

main()

MySQL を試してみる。

import Keyv from "@keyvhq/core"
import KeyvMySQL from "@keyvhq/mysql"

async function main() {
  const keyv = new Keyv({ store: new KeyvMySQL('mysql://test:test@127.0.0.1:3306/test') })
  if (!await keyv.set("name", "k-jun")) {
    console.error("error happended")
  }
  const name = await keyv.get("name")
  console.log(name)
}

main()
$ node index.js
k-jun

実行が終了しない。ひとまず置いておいて、中身が気になる。

mysql> show create table keyv\G;
*************************** 1. row ***************************
       Table: keyv
Create Table: CREATE TABLE `keyv` (
  `key` varchar(255) NOT NULL,
  `value` text,
  PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

おっとぉ..? ttl のカラムが存在しない..? と思ったら Json 形式で保存しているだけでした。

mysql> select * from keyv;
+-----------+-------------------------------------------+
| key       | value                                     |
+-----------+-------------------------------------------+
| keyv:name | {"value":"k-jun","expires":1629501898314} |
+-----------+-------------------------------------------+

MongoDB の試してみる。

$ docker run -p 27017:2017 -e MONGO_INITDB_DATABASE=test -e MONGO_INITDB_ROOT_USERNAME=root -e MONGO_INITDB_ROOT_PASSWORD=root mongo
import Keyv from "@keyvhq/core"
import KeyvMySQL from "@keyvhq/mysql"
import keyvMongo from "@keyvhq/mongo"

async function main() {
  const keyv = new Keyv({ store: new keyvMongo('mongodb://root:root@127.0.0.1:27017') })
  if (!await keyv.set("name", "k-jun", 3000)) {
    console.error("error happended")
  }
  const name = await keyv.get("name")
  console.log(name)
}

main()

中身はなんというか、まあ予想通り。

test> db.keyv.find({});
[
  {
    _id: ObjectId("61204098811ca4f77340f152"),
    key: 'keyv:name',
    expiresAt: ISODate("2021-08-20T23:54:03.454Z"),
    value: '{"value":"k-jun","expires":1629503643453}'
  }
]

サクッと、Redis も見ていく。

import Keyv from "@keyvhq/core"
import KeyvMySQL from "@keyvhq/mysql"
import keyvMongo from "@keyvhq/mongo"
import keyvRedis from "@keyvhq/redis"

async function main() {
  const keyv = new Keyv({ store: new keyvRedis('redis://127.0.0.1:6379') })
  if (!await keyv.set("name", "k-jun", 3000)) {
    console.error("error happended")
  }
  const name = await keyv.get("name")
  console.log(name)
}

main()

どうやら、Redis だけは Redis の Expire を頼っている。うん、普通。

127.0.0.1:6379> keys *
1) "keyv:name"
127.0.0.1:6379> keys *
(empty array)

各種 DB の中身を見てみましたが、なんというか想像通りであまりおもしろくありませんでした。TiDB などの KVS を MySQL 互換にしているのほんとどうやっているんでしょうね..。

それでは今日はこの辺で。