X Tutup
The Wayback Machine - https://web.archive.org/web/20201011105026/https://github.com/Snailclimb/JavaGuide/issues/491
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于 redis 没有事务回滚? #491

Open
fangjunpang opened this issue Oct 2, 2019 · 3 comments
Open

关于 redis 没有事务回滚? #491

fangjunpang opened this issue Oct 2, 2019 · 3 comments

Comments

@Rylynnnnn
Copy link

@Rylynnnnn Rylynnnnn commented Oct 2, 2019

看一下官方文档 https://redis.io/topics/transactions

Errors inside a transaction

During a transaction it is possible to encounter two kind of command errors:
A command may fail to be queued, so there may be an error before EXEC is called. For instance the command may be syntactically wrong (wrong number of arguments, wrong command name, ...), or there may be some critical condition like an out of memory condition (if the server is configured to have a memory limit using the maxmemory directive).
A command may fail after EXEC is called, for instance since we performed an operation against a key with the wrong value (like calling a list operation against a string value).
Clients used to sense the first kind of errors, happening before the EXEC call, by checking the return value of the queued command: if the command replies with QUEUED it was queued correctly, otherwise Redis returns an error. If there is an error while queueing a command, most clients will abort the transaction discarding it.

However starting with Redis 2.6.5, the server will remember that there was an error during the accumulation of commands, and will refuse to execute the transaction returning also an error during EXEC, and discarding the transaction automatically.

Before Redis 2.6.5 the behavior was to execute the transaction with just the subset of commands queued successfully in case the client called EXEC regardless of previous errors. The new behavior makes it much more simple to mix transactions with pipelining, so that the whole transaction can be sent at once, reading all the replies later at once.

Errors happening after EXEC instead are not handled in a special way: all the other commands will be executed even if some command fails during the transaction.

This is more clear on the protocol level. In the following example one command will fail when executed even if the syntax is right:

Why Redis does not support roll backs?

If you have a relational databases background, the fact that Redis commands can fail during a transaction, but still Redis will execute the rest of the transaction instead of rolling back, may look odd to you.

However there are good opinions for this behavior:

Redis commands can fail only if called with a wrong syntax (and the problem is not detectable during the command queueing), or against keys holding the wrong data type: this means that in practical terms a failing command is the result of a programming errors, and a kind of error that is very likely to be detected during development, and not in production.
Redis is internally simplified and faster because it does not need the ability to roll back.
An argument against Redis point of view is that bugs happen, however it should be noted that in general the roll back does not save you from programming errors. For instance if a query increments a key by 2 instead of 1, or increments the wrong key, there is no way for a rollback mechanism to help. Given that no one can save the programmer from his or her errors, and that the kind of errors required for a Redis command to fail are unlikely to enter in production, we selected the simpler and faster approach of not supporting roll backs on errors.

@fangjunpang
Copy link
Author

@fangjunpang fangjunpang commented Oct 3, 2019

没懂他的意思,是说redis不支持回滚,但是又保持原子性,这个我没理解

@LiWenGu
Copy link
Contributor

@LiWenGu LiWenGu commented Oct 11, 2019

没懂他的意思,是说redis不支持回滚,但是又保持原子性,这个我没理解

首先原子性的定义:事务中的命令要么全部被执行,要么全部都不执行。

然后再看官方文档关键段:
Redis commands can fail during a transaction, but still Redis will execute the rest of the transaction instead of rolling back

Redis 在事务失败时不进行回滚,而是继续执行余下的命令


我根据Redis文档理解,认为事务过程中失败有两种可能:

  1. Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令中用在了错误类型的键上面,所以如果在生产环境中你使用的正常命令,那么在 Redis 事务中,是不会出现错误而导致回滚的。

来自文档:Redis commands can fail only if called with a wrong syntax...

  1. 事务执行一半,Redis宕机
    如果 Redis 服务器因为某些原因被管理员杀死,或者遇上某种硬件故障,那么可能只有部分事务命令会被成功写入到磁盘中。
    如果 Redis 在重新启动时发现 AOF 文件出了这样的问题,那么它会退出,并汇报一个错误。
    使用redis-check-aof程序可以修复这一问题:它会移除 AOF 文件中不完整事务的信息,确保服务器可以顺利启动

  2. 而且回滚实现很复杂,需要解决事务回滚覆盖的情况。

综上:所以Redis 没有事务回滚

这是中文文档地址:http://www.redis.cn/topics/transactions.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
4 participants
You can’t perform that action at this time.
X Tutup