ARM Mac (M1) 에서 embedded-redis 사용하기

Adami·2021년 1월 18일
1
post-thumbnail

Reids 를 사용하는 프로젝트라면 로컬 프로파일에서 embedded-redis 를 많이 사용하는데

새로 구입한 ARM Mac 에서 아래처럼 구동이 안되는 문제가 있었다.

Caused by: java.lang.RuntimeException: Can't start redis server. Check logs for details.

로그를 확인 하라는데 어디서 확인할 수 있는지 알 수가 없다.

그래서 라이브러리 코드를 디버깅 해 찾아보니 아래 부분에서 에러가 발생한다.

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);
    }
}

레디스 프로세스를 띄우고 stdout 을 받아서 실행되었는지 확인하는 듯 하다.

디버거로 reader 의 값을 받아보면

=== REDIS BUG REPORT START: Cut & paste starting from here ===
[8366] 14 Jan 18:14:28.233 #     Redis 2.8.19 crashed by signal: 10

...

os:Darwin 20.2.0 x86_64

...

임베디드 redis 라이브러리에서 mac_arm64 용 바이너리가 준비되지 않은 것이 원인인 것을 알 수 있다.

https://github.com/kstyrc/embedded-redis/blob/master/src/main/java/redis/embedded/RedisExecProvider.java
private void initExecutables() {
    executables.put(OsArchitecture.WINDOWS_x86, "redis-server-2.8.19.exe");
    executables.put(OsArchitecture.WINDOWS_x86_64, "redis-server-2.8.19.exe");

    executables.put(OsArchitecture.UNIX_x86, "redis-server-2.8.19-32");
    executables.put(OsArchitecture.UNIX_x86_64, "redis-server-2.8.19");

    executables.put(OsArchitecture.MAC_OS_X_x86, "redis-server-2.8.19.app");
    executables.put(OsArchitecture.MAC_OS_X_x86_64, "redis-server-2.8.19.app");
}

라이브러리의 소스코드에도 MAC_OS_X_arm64 가 없는 것을 알 수 있다.

라이브러리를 수정해 사용할 수도 있겠지만, 문서에서는 사용자가 바이너리를 지정해 사용하는 방법을 제시하고 있다.

하지만 1번같은 경우는 RedisServer(String, int) 가 deprecate 되었는지 동작하지 않았고

2번은 Architecture enum 에 arm64 가 없어 사용할 수 없었다.

1번 방법 대신 RedisServer(File executable, int port) 생성자가 제공되는듯 해 이걸 사용해 문제를 해결하기로 했다.

우선 Redis 의 소스코드를 받아 컴파일한다.

$ wget https://download.redis.io/releases/redis-6.0.10.tar.gz
--2021-01-14 18:26:30--  https://download.redis.io/releases/redis-6.0.10.tar.gz
Resolving download.redis.io (download.redis.io)... 45.60.125.1
Connecting to download.redis.io (download.redis.io)|45.60.125.1|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2271970 (2.2M) [application/octet-stream]
Saving to: ‘redis-6.0.10.tar.gz’

redis-6.0.10.tar.gz 100%[===================>]   2.17M  --.-KB/s    in 0.09s

2021-01-14 18:26:30 (23.3 MB/s) - ‘redis-6.0.10.tar.gz’ saved [2271970/2271970]

$ tar -xzf redis-6.0.10.tar.gz
$ cd redis-6.0.10
$ make

...

$ src/redis-server
9566:C 14 Jan 2021 18:28:34.049 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
9566:C 14 Jan 2021 18:28:34.049 # Redis version=6.0.10, bits=64, commit=00000000, modified=0, pid=9566, just started
9566:C 14 Jan 2021 18:28:34.049 # Warning: no config file specified, using the default config. In order to specify a config file use src/redis-server /path/to/redis.conf
9566:M 14 Jan 2021 18:28:34.051 * Increased maximum number of open files to 10032 (it was originally set to 256).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 6.0.10 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 9566
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

9566:M 14 Jan 2021 18:28:34.053 # Server initialized
9566:M 14 Jan 2021 18:28:34.053 * Ready to accept connections

src/redis-server 에 생성된 바이너리의 이름을 바꿔 프로젝트에 추가한다.

그리고 EmbeddedRedisConfig 에 아키텍쳐를 확인해 분기하는 코드를 추가한다.

override fun afterPropertiesSet() {
    // for support MAC_ARM64 Arch
    redisServer = if (isArmMac()) {
        RedisServer(getRedisFileForArmMac(), redisPort!!)
    } else {
        RedisServer(redisPort!!)
    }

    redisServer!!.start()
}

private fun isArmMac(): Boolean {
    return System.getProperty("os.arch") == "aarch64" &&
            System.getProperty("os.name") == "Mac OS X"
}

private fun getRedisFileForArmMac(): File {
    return ClassPathResource("binary/redis/redis-server-6.0.10-mac-arm64").file
}

이렇게 하면 잘 실행된다.

[Redis] SpringBoot Data Redis 로컬/통합 테스트 환경 구축하기

profile
개발자

3개의 댓글

comment-user-thumbnail
2021년 1월 28일

안녕하세요.
src/redis-server 에 생성된 바이너리가 어떤걸까요? src/redis-server 파일인가요 ? 그 파일을 변경해서 실행하니 Permission denied가 뜨더라고요. ㅠ.ㅠ.

1개의 답글