The INCRBY指令在Redis管道中执行时返回对管道的引用,而不是修改的键的值。

huangapple go评论57阅读模式
英文:

The INCRBY instruction executed by a Redis pipeline return a reference to the pipeline instead the value of the key modified

问题

I have some problem to use Redis pipeline. I need to execute 2 commands (incr() and set()) by a Redis transaction.

Environment info: redis-py version 3.5.3; the version of the Redis server is v=5.0.5.

So I have tried to use the following code (the code example is reproducible):

import redis

r = redis.Redis()
pipe = r.pipeline()

def redis_insertion():
    pipe.multi()
    testIndex = pipe.incr('testIndex')
    pipe.set('new_key:' + str(testIndex), 'new_value')
    pipe.execute()
    pipe.reset()

redis_insertion()

By Monitor I can see the real commands executed by the redis server:

> redis-cli monitor
OK
1684750490.821375 [0 127.0.0.1:47322] "MULTI"
1684750490.821394 [0 127.0.0.1:47322] "INCRBY" "testIndex" "1"
1684750490.821400 [0 127.0.0.1:47322] "SET" "new_key:Pipeline<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>"" "new_value"
1684750490.821411 [0 127.0.0.1:47322] "EXEC"

The problem is that the instruction pipe.set('new_key:' + str(testIndex), 'new_value') return:

Pipeline<ConnectionPool<Connection<host=localhost,port=6379,db=0>>>

instead of the value of the key testIndex after the execution of the INCRBY instruction.

Could someone explain me this behaviour?

英文:

I have some problem to use Redis pipeline. I need to execute 2 commands (incr() and set()) by a Redis transaction.

Environment info: redis-py version 3.5.3; the version of the Redis server is v=5.0.5.

So I have tried to use the following code (the code example is reproducible):

import redis

r = redis.Redis()
pipe = r.pipeline()

