CLOVER🍀

That was when it all began.

Infinispan 15.0のRESP゚ンドポむントRedisプロトコルでサポヌトされおいるコマンドずクラスタリングを確認しおみる

これは、なにをしたくお曞いたもの

Infinispan 15.0.0.Finalがリリヌスされたした。

Infinispan 15.0.0.Final

今回は倉曎内容が山盛りになっおいおちょっず驚くのですが、RESP゚ンドポむントRedisプロトコルでサポヌトされおいるコマンドが
倧量に増えおいるので、こちらを確認しおみたいず思いたす。
あず、クラスタリングもやっおみようず思いたす。

InfinispanのRESP゚ンドポむント

InfinispanのRESP゚ンドポむントは、Infinispan 14.0で远加されたRedis互換の゚ンドポむントです。

Infinispan 14.0.0.Final

Infinispan 14.0のRESPエンドポイントをRedis CLIで試す - CLOVER🍀

぀たり、Infinispan ServerをRedisの代わりずしお䜿うこずができたす。

Infinispan 14.0のリリヌスブログの時には少し名前ずサポヌトしおいるコマンドが出おいたくらいなのに、15.0になっおだいぶクロヌズアップ
されおいる感じがしたす。

Infninspan 15.0のリリヌスブログでは、Redisのほずんどのデヌタ型ず90以䞊のコマンドを実装しおいお、以䞋の点が通垞のRedisず
比范した際の利点ずしおいたす。

  • マルチスレッド 
 クラスタリングをしなくおも耇数のコアを掻甚できる
  • P2Pクラスタリング 
 クラスタヌ内のノヌドにはマスタヌレプリカの区別はなく、実行䞭のノヌドの远加削陀も容易
  • 専甚の蚭定を行ったキャッシュ 
 耇数のキャッシュを定矩でき、それぞれ異なる蚭定が可胜。クラスタヌでも動䜜する
  • クロスサむトレプリケヌションのサポヌト
  • 耇数の氞続化オプション 
 ディスク、デヌタベヌスやその他の倖郚ストアに保存可胜
  • 倖郚のIDプロバむダヌずの統合 
 OAuth2、LDAP、Kerberos、クラむアント蚌明曞による認蚌認可
  • 完党なパむプラむン受信凊理によるバッチ凊理のスルヌプットの向䞊
  • Kubernetes Operator

など。

RESP゚ンドポむントで耇数のキャッシュが䜿えるずいうこずですが、Infinispan Serverの゚ンドポむントにひず぀のRedis甚キャッシュを
玐付ける蚭定だったず思うので、耇数のRedis甚キャッシュを扱おうず思うずInfinispan Serverに゚ンドポむントを耇数定矩する必芁が
あるように思いたすね 。

InfinispanのRESP゚ンドポむントのドキュメントはこちら。

Using the RESP protocol endpoint with Infinispan

15.0の時点でも、実隓的モゞュヌル扱いなこずには泚意が芁りそうですね。

Infinispan Server includes an experimental module that implements the RESP3 protocol. The RESP endpoint allows Redis clients to connect to one or several Infinispan-backed RESP servers and perform cache operations.

ずころで、Redisコマンドのサポヌトが増えたずいう話でした。

Infinispan 14.xの頃からするず、それはもうびっくりするくらい増えおいたす。

ドキュメントからサポヌトしおいるコマンドを抜き出しおみたす。

Infinispan 14.xの頃は16個でした。

$ curl -s https://infinispan.org/docs/14.0.x/titles/resp/resp-endpoint.html | grep redis.io | perl -wp -e 's!.+<a href.+">(.+?)</a>.+!$1!' | sort | wc -l
16

Infinispan 15.0ではなんず154個になっおいたす。

$ curl -s https://infinispan.org/docs/15.0.x/titles/resp/resp-endpoint.html | grep redis.io | perl -wp -e 's!.+<a href.+">(.+?)</a>.+!$1!' | sort | wc -l
154

むンメモリヌ・デヌタグリッドでRedis互換の機胜を持぀ものはありたしたが、ここたで倚くコマンドをサポヌトしおいるものは
芋たこずない気がしたすね。

