🎉

初心で挑むredis入門 ~Redis Strings編~

に公開

今回はredisで使えるStringsについてみていきます。

早速検証!!

redisの環境構築については先日公開した以下の記事を参考にしてください。

https://zenn.dev/akasan/articles/redis_quickstart

Redis Stringsのドキュメントは以下になります。

https://redis.io/docs/latest/develop/data-types/strings/

単独の値の格納

redisでは文字列やシリアライズされたデータをbytesデータとして格納します。早速keyとvalueを指定して文字列を格納してみましょう。

data_string.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
key, value = "foo", "bar"
r.set(key, value)
fetched_value = r.get(key)
print(f"original: {value}, fetched_value: {fetched_value}")
print(f"original type: {type(value)}, fetched_value type: {type(fetched_value)}")

keyにfoo、valueにbarを設定し、そのペアをredisに登録しています。

r.set(key, value)

そしてそのkeyを利用してredisに問い合わせを行い、データを取得しています。

fetched_value = r.get(key)

早速このコードを実行してみましょう。

uv run data_string.py

# 結果
original: bar, fetched_value: b'bar'
original type: <class 'str'>, fetched_value type: <class 'bytes'>

結果を見ると、元データはstr型ですがredisから取得された値はbytes型となっています。これは先ほど言及したようにredisで取り扱われるStringsはbytes型になるためです。型を合わせるためにはfetched_valueをデコードする必要があります。

複数の値の格納

先ほどの例では単独の(key, value)ペアに対して登録していますが、複数の値を同時に設定・取得することができます。そのような場合にはmsetやmgetを使います。

data_string_multiple.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)

items = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}
r.mset(items)
fetched_values = r.mget(["key1", "key3"])
print(f"{fetched_values=}")

itemsで複数の(key, value)ペアを作成してmsetを使って登録しています。

items = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
}
r.mset(items)

そしてmgetで複数のキーを指定すると値を取得できます。

fetched_values = r.mget(["key1", "key3"])

このコードを実行すると以下のような結果になります。

uv run data_string_multiple.py

# 結果
fetched_values=[b'value1', b'value3']

カウンターとして利用する

redisのStringsの面白い機能として、カウンターとして利用する機能があります。まずはコードを見てもらいましょう。

data_string_counter.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
r.set("counter", 0)
print(f'{r.get("counter")=}')
r.incr("counter")
print(f'{r.get("counter")=}')
r.incrby("counter", 10)
print(f'{r.get("counter")=}')

内部でどういう挙動になっているかというと、、、

  1. r.setでカウンターの値を初期化
  2. r.incrが実行されると指定されたキーに該当する値をint型としてパースする
  3. 3の結果に対して1を加算する

ということになっているようです。値を初期化する時点で数値に該当するような値を指定すればカウンターとなるということです。r.incrは実行するとカウンターを1増やしますが、r.incrbyは第二引数で指定された値だけ増やすことができます。

それでは早速コードを実行してみましょう。

uv run data_string_counter.py

# 結果
r.get("counter")=b'0'
r.get("counter")=b'1'
r.get("counter")=b'11'

初期値は0ですが、r.incrを実行すると1が増え、r.incrbyを実行すると指定された値(今回の例では10)だけ増えていることがわかります。

また、加算用の機能があるということは減算用の機能ももちろんあります。r.decrr.decrbyがそれぞれ対応する機能です。

data_string_counter_decr.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
r.set("counter", 10)
print(f'{r.get("counter")=}')
r.decr("counter")
print(f'{r.get("counter")=}')
r.decrby("counter", 10)
print(f'{r.get("counter")=}')

先ほどの例と同様、r.decrr.decrbyを実行すると対応するキーの値がintとしてパースされ、任意の値を引くことができます。

実行してみると予想していた結果となりました!

uv run data_string_counter_decr.py

# 結果
r.get("counter")=b'10'
r.get("counter")=b'9'
r.get("counter")=b'-1'

また、実はfloat型に対してもカウンターを利用することができます。r.incrbyfloatを利用するとfloat型でのカウンターを実装できます。

data_string_counter_float.py
import redis

r = redis.Redis(host="localhost", port=6379, db=0)
r.set("counter", 0)
print(f'{r.get("counter")=}')
r.incrbyfloat("counter", 5.5)
print(f'{r.get("counter")=}')
r.incrbyfloat("counter", -3.5)
print(f'{r.get("counter")=}')

r.incrbyfloatは第二引数で指定された値だけ増やしたり減らしたりできます。ご覧の通り、r.decrbyfloatはないので注意してください。

実行してみると以下のような結果となります。

uv run data_string_counter_float.py

# 結果
r.get("counter")=b'0'
r.get("counter")=b'5.5'
r.get("counter")=b'2'

基本コマンド一覧

以下にStrings周りで利用できる基本コマンド一覧をまとめます。

  • r.set: 指定したキーに対して値を設定する
  • r.setnx: 指定したキーに対応するデータが保存されていない場合にのみ保存を実行する
  • r.get: 指定したキーに対応するデータを取得する
  • r.mset: 複数の(key, value)ペアを同時に設定する
  • r.mget: 複数のキーに対応するデータを同時に取得する
  • r.incr: 指定したキーに対応する値をintとしてパースして1増やす
  • r.incrby: 指定したキーに対応する値をintとしてパースして任意の値だけ増やす
  • r.decr: 指定したキーに対応する値をintとしてパースして1減らす
  • r.decrby: 指定したキーに対応する値をintとしてパースして任意の値だけ減らす
  • r.incrbyfloat: 指定したキーに対応する値をfloatとしてパースして任意の値だけ増やす

まとめ

今回はRedis Stringsの機能についてみてみました。文字列のペアの取り扱いとカウンターとしての取り扱いができることを確認しました。次回はRedhs hashesを取り扱おうと思います。

Discussion