def redis_insertion():
    pipe.multi()
    testIndex = pipe.incr(&#39;testIndex&#39;)
    pipe.set(&#39;new_key:&#39; + str(testIndex), &#39;new_value&#39;)
    pipe.execute()
    pipe.reset()

redis_insertion()

By Monitor I can see the real commands executed by the redis server:

&gt; redis-cli monitor
OK
1684750490.821375 [0 127.0.0.1:47322] &quot;MULTI&quot;
1684750490.821394 [0 127.0.0.1:47322] &quot;INCRBY&quot; &quot;testIndex&quot; &quot;1&quot;
1684750490.821400 [0 127.0.0.1:47322] &quot;SET&quot; &quot;new_key:Pipeline&lt;ConnectionPool&lt;Connection&lt;host=localhost,port=6379,db=0&gt;&gt;&gt;&quot; &quot;new_value&quot;
1684750490.821411 [0 127.0.0.1:47322] &quot;EXEC&quot;

The problem is that the instruction pipe.set(&#39;new_key:&#39; + str(testIndex), &#39;new_value&#39;) return:

Pipeline&lt;ConnectionPool&lt;Connection&lt;host=localhost,port=6379,db=0&gt;&gt;&gt;

instead of the value of the key testIndex after the execution of the INCRBY instruction.

Could someone explain me this behaviour?

答案1

得分: 1

The execute function returns a list of command responses from Redis, so your incr response should be the first thing in that list.

示例:

from redis import Redis

redis_client = Redis(decode_responses=True)

pipeline = redis_client.pipeline(transaction=False)

pipeline.incr("somekey", 1)
pipeline.set("hello", "world")
pipeline.get("hello")
responses = pipeline.execute()

print(responses)

输出:

$ python demo.py
[3, True, 'world']

版本信息:

$ cat requirements.txt
async-timeout==4.0.2
redis==4.5.5
$ python --version
Python 3.10.7
英文:

The execute function returns a list of command responses from Redis, so your incr response should be the first thing in that list.

Example:

from redis import Redis

redis_client = Redis(decode_responses=True)

pipeline = redis_client.pipeline(transaction=False)

pipeline.incr(&quot;somekey&quot;, 1)
pipeline.set(&quot;hello&quot;, &quot;world&quot;)
pipeline.get(&quot;hello&quot;)
responses = pipeline.execute()

print(responses)

Output:

$ python demo.py
[3, True, &#39;world&#39;]

Versions:

$ cat requirements.txt
async-timeout==4.0.2
redis==4.5.5
$ python --version
Python 3.10.7

</details>



# 答案2
**得分**: 0

根据 @Simon Prickett 的答案,特别感谢他的评论:

> 如果你需要操作这个值,要么先获取它,然后在执行你的“设置命令”时观察“somekey”键,或者使用在 Redis 服务器上原子执行这个逻辑的 Lua 脚本。

我已将我的代码修改如下:

```python
import redis

r = redis.Redis()
pipe = r.pipeline()

def redis_insertion():
    pipe.watch('testIndex')
    testIndex = int(r.get('testIndex'))
    pipe.multi()
    testIndex += 1
    pipe.set('testIndex', testIndex)
    pipe.set('new_key:' + str(testIndex), 'new_value')
    pipe.execute()
    pipe.reset()

redis_insertion()

在这种情况下,监视器显示:

> redis-cli monitor
OK
1684824514.507417 [0 127.0.0.1:46494] "WATCH" "testIndex"
1684824514.507815 [0 127.0.0.1:46496] "GET" "testIndex"
1684824514.508060 [0 127.0.0.1:46494] "MULTI"
1684824514.508073 [0 127.0.0.1:46494] "SET" "testIndex" "37"
1684824514.508080 [0 127.0.0.1:46494] "SET" "new_key:37" "new_value"
1684824514.508087 [0 127.0.0.1:46494] "EXEC"
1684824514.508670 [0 127.0.0.1:46494] "GET" "testIndex"

监视器的输出显示,在 Redis 数据库中已经正确插入了以下键:

  • testIndex=37 ("SET" "testIndex" "37")
  • new_key:37='new_value' ("SET" "new_key:37" "new_value")
英文:

By the answer of @Simon Prickett and especially thanks to his comment:
> If you need to work on the value then either get it first and watch the "somekey" key while you do your "set command", or use a Lua script that executes atomically on the redis server to perform this logic.

I have changed my code as below:

import redis

r = redis.Redis()
pipe = r.pipeline()

def redis_insertion():
    pipe.watch(&#39;testIndex&#39;)
    testIndex = int(r.get(&#39;testIndex&#39;))
    pipe.multi()
    testIndex += 1
    pipe.set(&#39;testIndex&#39;, testIndex)
    pipe.set(&#39;new_key:&#39; + str(testIndex), &#39;new_value&#39;)
    pipe.execute()
    pipe.reset()

redis_insertion()

In this case the monitor shows:

&gt; redis-cli monitor
OK
1684824514.507417 [0 127.0.0.1:46494] &quot;WATCH&quot; &quot;testIndex&quot;
1684824514.507815 [0 127.0.0.1:46496] &quot;GET&quot; &quot;testIndex&quot;
1684824514.508060 [0 127.0.0.1:46494] &quot;MULTI&quot;
1684824514.508073 [0 127.0.0.1:46494] &quot;SET&quot; &quot;testIndex&quot; &quot;37&quot;
1684824514.508080 [0 127.0.0.1:46494] &quot;SET&quot; &quot;new_key:37&quot; &quot;new_value&quot;
1684824514.508087 [0 127.0.0.1:46494] &quot;EXEC&quot;
1684824514.508670 [0 127.0.0.1:46494] &quot;GET&quot; &quot;testIndex&quot;

The output of the monitor shows that in the Redis DB have been correctly inserted the keys:

  • testIndex=37 (&quot;SET&quot; &quot;testIndex&quot; &quot;37&quot;)
  • new_key:37='new_value' (&quot;SET&quot; &quot;new_key:37&quot; &quot;new_value&quot;)

huangapple
  • 本文由 发表于 2023年5月22日 18:29:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305257.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定