ずころで、そもそもRedisのコマンドっおいく぀あるのでしょう

Commands | Redis

確認しおみたす。この時点でのRedisのバヌゞョンは、7.2.4です。

$ curl -s https://redis.io/commands | perl -wnl -e 'if (m!.+<h1 class.+>! .. m!</h1>!) { if (not /h1/) { s!^ +!!g; print } }' | sort | wc -l
464

464個あるらしいです 。154個実装しおも、ただ半分にも満たない感じですね 。

差分をずっおみたす。

$ diff <(curl -s https://infinispan.org/docs/15.0.x/titles/resp/resp-endpoint.html | grep redis.io | perl -wp -e 's!.+<a href.+">(.+?)</a>.+!$1!' | sort) <(curl -s https://redis.io/commands | perl -wnl -e 'if (m!.+<h1 class.+>! .. m!</h1>!) { if (not /h1/) { s!^ +!!g; print } }' | sort)

Infinispanにしかないものっおあるんでしょうか

$ diff <(curl -s https://infinispan.org/docs/15.0.x/titles/resp/resp-endpoint.html | grep redis.io | perl -wp -e 's!.+<a href.+">(.+?)</a>.+!$1!' | sort) <(curl -s https://redis.io/commands | perl -wnl -e 'if (m!.+<h1 class.+>! .. m!</h1>!) { if (not /h1/) { s!^ +!!g; print } }' | sort) | grep '<'
< CLIENT GETINFO
< MEMORY-STATS
< MEMORY-USAGE

ありたした 。

RedisにCLIENT GETINFOずいうコマンドはないようなので、間違っおいる気がしたす 。

゜ヌスコヌドを芋るず、これはCLIENT GETNAMEの誀りみたいです。

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/src/main/java/org/infinispan/server/resp/commands/connection/CLIENT.java

これはPull Requestを出しおおきたした。

残り2぀は、「-」があるので差分ずしお出おいるようです。

Redisのみにある方はこんな感じです。

$ diff <(curl -s https://infinispan.org/docs/15.0.x/titles/resp/resp-endpoint.html | grep redis.io | perl -wp -e 's!.+<a href.+">(.+?)</a>.+!$1!' | sort) <(curl -s https://redis.io/commands | perl -wnl -e 'if (m!.+<h1 class.+>! .. m!</h1>!) { if (not /h1/) { s!^ +!!g; print } }' | sort) | grep '>'
> ACL CAT
> ACL DELUSER
> ACL DRYRUN
> ACL GENPASS
> ACL GETUSER
> ACL LIST
> ACL LOAD
> ACL LOG
> ACL SAVE
> ACL SETUSER
> ACL USERS
> ACL WHOAMI
> ASKING
> BF.ADD
> BF.CARD
> BF.EXISTS
> BF.INFO
> BF.INSERT
> BF.LOADCHUNK
> BF.MADD
> BF.MEXISTS
> BF.RESERVE
> BF.SCANDUMP
> BGREWRITEAOF
> BGSAVE
> BITCOUNT
> BITFIELD
> BITFIELD_RO
> BITOP
> BITPOS
> BLMOVE
> BLMPOP
> BRPOPLPUSH
> BZMPOP
> BZPOPMAX
> BZPOPMIN
> CF.ADD
> CF.ADDNX
> CF.COUNT
> CF.DEL
> CF.EXISTS
> CF.INFO
> CF.INSERT
> CF.INSERTNX
> CF.LOADCHUNK
> CF.MEXISTS
> CF.RESERVE
> CF.SCANDUMP
> CLIENT CACHING
> CLIENT GETNAME
> CLIENT GETREDIR
> CLIENT KILL
> CLIENT NO-EVICT
> CLIENT NO-TOUCH
> CLIENT PAUSE
> CLIENT REPLY
> CLIENT TRACKING
> CLIENT TRACKINGINFO
> CLIENT UNBLOCK
> CLIENT UNPAUSE
> CLUSTER ADDSLOTS
> CLUSTER ADDSLOTSRANGE
> CLUSTER BUMPEPOCH
> CLUSTER COUNT-FAILURE-REPORTS
> CLUSTER COUNTKEYSINSLOT
> CLUSTER DELSLOTS
> CLUSTER DELSLOTSRANGE
> CLUSTER FAILOVER
> CLUSTER FLUSHSLOTS
> CLUSTER FORGET
> CLUSTER GETKEYSINSLOT
> CLUSTER INFO
> CLUSTER KEYSLOT
> CLUSTER LINKS
> CLUSTER MEET
> CLUSTER MYID
> CLUSTER MYSHARDID
> CLUSTER REPLICAS
> CLUSTER REPLICATE
> CLUSTER RESET
> CLUSTER SAVECONFIG
> CLUSTER SET-CONFIG-EPOCH
> CLUSTER SETSLOT
> CLUSTER SLAVES
> CMS.INCRBY
> CMS.INFO
> CMS.INITBYDIM
> CMS.INITBYPROB
> CMS.MERGE
> CMS.QUERY
> COMMAND COUNT
> COMMAND DOCS
> COMMAND GETKEYS
> COMMAND GETKEYSANDFLAGS
> COMMAND INFO
> COMMAND LIST
> CONFIG GET
> CONFIG RESETSTAT
> CONFIG REWRITE
> CONFIG SET
> COPY
> DUMP
> EVAL
> EVALSHA
> EVALSHA_RO
> EVAL_RO
> FAILOVER
> FCALL
> FCALL_RO
> FT.AGGREGATE
> FT.ALIASADD
> FT.ALIASDEL
> FT.ALIASUPDATE
> FT.ALTER
> FT.CONFIG GET
> FT.CONFIG SET
> FT.CREATE
> FT.CURSOR DEL
> FT.CURSOR READ
> FT.DICTADD
> FT.DICTDEL
> FT.DICTDUMP
> FT.DROPINDEX
> FT.EXPLAIN
> FT.EXPLAINCLI
> FT.INFO
> FT.PROFILE
> FT.SEARCH
> FT.SPELLCHECK
> FT.SUGADD
> FT.SUGDEL
> FT.SUGGET
> FT.SUGLEN
> FT.SYNDUMP
> FT.SYNUPDATE
> FT.TAGVALS
> FT._LIST
> FUNCTION DELETE
> FUNCTION DUMP
> FUNCTION FLUSH
> FUNCTION KILL
> FUNCTION LIST
> FUNCTION LOAD
> FUNCTION RESTORE
> FUNCTION STATS
> GEOADD
> GEODIST
> GEOHASH
> GEOPOS
> GEORADIUS
> GEORADIUSBYMEMBER
> GEORADIUSBYMEMBER_RO
> GEORADIUS_RO
> GEOSEARCH
> GEOSEARCHSTORE
> GETBIT
> HGETALL
> HSTRLEN
> JSON.ARRAPPEND
> JSON.ARRINDEX
> JSON.ARRINSERT
> JSON.ARRLEN
> JSON.ARRPOP
> JSON.ARRTRIM
> JSON.CLEAR
> JSON.DEBUG
> JSON.DEBUG MEMORY
> JSON.DEL
> JSON.FORGET
> JSON.GET
> JSON.MERGE
> JSON.MGET
> JSON.MSET
> JSON.NUMINCRBY
> JSON.NUMMULTBY
> JSON.OBJKEYS
> JSON.OBJLEN
> JSON.RESP
> JSON.SET
> JSON.STRAPPEND
> JSON.STRLEN
> JSON.TOGGLE
> JSON.TYPE
> LASTSAVE
> LATENCY DOCTOR
> LATENCY GRAPH
> LATENCY HISTOGRAM
> LATENCY HISTORY
> LATENCY LATEST
> LATENCY RESET
> LOLWUT
> MEMORY DOCTOR
> MEMORY MALLOC-STATS
> MEMORY PURGE
> MEMORY STATS
> MEMORY USAGE
> MIGRATE
> MODULE LOAD
> MODULE LOADEX
> MODULE UNLOAD
> MONITOR
> MOVE
> OBJECT ENCODING
> OBJECT FREQ
> OBJECT IDLETIME
> OBJECT REFCOUNT
> PEXPIREAT
> PFADD
> PFCOUNT
> PFDEBUG
> PFMERGE
> PFSELFTEST
> PSYNC
> PUBSUB CHANNELS
> PUBSUB NUMPAT
> PUBSUB NUMSUB
> PUBSUB SHARDCHANNELS
> PUBSUB SHARDNUMSUB
> REPLCONF
> REPLICAOF
> RESTORE
> RESTORE-ASKING
> ROLE
> SAVE
> SCRIPT DEBUG
> SCRIPT EXISTS
> SCRIPT FLUSH
> SCRIPT KILL
> SCRIPT LOAD
> SETBIT
> SHUTDOWN
> SLAVEOF
> SLOWLOG GET
> SLOWLOG LEN
> SLOWLOG RESET
> SMISMEMBER
> SPUBLISH
> SREM
> SSUBSCRIBE
> SUNSUBSCRIBE
> SWAPDB
> SYNC
> TDIGEST.ADD
> TDIGEST.BYRANK
> TDIGEST.BYREVRANK
> TDIGEST.CDF
> TDIGEST.CREATE
> TDIGEST.INFO
> TDIGEST.MAX
> TDIGEST.MERGE
> TDIGEST.MIN
> TDIGEST.QUANTILE
> TDIGEST.RANK
> TDIGEST.RESET
> TDIGEST.REVRANK
> TDIGEST.TRIMMED_MEAN
> TFCALL
> TFCALLASYNC
> TFUNCTION DELETE
> TFUNCTION LIST
> TFUNCTION LOAD
> TOPK.ADD
> TOPK.COUNT
> TOPK.INCRBY
> TOPK.INFO
> TOPK.LIST
> TOPK.QUERY
> TOPK.RESERVE
> TOUCH
> TS.ADD
> TS.ALTER
> TS.CREATE
> TS.CREATERULE
> TS.DECRBY
> TS.DEL
> TS.DELETERULE
> TS.GET
> TS.INCRBY
> TS.INFO
> TS.MADD
> TS.MGET
> TS.MRANGE
> TS.MREVRANGE
> TS.QUERYINDEX
> TS.RANGE
> TS.REVRANGE
> UNLINK
> WAIT
> WAITAOF
> XACK
> XADD
> XAUTOCLAIM
> XCLAIM
> XDEL
> XGROUP CREATE
> XGROUP CREATECONSUMER
> XGROUP DELCONSUMER
> XGROUP DESTROY
> XGROUP SETID
> XINFO CONSUMERS
> XINFO GROUPS
> XINFO STREAM
> XLEN
> XPENDING
> XRANGE
> XREAD
> XREADGROUP
> XREVRANGE
> XSETID
> XTRIM
> ZMSCORE
> ZRANK
> ZREVRANK

ただただたくさんありたすね。HGETALLなどもあったりしたす。

これで今埌も差分比范はできそうです。

ここからは、Infinispan Serverで少しRedisプロトコルを詊しおみたしょう。

環境

今回の環境はこちら。

$ java --version
openjdk 21.0.2 2024-01-16 LTS
OpenJDK Runtime Environment Temurin-21.0.2+13 (build 21.0.2+13-LTS)
OpenJDK 64-Bit Server VM Temurin-21.0.2+13 (build 21.0.2+13-LTS, mixed mode, sharing)


$ bin/server.sh --version

Infinispan Server 15.0.0.Final (I'm Still Standing)
Copyright (C) Red Hat Inc. and/or its affiliates and other contributors
License Apache License, v. 2.0. http://www.apache.org/licenses/LICENSE-2.0

Infinispan Serverは172.18.0.3で動䜜しおいるものずしお、以䞋のコマンドで起動させたす。

$ bin/server.sh \
    -b 0.0.0.0 \
    -Djgroups.tcp.address=$(hostname -i)

Infinispan Serverには、以䞋のコマンドで管理甚ナヌザヌずアプリケヌション甚ナヌザヌを䜜成しおいるものずしたす。

$ bin/cli.sh user create -g admin -p password ispn-admin
$ bin/cli.sh user create -g application -p password ispn-user

RedisぞのアクセスにはRedis CLIを䜿いたす。

$ bin/redis-cli --version
redis-cli 7.2.4

Redis CLIからInfinispan ServerのRESP゚ンドポむントぞ接続する

アプリケヌション甚ナヌザヌの認蚌情報を䜿っお、RESP゚ンドポむントに接続したす。

$ bin/redis-cli -h 172.18.0.3 -p 11222 --user ispn-user --pass password
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.

Infinispan Serverはデフォルトで認蚌必須なので、先にナヌザヌを䜜っおおく必芁がありたす。

で、接続さえできればあっさり䜿えたす。

172.18.0.3:11222> set key1 value1
OK
172.18.0.3:11222> get key1
"value1"

このあたりは、14.0の時にも確認しおいるので同じですね。

Infinispan Serverにログむンしお、キャッシュの定矩を確認しおおきたしょう。

$ bin/cli.sh -c http://ispn-admin:password@localhost:11222

キャッシュの䞀芧。

> ls caches
memcachedCache
___script_cache
respCache

respCacheずいうのは、Infinispan Serverが起動時に䜜成するデフォルトのキャッシュです。

確認。

> describe caches/respCache
{
  "respCache" : {
    "distributed-cache" : {
      "key-partitioner" : "org.infinispan.distribution.ch.impl.RESPHashFunctionPartitioner",
      "mode" : "SYNC",
      "statistics" : true,
      "encoding" : {
        "key" : {
          "media-type" : "application/octet-stream"
        },
        "value" : {
          "media-type" : "application/octet-stream"
        }
      }
    }
  }
}

Distributed Cacheになっおいたす。確か、14.0の時はReplicated Cacheだったず思いたす。

定矩が倉わったのでしょうか

そのようです。

            if (cacheManager.getCacheManagerConfiguration().isClustered()) { // We are running in clustered mode
               builder.clustering().cacheMode(CacheMode.DIST_SYNC);
               // See: https://redis.io/docs/reference/cluster-spec/#key-distribution-model
               builder.clustering().hash().keyPartitioner(new RESPHashFunctionPartitioner());
            }

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/src/main/java/org/infinispan/server/resp/RespServer.java#L86-L90

こちらの倉曎ですね。

ISPN-15637 Make the respCache distributed by default by tristantarrant · Pull Request #11906 · infinispan/infinispan · GitHub

respcache should default to distributed

特に理由は曞かれおいたせんが、デフォルトをDistributed Cacheにするべきだず刀断したようです。

ちなみに、RESP゚ンドポむントで登録したデヌタをInfinipsan Serverでも芋るこずができたす。

> cache respCache
> get key1
value1

クラスタリングしおみる

Infinispan 14.0の時はRESP゚ンドポむントに蚭定するキャッシュの倉曎をしおみたりしたのですが、今回はクラスタリングしおみたいず
思いたす。

ちょうど、デフォルトがDistributed Cacheになっおいたしたし。

Infinispan Serverを3ノヌド172.18.0.3〜5にしたす。

$ bin/cli.sh -c http://ispn-admin:password@localhost:11222
> ls /cluster
a65add5acb25-63023
06834bc0e989-48561
1ce7dbd93833-65191

Redis CLIから接続しおみたす。

$ bin/redis-cli -h 172.18.0.3 -p 11222 --user ispn-user --pass password
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.

CLUSTER NODESコマンドを実行しおみたす。

172.18.0.3:11222> cluster nodes
a65add5acb25-63023 0.0.0.0:11222@39380 master - 0 1710676040 9 connected 256-1087 5440-6015 7360-8511 9536-10367 10944-11775 11904-12543 13504-13887 14848-14911
06834bc0e989-48561 0.0.0.0:11222@39380 myself,master - 0 1710676040 9 connected 1344-2111 2368-2431 4096-4799 6080-7359 8512-9535 10368-10943 14208-14655 14976-15551 15680-15807
1ce7dbd93833-65191 0.0.0.0:11222@39380 master - 0 1710676040 9 connected 0-255 1088-1343 2112-2367 2432-4095 4800-5439 6016-6079 11776-11903 12544-13503 13888-14207 14656-14847 14912-14975 15552-15679 15808-16383

3ノヌド認識しおいたす。Redis Clusterずしお認識されおいる、ずいうこずでよさそうです。

デヌタを10個ほど登録しおみたす。

172.18.0.3:11222> set key1 value1
OK
172.18.0.3:11222> set key2 value2
OK
172.18.0.3:11222> set key3 value3
OK
172.18.0.3:11222> set key4 value4
OK
172.18.0.3:11222> set key5 value5
OK
172.18.0.3:11222> set key6 value6
OK
172.18.0.3:11222> set key7 value7
OK
172.18.0.3:11222> set key8 value8
OK
172.18.0.3:11222> set key9 value9
OK
172.18.0.3:11222> set key10 value10
OK

取埗。

172.18.0.3:11222> get key1
"value1"
172.18.0.3:11222> get key2
"value2"
172.18.0.3:11222> get key3
"value3"
172.18.0.3:11222> get key4
"value4"
172.18.0.3:11222> get key5
"value5"
172.18.0.3:11222> get key6
"value6"
172.18.0.3:11222> get key7
"value7"
172.18.0.3:11222> get key8
"value8"
172.18.0.3:11222> get key9
"value9"
172.18.0.3:11222> get key10
"value10"

Redis CLIに-cオプションを぀けなくおも、ふ぀うに動きたすね

ここたでくるず予想が぀きたすが、-cオプションを぀けおも特にリダむレクトしたりしたせん。

$ bin/redis-cli -h 172.18.0.3 -p 11222 --user ispn-user --pass password -c
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.

䞀応、Infinispan ServerのManagement Consoleで確認するず、デヌタは各ノヌドに分散されお配眮されおいるようです。

Redis Clusterではあるものの、デヌタを取埗する察象のノヌドに向けおリダむレクトが行われないRedis Clusterずいった感じでしょうか。

たあ、なんずなくこうなる気はしおいたので、予想通りではあるのですが。

ずころで、こうなるずもしかしお1ノヌドの時はシングルノヌドのRedis Clusterずしお認識されおいるのでしょうか

$ bin/redis-cli -h 172.18.0.3 -p 11222 --user ispn-user --pass password
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
172.18.0.3:11222> cluster nodes
9b7484f2d27a-3856 0.0.0.0:11222@54440 myself,master - 0 1710676876 1 connected 0-16383

そのようです。

実装をもう少し

Infinispan 14.0で詊した時も少し実装を芋たのですが、15.0で芋るずだいぶ倉わっおいそうです。

実装されおいるコマンドは、以䞋のパッケヌゞサブパッケヌゞ含むにありたす。

https://github.com/infinispan/infinispan/tree/15.0.0.Final/server/resp/src/main/java/org/infinispan/server/resp/commands

前はResp3Handlerなどにコマンド名が曞かれおいたのですが、だいぶ倉わりたしたね。

たた、以前はRESPサヌバヌの実装にLettuceが䜿われたりしおいたしたが、今はそうではなさそうです。
Nettyをメむンに䜿っおいる感じですね。

Redisのコマンドのデコヌド凊理はNettyのデコヌダヌの仕組みで行われるようなのですが、

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/src/main/java/org/infinispan/server/resp/BaseRespDecoder.java

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/src/main/java/org/infinispan/server/resp/RespChannelInitializer.java#L39-L41

ここで䜿われおいるRespDecoderずいうクラスがないぞず思ったら、その実装は定矩からパヌサヌを自動生成しおいるようです。

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/src/main/resources/resp.gr

https://github.com/infinispan/infinispan/blob/15.0.0.Final/server/resp/pom.xml#L79-L95

こういう仕組みでできおいるんですね。

おわりに

Infinispan 15.0で実装コマンドが倧きく増えた、RESP゚ンドポむントを詊しおみたした。

さらっず䜿う分には特に14.xの時ず倉わりはないのですが、内郚実装がだいぶ倉わっおいる感じがしたす。

たた14.xの時はクラスタリングも詊しおいなかったので、実際に䜿うずどういう挙動になるのかちょっず気になっおいたので確認する
いい機䌚になりたした。

それにしおも、この勢いでRedisのほずんどの機胜をカバヌするんでしょうか

Redis、それからDragonflyあたりず競うこずになったり

Dragonfly - The Fastest In-Memory Data Store