今天在做应用的单元测试时,遇到一个使用embedded-redis的问题,记录如下:
在启动单元测试时,本地的redisServer启动失败,异常栈信息如下:
java.lang.RuntimeException: Can't start redis server. Check logs for details.
at redis.embedded.AbstractRedisInstance.awaitRedisServerReady(AbstractRedisInstance.java:61)
at redis.embedded.AbstractRedisInstance.start(AbstractRedisInstance.java:39)
at redis.embedded.RedisServer.start(RedisServer.java:9)
抛出异常的代码位置如下:
private void awaitRedisServerReady() throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(redisProcess.getInputStream()));
try {
String outputLine;
do {
outputLine = reader.readLine();
if (outputLine == null) {
// Something goes wrong. Stream is ended before server was activated.
throw new RuntimeException("Can't start redis server. Check logs for details.");
}
} while (!outputLine.matches(redisReadyPattern()));
} finally {
IOUtils.closeQuietly(reader);
}
}
通过源代码可以看出,redis进程启动之后,程序会读取redis进程的启动日志,然后和redisReadyPattern()方法返回的正则表达式做匹配,如果启动日志可以和指定的正则匹配上就算启动成功,正则表达式如下:
.*The server is now ready to accept connections on port.*
Redis进程启动失败时,我通过debug记录了RedisServer启动日志,如下:
[19124] 27 Jun 22:01:56.481 #
The Windows version of Redis allocates a memory mapped heap for sharing with
the forked process used for persistence operations. In order to share this
memory, Windows allocates from the system paging file a portion equal to the
size of the Redis heap. At this time there is insufficient contiguous free
space available in the system paging file for this operation (Windows error
0x5AF). To work around this you may either increase the size of the system
paging file, or decrease the size of the Redis heap with the --maxheap flag.
Sometimes a reboot will defragment the system paging file sufficiently for
this operation to complete successfully.
Please see the documentation included with the binary distributions for more
details on the --maxheap flag.
Redis can not continue. Exiting.
分析错误日志可以得出,Redis在启动时需要申请一块儿连续的内存空间,但此时没有足够的连续内存空间,所以启动失败。
解决问题的方法比较简单。因为启动redis是用于单元测试,并不需要太大内存,把内存设置小一些即可:
// 利用setting设置最大内存为200m,还可以更小,看自己计算机上的可用内存而定
RedisServer redisServer = RedisServer.builder().setting("maxheap 200m").port(6379).setting("bind localhost").build();
redisServer.start();