Analysis of Redis transaction and improvement of the transaction characteristics of Redis
How many of the data acid properties are met?
To keep it simple, Redis transactions guarantee consistency and isolation;
Not satisfying atomicity and permanence;
Atomic Nature
Redis transaction encounters an error midway through execution, does not rollback, but continues execution of subsequent commands; (atomicity violation)
Transactions can be understood as a packaged batch execution script, but bulk instructions are not atomic operations;
The failure of an instruction in the middle does not result in the rollback of the previous instruction, nor does it cause subsequent instructions to be made;
Like what:
redis 127.0.0.1:7000> multiOKredis 127.0.0.1:7000> set a aaaQUEUEDredis 127.0.0.1:7000> set b bbbQUEUEDredis 127.0.0.1:7000> set c cccQUEUEDredis 127.0.0.1:7000> exec1) OK2) OK3) OK
If the set B BBB fails, set a succeeds and does not roll back, and set C will continue to execute;
Durability
A transaction is simply a queue that wraps up a set of REDIS commands and does not provide any additional persistence functionality, so the persistence of the transaction is determined by the persistence mode used by Redis:
- In pure memory mode, transactions are definitely not durable.
- In RDB mode, the server may fail after the transaction executes and before the Rdb file is updated, so Redis transactions in RDB mode are not persistent.
- In AOF "Always SYNC" mode, each command of a transaction is immediately called Fsync or Fdatasync to write the transaction data to the AOF file after successful execution. However, this save is performed by a background thread, and the main thread is not blocked until the save succeeds, so there is a very small interval between the execution of the command and the data being saved to the hard disk, so the transaction in this mode is not persistent.
- Other AOF modes are similar to "Always SYNC" mode, so they are not persistent.
Isolation and consistency
Redis transactions do not process other commands during execution, but wait for all commands to execute before processing other commands (to satisfy isolation)
Redis transactions can guarantee data consistency when an error occurs during execution or the process is terminated (see Resources 1)
Defects in Redis transactions
In addition to not guaranteeing atomicity and durability, the following problems apply in practice:
1) If a query is encountered in the middle of the transaction, will not return the results;
After setting the transaction start flag, all commands are queued, even the query instruction;
If the subsequent update operation relies on the preceding query directives, the Redis transaction is unable to complete the task effectively;
For example:
redis 127.0.0.1:7000> multiOKredis 127.0.0.1:7000> set a aaaQUEUEDredis 127.0.0.1:7000> get bQUEUED业务逻辑...redis 127.0.0.1:7000> set c cccQUEUEDredis 127.0.0.1:7000> exec1) OK2) bbb3) OK
The second step get a returns a queued, not a query result,
If a subsequent set operation relies on the result of a get (there is a dependency on the business logic), the get operation cannot be placed in the transaction operation;
2) Each command in the transaction has a network interaction with the Redis server;
When a Redis transaction is specified to start, the execution of a transaction returns the queued, is the queued operation implemented on the client side or on the server?
View the source code, it is easy to find the server-side implementation;
In the REDIS.C, there is this passage:
int processCommand(redisClient *c) {... /* Exec the command */ if (c->flags & REDIS_MULTI && c->cmd->proc != execCommand && c->cmd->proc != discardCommand && c->cmd->proc != multiCommand && c->cmd->proc != watchCommand) { queueMultiCommand(c); // 将事务中的命令都放入到队列中,然后返回"QUEUED" addReply(c,shared.queued); } else { if (server.vm_enabled && server.vm_max_threads > 0 && blockClientOnSwappedKeys(c)) return REDIS_ERR; //调用该命令函数来处理命令 call(c); } return REDIS_OK;}
This involves the client and the server side of the multiple interaction, clearly is the need to execute a batch of n commands, but also through multiple network interaction, some waste;
Query implementations in update operations
If there is such a demand: After the beginning of the transaction, the middle of the query logic interspersed;
The use of Redis transactions (libraries) does not satisfy this requirement;
Possible solutions:
Can consider the use of multiple libraries, read and write separation, query library is only used to query, update the library to open transactions to write operations;
You no longer use Redis's transaction instructions to bulk package the commands to be executed on the client, decide whether to roll back or all, so that the query logic can be executed at the interval of the update, without having to advance the query logic to the multi of the transaction instruction;
Advance the query business logic and strictly standardize code authoring requirements, all of the Redis query logic is placed outside the transaction:
redis 127.0.0.1:7000> get b bbb 业务逻辑... redis 127.0.0.1:7000> multi OK redis 127.0.0.1:7000> set a aaa QUEUED redis 127.0.0.1:7000> set c ccc QUEUED redis 127.0.0.1:7000> exec 1) OK 2) OK
Optimize network features
Package multiple commands to a Redis server for execution, reduce network interaction, optimize performance, and possible solutions:
- For all get/set operations, the existing Mget/mset directives can be used;
- For a variety of different types of update operations, the LUA script can be used to package the command, sent to the server side of the execution;
Reference
Http://redisbook.readthedocs.org/en/latest/feature/transaction.html
Posted by: Big CC | 10mar,2015
Blog: blog.me115.com [Subscribe]
Weibo: Sina Weibo
Analysis and improvement of Redis transactions