STOVE-Milk/steam-clone

[BE / 로비서버] Redis map 데이터 동시성 접근 오류, 성능 저하

Closed this issue · 1 comments

기존 방식

  • map을 String으로 저장하다보니 sync 시 redis의 String형 map 데이터를 가져와서 MapDto Object로 변환해줌
  • 변환 자체의 로직은 문제 없으나 동시에 접근하면서 문제가 발생함
  • 성능적으로 필요 없는 map 데이터를 많이 불러와서 변환(Deserialize)하는 것은 문제
    • 현재 sync는 맵 업데이트, 입장 시의 데이터 동기화를 위해 자주 호출되지는 않음
    • move에 따른 동기화가 많이 필요하다면 문제
      • map을 필요할때만 불러오고, 평상시에는 map을 제외한 로딩이 필요함

해결 방법 생각

  • redisTemplate를 이용한 직접적인 쿼리
  • template.opsForValue().set("key", "value");

Before Code

public synchronized void moveUserInRedis(String roomId, String movedUserId, Direction direction) {
    Optional<RoomCache> opRoomCache = roomCacheRepository.findById(roomId);
    RoomCache roomCache;
    if(opRoomCache.isPresent()) {
        roomCache = opRoomCache.get();
        roomCache.moveUser(movedUserId, direction);
        roomCacheRepository.save(roomCache);
    }
}

public synchronized void moveUser(String userId, Direction direction) {
    this.getUsers().get(userId).move(direction, Integer.parseInt(JsonUtil.parse(this.map, "side").toString()));
}

public void move(Direction direction, Integer max) {
    switch (direction) {
        case UP:
            if(y < max)
                y++;
            break;
        case RIGHT:
            if(x < max)
                x++;
            break;
        case DOWN:
            if(y > 0)
                y--;
            break;
        case LEFT:
            if (x > 0)
                x--;
            break;
    }
}

after code

public synchronized void moveUserInRedis(String roomId, String movedUserId, Direction direction) {
    HashOperations<String, String, Integer> hash = redisTemplate.opsForHash();
    String mainKey = "library:1";
    String hashKey = "users.[" + movedUserId + "].";
    switch (direction) {
        case UP:
            hashKey += 'y';
            if(hash.get(mainKey, hashKey) < MAX_SIDE_OF_MAP)
                hash.increment(mainKey, hashKey, 1);
            break;
        case RIGHT:
            hashKey += 'x';
            if(hash.get(mainKey, hashKey) < MAX_SIDE_OF_MAP)
                hash.increment(mainKey, hashKey, 1);
            break;
        case DOWN:
            hashKey += 'y';
            if(hash.get(mainKey, hashKey) > 0)
                hash.increment(mainKey, hashKey, -1);
            break;
        case LEFT:
            hashKey += 'x';
            if(hash.get(mainKey, hashKey) > 0)
                hash.increment(mainKey, hashKey, -1);
            break;
    }
}