英文:
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('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?
答案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("somekey", 1)
pipeline.set("hello", "world")
pipeline.get("hello")
responses = pipeline.execute()
print(responses)
Output:
$ python demo.py
[3, True, 'world']
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('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()
In this case the monitor shows:
> 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"
The output of the monitor shows that in the Redis DB have been correctly inserted the keys:
- testIndex=37 (
"SET" "testIndex" "37"
) - new_key:37='new_value' (
"SET" "new_key:37" "new_value"
)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论