Nodejsで使用するredis clientは何がベターなのかを調査する

## はじめに

*[zennの記事](https://zenn.dev/articles/bc474f431e65aa/edit)の転記です

今後PaaS上での開発に移行するにあたり、Node jsを利用していくことになりました。
その際に使うredisクライアントのライブラリを調査してるのですが、そういやこういうものの調べ方や考えをまとめたことないなと思ったので、後輩とかに共有するためにちょっとまとめてみようと思います。

## 候補 → ioredis or node-redis

まずは候補を探します。
[redis公式](https://redis.io/clients#nodejs) がおすすめを提示してくれていましたので、そのまま参考にします。
星マークがおすすめ。ニコちゃんマークは開発が活発なもの(過去6ヶ月で動きがあったもの)です。

以下3 repisitoriesがおすすめに上がっていますね。

- [ioredis](https://github.com/luin/ioredis)
- [node-redis](https://github.com/NodeRedis/node-redis)
- [tedis](https://github.com/silkjs/tedis)

最後のtedisだけスター数が少なく、以下redislabsのdocument referenceにもtedisが乗っていないので、こちらは一旦スルーします

- [ioredisのdoc](https://docs.redislabs.com/latest/rs/references/client_references/client_ioredis/)
- [node-redisのdoc](https://docs.redislabs.com/latest/rs/references/client_references/client_nodejs/)

## 比較

候補が2つに絞られたので比較をしていきます。基本はそれぞれの背景を見て、今のトレンドと性能比較をすればいいかな。
どちらにもいい点ありそうなら、いい点悪い点あげて比較するんですが、果たしてどうなるか。

### 機能 → ioredis >  node-redis

元々はnode-redisがNode Redisという団体によって作成されたもので、こちら2010年から現在も活動されています。

ただ、promiseや、redisのpipelineのような一部機能をサポートしてないようです。
そのためか元Alibabaのエンジニアである
[Zihua Li](https://github.com/luin)さんがioredisを開発したようです。

機能面は純粋にioredisが上位互換と思って良さそう

* node-redisのpromiseはv4で正式サポートされるそうです

### 性能 → ioredis <= node-redis

以下を参考に。

[poppinlp/node_redis-vs-ioredis](https://github.com/poppinlp/node_redis-vs-ioredis)

どちらもほぼ同じですが、multiで動かした場合、batch vs pipelineでの比較はともに若干node-redisに軍配が上がっています。

batchって何かしらというと、node-redisで提供してるmultiを実行して結果をまとめて1つのコールバックでもらうという、利用者から見るとpipelineのような機能らしいです。

https://github.com/NodeRedis/node-redis/issues/806


### 人気 → ioredis >> node-redis

以下を参考にしました。([npm trends](https://www.npmtrends.com/)、いいサイトですね)

[ioredis vs node-redis](https://www.npmtrends.com/ioredis-vs-node-redis)

2021/7/23時点の過去6ヶ月の記録でダウンロード数、スター数ともに圧倒的にioredisが上に。


### その他

大手クラウド事業者のサンプルはnode-redisが多かったです。

- AWS -> ioredis

[Amazon ElastiCache for Redis を使ったChatアプリの開発](https://aws.amazon.com/jp/blogs/news/how-to-build-a-chat-application-with-amazon-elasticache-for-redis/)の[サンプルコード](https://github.com/aws-samples/elasticache-refarch-chatapp)を参照。

こちらはioredisを使用していました。

- GCP -> node-redis

[Cloud Functions から Redis インスタンスへの接続](https://cloud.google.com/memorystore/docs/redis/connect-redis-instance-functions?hl=ja#node.js)の[サンプルコード](https://github.com/GoogleCloudPlatform/nodejs-docs-samples/blob/master/memorystore/redis)を参照。
node-redisを使ってますね。

- Azure -> node-redis, ioredis

[クイックスタート: Node.js で Azure Cache for Redis を使用する](https://docs.microsoft.com/ja-jp/azure/azure-cache-for-redis/cache-nodejs-get-started)のサンプルコードを見ると、node-redisを使っています。
リンク見失いまいしたが、ioredisのサンプルもありました

軽くググった感じでもnode-redisの方がサンプルは多そうでした。この辺は歴史の長さですかね。
ただ、ioredisのサンプルが少ないというわけではないですので、これでどちらが優位というほどではなさそうです。

## 結論 → 基本ioredisが良い

調査結果を改めてまとめます。

- 機能: ioredis >  node-redis
- 性能: ioredis <= node-redis
- 人気: ioredis >> node-redis

性能がほぼ=と考えると、ioredisの方が優位に見えますね。個人的にも以下のように考えます

- 基本はioredisがいい
- 機能や互換性とかはどうでもいい、とにかく少しでも速いものが欲しいんじゃ！って人はnode-redis

以下でその理由を深堀していきます。

### 結論に至った理由

理由は以下です

- promiseの有無
	- node-redisでは次バージョンまでpromiseがないこと
- redis機能の充実度合い
	- 性能向上に貢献しているpipelineがnode-redisは非サポート
	- redisで提供している機能を使った性能を考えると、ioredisの方が性能がいいとも言える

#### promiseがない

言わずもがなですね。promiseがないとJavaScriptのコードが一気に複雑化するので、promiseがないのは痛いです。
まあversion 4でサポートされることを考えると、将来的にはなくなる優位性かもしれません

#### redis機能の充実度合い

pipelineがない点について。こちら、node-redis公式でも[pipelineの導入が議論](https://github.com/NodeRedis/node-redis/issues/539)されていました.
しかし、redis側の提示しているpipelineの仕組みに欠点があることから採用を見送ったようです。おそらくその代わりにbatchがあるでしょうということなんだと

ただ、redisのclientという標準的なプロトコルを実装するライブラリが、公式で提供されている機能を実装せず独自実装で同じ機能を提供するのって、すごく違和感があるんですよね。redis機能を使った上で+αならわかりますが
これだと例えば公式がpipelineの欠点をredis側がカバーするようアップデートかけたとしても、pipelineを使ってないnode redisは恩恵を受けられないし。
標準プロトコルへの取り組み方が、ioredisの方がよりあるべき形であるように感じてしまいます。

もちろん性能にシビアな世界では速さが正義！カスタマイズ上等！だと思います。
ただ私は一定の性能が出てれば十分な世界でやっているので、基本redisを使った性能向上はredisの機能で実現したいです。
ですので、redis機能としてpipelineを実装しており、その上で性能が出ているioredisに軍配があがります。

#### 本当にpipelineが必要か？問題

上記理由を書いたんですが、人によってはpipelineを使う必要がないため、この優位性がはまらない人もいると思います。

例えば[Sharing: Redis get pipeline vs mget](https://medium.com/@jychen7/redis-get-pipeline-vs-mget-6e41aeaecef)で実測されているように、近いことができるmgetの方がpipelineよりもさらに速いです。
redisは速度が正義であるなら、pipelineいらん、mgetでいいやん！となるところですね。

ただ、記事のPros/Consの通りでpipeline使い勝手がいいので、redisの中で使える機能が多いことはやはり優位に働きます。個人的にも今もredisを利用しているのですが、そこではこの使い勝手をとってpipelineを活用しているため、pipelineを提供しているのは優位だと思っています。

### もちろん上記を優位に感じない → node-redisもあり

つらつらと理由を書きましたが、promiseの話は先でなくなりますし、redis機能も使わない人にはどうでもいい話です。
なのでこの辺を気にせず速度に若干の優位性があるnode-redisを使う！って判断もありだと思います。その辺はなにを基準にするかですよね

## 最後に

ここまでライブラリを選定するための調査から結論まで書きましたが、結局最後のところはチーム・個人の事情や趣味が色濃く出てきます。状況や見方を少し変えればいくらでも評価は変わるものなので、納得できる要素が集まったら後は決断！って感じがしますね。

その決断に納得感を得るためには、物事のベストプラクティスや設計に対する考え方などを日々学んで土台を広げていくことが大事なのかもしれません。

## 参考
[Node.jsでRedis使うならioredisがおすすめ](https://qiita.com/jnst/items/79589a8008d328f06120)

*記事に貼ったリンクは除く