提交 18534064 编写于 作者: J jonathan pickett

merge antirez changes 2.8.15-->2.8.16

...@@ -14,6 +14,39 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade! ...@@ -14,6 +14,39 @@ HIGH: There is a critical bug that may affect a subset of users. Upgrade!
CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP. CRITICAL: There is a critical bug affecting MOST USERS. Upgrade ASAP.
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
--[ Redis 2.8.16 ] Release date: 16 Sep 2014
# UPGRADE URGENCY: HIGH for Redis if you are using 2.8.15 + AOF.
LOW for Sentinel.
* [FIX] The ability to load truncated AOF files introduced with Redis 2.8.15
contains a bug fixed in this release: after loading the file was not
truncated to the last valid command, so the new commands are appended
after a non well formed command. This means that:
1) The first AOF rewrite triggered by the server will automatically
fix the problem.
2) However, if the server is restarted before the rewrite, Redis may
not be able to load the file and you need to manually fix it.
In order to fix a corrupted file you should start the redis-check-aof
utility WITHOUT the --fix option, just to check the offset where the
corruption is found. Around the offset reported by the check utility
you'll find, inside your AOF file, a command which is not complete
according to the Redis protocol. Just remove this incomplete command
leafing the file unaltered before and after the offending command,
and restart the server.
IMPORTANT #1: Redis 2.8.15 is the only stable version of Redis with
this bug so probably no actual real-world problem happened since the
problem is automatically fixed at the first automatic AOF rewrite.
IMPORTANT #2: Before upgrading to Redis 2.8.16, if you are using Redis
2.8.15 with AOF enabled, make sure to trigger a manual AOF rewrite
using the BGREWRITEAOF command.
* [FIX] SAVE is no longer propagated to AOF / slaves.
--[ Redis 2.8.15 ] Release date: 12 Sep 2014 --[ Redis 2.8.15 ] Release date: 12 Sep 2014
# UPGRADE URGENCY: LOW for Redis, HIGH for Sentinel. # UPGRADE URGENCY: LOW for Redis, HIGH for Sentinel.
......
...@@ -579,6 +579,7 @@ int loadAppendOnlyFile(char *filename) { ...@@ -579,6 +579,7 @@ int loadAppendOnlyFile(char *filename) {
struct redis_stat sb; struct redis_stat sb;
int old_aof_state = server.aof_state; int old_aof_state = server.aof_state;
long loops = 0; long loops = 0;
off_t valid_up_to = 0; /* Offset of the latest well-formed command loaded. */
if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) { if (fp && redis_fstat(fileno(fp),&sb) != -1 && sb.st_size == 0) {
server.aof_current_size = 0; server.aof_current_size = 0;
...@@ -672,6 +673,7 @@ int loadAppendOnlyFile(char *filename) { ...@@ -672,6 +673,7 @@ int loadAppendOnlyFile(char *filename) {
/* Clean up. Command code may have changed argv/argc so we use the /* Clean up. Command code may have changed argv/argc so we use the
* argv/argc of the client instead of the local variables. */ * argv/argc of the client instead of the local variables. */
freeFakeClientArgv(fakeClient); freeFakeClientArgv(fakeClient);
if (server.aof_load_truncated) valid_up_to = ftello(fp);
} }
/* This point can only be reached when EOF is reached without errors. /* This point can only be reached when EOF is reached without errors.
...@@ -696,9 +698,27 @@ readerr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */ ...@@ -696,9 +698,27 @@ readerr: /* Read error. If feof(fp) is true, fall through to unexpected EOF. */
uxeof: /* Unexpected AOF end of file. */ uxeof: /* Unexpected AOF end of file. */
if (server.aof_load_truncated) { if (server.aof_load_truncated) {
redisLog(REDIS_WARNING,"!!! Warning: short read while loading the AOF file !!!"); redisLog(REDIS_WARNING,"!!! Warning: short read while loading the AOF file !!!");
redisLog(REDIS_WARNING, redisLog(REDIS_WARNING,"!!! Truncating the AOF at offset %llu !!!",
"AOF loaded anyway because aof-load-truncated is enabled"); (unsigned long long) valid_up_to);
goto loaded_ok; if (valid_up_to == -1 || truncate(filename,valid_up_to) == -1) {
if (valid_up_to == -1) {
redisLog(REDIS_WARNING,"Last valid command offset is invalid");
} else {
redisLog(REDIS_WARNING,"Error truncating the AOF file: %s",
strerror(errno));
}
} else {
/* Make sure the AOF file descriptor points to the end of the
* file after the truncate call. */
if (server.aof_fd != -1 && lseek(server.aof_fd,0,SEEK_END) == -1) {
redisLog(REDIS_WARNING,"Can't seek the end of the AOF file: %s",
strerror(errno));
} else {
redisLog(REDIS_WARNING,
"AOF loaded anyway because aof-load-truncated is enabled");
goto loaded_ok;
}
}
} }
redisLog(REDIS_WARNING,"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server."); redisLog(REDIS_WARNING,"Unexpected end of file reading the append only file. You can: 1) Make a backup of your AOF file, then use ./redis-check-aof --fix <filename>. 2) Alternatively you can set the 'aof-load-truncated' configuration option to yes and restart the server.");
exit(1); exit(1);
......
...@@ -2000,6 +2000,7 @@ void call(redisClient *c, int flags) { ...@@ -2000,6 +2000,7 @@ void call(redisClient *c, int flags) {
c->cmd->proc(c); c->cmd->proc(c);
duration = ustime()-start; duration = ustime()-start;
dirty = server.dirty-dirty; dirty = server.dirty-dirty;
if (dirty < 0) dirty = 0;
/* When EVAL is called loading the AOF we don't want commands called /* When EVAL is called loading the AOF we don't want commands called
* from Lua to go into the slowlog or to populate statistics. */ * from Lua to go into the slowlog or to populate statistics. */
......
#define REDIS_VERSION "2.8.15" #define REDIS_VERSION "2.8.16"
...@@ -39,14 +39,41 @@ tags {"aof"} { ...@@ -39,14 +39,41 @@ tags {"aof"} {
## Should also start with truncated AOF without incomplete MULTI block. ## Should also start with truncated AOF without incomplete MULTI block.
create_aof { create_aof {
append_to_aof [formatCommand set foo hello] append_to_aof [formatCommand incr foo]
append_to_aof [string range [formatCommand set bar world] 0 end-1] append_to_aof [formatCommand incr foo]
append_to_aof [formatCommand incr foo]
append_to_aof [formatCommand incr foo]
append_to_aof [formatCommand incr foo]
append_to_aof [string range [formatCommand incr foo] 0 end-1]
} }
start_server_aof [list dir $server_path aof-load-truncated yes] { start_server_aof [list dir $server_path aof-load-truncated yes] {
test "Short read: Server should start if load-truncated is yes" { test "Short read: Server should start if load-truncated is yes" {
assert_equal 1 [is_alive $srv] assert_equal 1 [is_alive $srv]
} }
set client [redis [dict get $srv host] [dict get $srv port]]
test "Truncated AOF loaded: we expect foo to be equal to 5" {
assert {[$client get foo] eq "5"}
}
test "Append a new command after loading an incomplete AOF" {
$client incr foo
}
}
# Now the AOF file is expected to be correct
start_server_aof [list dir $server_path aof-load-truncated yes] {
test "Short read + command: Server should start" {
assert_equal 1 [is_alive $srv]
}
set client [redis [dict get $srv host] [dict get $srv port]]
test "Truncated AOF loaded: we expect foo to be equal to 6 now" {
assert {[$client get foo] eq "6"}
}
} }
## Test that the server exits when the AOF contains a format error ## Test that the server exits when the AOF contains a format error
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册