2023-01-21
면접 전 질문 관련해서 찾아서 정리해놓은 것으로 오늘 TIL 은 대체...
.
.
.
.
Redis 관련 질문
현재 우리 프로젝트에서 캐시 사용중인 방법
Write-Around
캐시를 거치지 않고 무조건 디비에 저장한다. 그리고 조회 시, 캐시 미스의 경우에만 DB 에서 데이터를 가지고 와서 조회를 한다.
저장을 한번만 저장해서 간단하지만, 단점은 캐시와 DB 의 데이터가 맞지 않을 수 있다.
엘라스틱 캐시 사용안한 이유
엘라스틱 캐시는 레디스를 이용하는데 있어서 좀 더 확장적인 개념으로, 인 메모리 데이터 스토어 또는 캐시를 손쉽게 배포, 운영 및 확장할 수 있게 해주는 웹 서비스 이다. Redis 와 MemCached 두가지를 지원한다.
손쉽게 분산 인 메모리 캐시를 생성하고 확장할 수 있는 서비스 인데, 저희 같은 경우에는 굳이 유료인 엘라스틱 캐시를 사용할 필요가 없다고 판단했습니다.
엘라스틱 캐시 특징
● 다양한 데이터 구조, 스냅샷, 복제본 가능(Master, Slave), 트랜잭션, Pub/Sub, 루아 스크립트 지원, 위치기반 지원
● 빠른 오픈 소스 인 메모리 데이터 스토어 및 캐시.
● Redis의 간편한 사용성 및 능력과 더불어 가장 까다로운 애프리케이션에 적합한 가용성, 안정성 및 성능을 제공한다.
● 단일 노드와 최대 15개의 샤드 클러스터가 지원되므로 인 메모리 데이터를 3.55TIB 까지 확장이 가능하다.
● RDB 작업(특정 간격마다 모든 데이터를 디스크에 저장)이 매우 오래 걸린다.
● AWS, 60기가 메모리 기준으로 10분 소요, Redis 장애의 원인 대부분이 해당 기능 때문에 발생하기 때문에 사용에 주의해야 한다.
Redis MemCached 특징 간단 정리
Redis(Remote Dictionary Storage)
모든 데이터를 메모리에 저장하고 조회하는 인메모리 데이터베이스, 메모리 기반의 key-value 구조의 데이터 관리 시스템
String, set, hash, Sorted set, List(LinkedList) 저장 타입의 종류
싱글 스레드이기 때문에 한번에 한개의 명령어만 수행 가능하다.(MemCached 는 멀티 스레드를 지원한다.)
MemCached
분산 메모리 캐시 시스템이다. RAM에 데이터 및 오브젝트를 캐시함으로 데이터베이스 및 API 에서 읽어와야 하는 횟수를 줄일 수 있다.
서버 한 대에 장애가 발생해도 문제가 발생하지 않으며, 검색시간이 짧다. 디스크 영구 저장이 불가능하다.
레디스와 MemCached 차이
● 처리속도
- Redis : 데이터가 디스크와 메모리에 저장
- MemCached : 데이터가 메모리에만 저장
다만, keys 와 flushall 등의 명령어를 사용할 때, 맴캐쉬드는 1ms 정도가 소요되지만 레디스는 1초가 걸리는 차이가 있다.
● 데이터 저장 방식
- Redis : 데이터가 디스크에도 저장이 되기 때문에 데이터 복구 가능
- MemCached : 메모리에만 저장되기 때문에 프로세스가 죽거나, 장애 발생시 데이터 사라짐
● 만료일 지정방식
- 둘 다 동일
● 메모리 재사용
- Redis : 메모리를 재사용하지 않음, 명시적으로 데이터 제거 가능
- MemCached : 저장소 메모리를 재사용, 만료전에 더 이상 데이터를 넣을 메모리가 없으면 LRU 알고리즘에 따라 데이터 삭제
● 데이터 타입
- Redis : 다양한 데이터 타입 지원
- MemCached : 문자열만 지원
차이 요약
- Memcached는 write 시간에서 굉장히 고성능을 보이고, Redis는 write에 메모리를 효율적으로 사용합니다.
- Redis는 Memcached에 비해 더 나은 read 시간 및 메모리 사용 효율성을 보여줍니다.
- 또한, Redis는 key-value 삭제에서도 엄청난 성능을 보여주며, 메모리 관리도 효율적입니다.
- write 시간 이외에는 대부분의 성능에서 Redis가 우수함을 알 수 있습니다.
- 결론적으로 다양한 자료 구조를 지원하며, 성능면에서 우수한 결과를 내는 Redis를 사용하는 것이 좋다.
참고한 블로그 링크
[REDIS] 📚 캐시 데이터 영구 저장하는 방법 (RDB / AOF)
Redis 데이터의 영속성 (Redis Persistence) Redis는 In-memory DB 임에도 불구하고, 메모리 데이터를 disk에 저장할 수 있는 특징이 있다. 그래서 서버가 꺼진 후 restart되더라도, disk에 저장해놓은 데이타를
inpa.tistory.com
In-memory Redis vs Memcached 비교하기
개요 최근 캐시로 Redis를 많이 사용합니다. 많은 자료들과 우수한 성능, Spring에서 풍부한 기능 제공 등 다양한 이유가 있습니다. 이번 시간에는 Redis 이외에도 캐시로 유명한 Memcached를 알아보고
escapefromcoding.tistory.com
Redis 레디스 특징, 장단점, Memcached와 redis 비교
Redis 레디스 특징, 장단점, Memcached와 redis 비교 Redis(Remote Dictionary Storage, 레디스)는 모든 데이터를 메모리에 저장하고 조회하는 인메모리 데이터베이스, 메모리 기반의 key-value 구조의 데이터 관리
sudo-minz.tistory.com
Docker 를 사용안한 이유
본인이 사용하는 운영체제 위에서 VSC 또는 IDE 등의 통합개발환경을 설치하고 여러가지 라이브러리를 설치하고 사용하는데,
이것을 다른 사용환경에서도 사용하려면 또 같은것을 설치하는 작업의 반복인데, 왜냐면 각각의 환경이 모두 다르기 때문이다.
이러한 불편함을 해소하기 위한것이 VMWare 와 같은 가상머신이 존재한다. 가상머신 위에 환경을 구성하고 이미지를 설치하여 똑같은 환경에서
개발을 이어갈 수 있다. 그럼에도 불구하고 도커가 핫한 이유는 무엇인가...
가상 머신의 경우 컴퓨터 안에 가상의 컴퓨터 환경을 만들기 때문에 OS를 또 설치해야 한다는 부담도 존재한다.
반면 Docker 는 격리된 공간에 필요한 라이브러리, 실행파일만 담아놓고 사용하기 때문에 부담이 줄어든다.
운영체제의 모든 파일이 아닌 실행 파일만을 갖고 있기 때문에 리소스가 줄고 속도 향상에 매우 커다란 이점을 가져온다.
DB 나 Web Server 를 담고 있는 컨테이너 라고 하는데 이 안에 담겨있는 프로그램들을 이미지 라고 한다.
즉, 필요한 부분들만을 가져와서 컨테이너에 담아놓고 필요한 것만 뽑아 쓰는 것이 도커라고 한다.
참고한 블로그 링크
[Docker] 도커(Docker)란? 도커의 개념, 장점, 구조
목표 도커(Docker)의 개념에 대해서 이해하는 시간을 갖도록 하겠습니다. 개요 이번 학기에 캡스톤 디자인을 수강하는데, 개발 과정에서 도커를 활용해야하는 상황입니다. 도커와 더불어 쿠버네
chanos.tistory.com
● 레디스를 사용한 이유, 비회원 방식에 레디스를 적용한 이유
저희 프로젝트에서 비회원은 처음 생성 이후에 정보 변경이 일절 없으며, 만료 시간이 정해져 있는 휘발성 데이터이다.
그렇기 때문에 읽고, 쓰는 속도가 빠른 레디스를 선택했고 이를 Hash 형태로 관리하는것이 목적이었기에 MemCached 보다 Redis 를 선택했다.
또한 채팅에서도 사용했는데, 저희 프로젝트에서는 채팅의 비중이 높지않고 레디스의 pub/sub 방식은 메시지가 휘발성이라서 저장을 하지
않기에 더 가볍게 이용이 가능하다고 생각해서 Redis 를 이용하는것을 선택함
● ec2 하나의 레디스를 사용하지 않고 왜 따로 분리했는가
현재 저희가 사용중인 EC2 서버가 프리티어 1기가 한계이기 때문에, 한 서버에서 레디스도 같이 올리기 보다는 다른 EC2 서버에 올려서
본 서버에서의 사용을 줄여서 조금이라도 메모리를 더 확보하기 위해서 입니다.
● JPA 말고 다른 sql 을 사용하지 않은 이유
처음에는 QueryDsl 와 같은 다른 방식의 SQL 방식을 사용하려고 고민을 했었는데, 코드를 작성하면서 굳이 필요치 않다고 판단해서 기존에 사용하던 JPA 방식으로 사용하기로 결정했습니다.
● Redis 휘발성 관련
휘발성이면서 동시에 Disk 에 저장또한 가능하기 때문에 이는, Redis 의 데이터를 디스크에 기록하는 스냅샷 이라는 영속화 기능이 있다.
그래서 이 부분을 우리는 사용하지 않기 때문에, 휘발성이라고 이해하고 사용한 것 같습니다.
RDB
특정한 간격마다 메모리에 있는 레디스 데이터 전체를 디스크에 쓴다.
AOF
명령이 실행될 때 마다 데이터를 파일에 기록하여 데이터의 손실이 거의 없다.
● Redis 직렬화 관련(Serialization)
짧게 말하자면...
serialVersionUID 를 지정하지 않으면 컴파일러가 계산한 값을 부여하는데, 이렇게 되면 컴파일러에 따라 할당되는 값이 다를 수 있다.
serializable 를 상속하는 Class 의 경우 Class 의 versioning 용도로 serialVersionUID 변수를 사용한다.
이 때, serialVersionUID 값을 명시적으로 지정하지 않으면 Compiler 가 계산한 값을 부여한다.
컴파일러는 serializable Class 혹은 Outer Class 를 참고하여 만들기 때문에 만약 다른 클래스에 변경이 있으면
serialVersionUID 도 변경이 있을 수 있다.
직렬화 할 때와 역직렬화를 할 때 serialVersionUID 값이 다르면 InvalidClassExceptions 이 발생해서 저장된 값을 Restore 불가능
우선 순서를 말하자면...
자바에서 직렬화란 자바의 객체를 바이트의 배열로 변환을 해서 파일이나, 메모리, DB 등이 저장을 하는 과정을 말한다.
저장된 것을 다시 객체로 변화하는 과정을 역직렬화 라고 말한다.
직렬화를 할 때에는 serialVersionUID 를 저장을 하고, 객체로 다시 불러들일 때는 그 값을 체크하는 용도로 사용한다.
serialVersionUID 값을 파일 등으로 저장할 때에 해당하는 클래스의 버전이 맞는지 확인을 위한 중요 장치이다.
그런데 이를 작성하지 않으면 Java VM 에서 내부 알고리즘에 따라서 자동으로 작성하는데,
이는 어떤 JavaVM 을 사용하는지에 따라서 달라진다. 그래서 클라이언트가 windows 서버가 Linux 일 경우 JavaVM 이
다르므로, 이 값이 다르게 설정이 되므로 역직렬화를 할 때 익셉션이 발생할 수 있다.
implement Serializable 구현화 한 이유...
자바에서 직렬화란 객체 데이터를 바이트(Byte) 형태로 변환하는 것을 말한다.
바이트 단위로 변환하는 이유는 데이터를 외부 서버로 전송하기 위해서다. 객체를 DB에 저장하거나 파일로 저장한 객체를 전송하는 등의
상황에선 스트림을 통해 데이터를 보내는데 이 때 바이트 단위로 보내야 한다. 이는 반대의 상황에서도 같으며 다시 객체화 할 때 역직렬화가
일어나게 된다. 이런 이유로 서블릿 기반의 WAS 는 대부분 세션의 자바 직렬화를 지원한다.
레디스의 저장방식은 byte array 형식이기 때문에 직렬화를 하여 캐싱을 할 때 넘겨줘야 한다.
이 때 redisConfig 에서 직렬화 설정을 하거나 직접 엔티티에 직렬화 설정을 하는 방법이 있는데, 우리는 엔티티에 직접 설정하는 방법을 사용해서 ChatRoom 에서 직렬화를 구현했다.
기본 직렬화 형태를 사용하면..
시간이 더 걸린다는 점이 있습니다. 기본 직렬화 매커니즘은 그래프를 따라 전체를 흝기 때문입니다.
과한 저장공간을 차지할 수 도 있고, 기본 해당 객체의 그래프를 순환하면서 처리하므로 스택 오버플로우가 생기 수 도 있다.
레디스의 저장방식은 byte array 형식이다. 따라서 spring-data 에서 redis 를 편하게 쓸 수 있도록 keySerializer, valueSerializer 를 제공한다.
이를 설정하지 않으면 "\xac\xed\x00\x05t\x00\x03key" 이런식으로 표기된다. 사용시 RedisTemplate<Key, Value> 객체를 설정하여 Bean에 등록한다.
짧게 말하자면 직렬화는, 보통 파일이나 패킷 전송시에 '파싱할 수 있는 데이터를 만들기 위해' 사용 된다.
자바의 직렬화는 자바 시스템 내부에서 사용되는 객체 또는 데이터들을 외부의 자바 시스템에서도 사용할 수 있도록 바이트 형태로 데이터 변환하는 기술과 바이트로 변환된 데이터를 다시 객체로 변환하는 역직렬화를 포함한다.
시스템적으로 JVM의 Runtime Data Area(Heap 또는 스택영역)에 상주하고 있는 객체 데이터를 바이트 형태로 변환하는 기술과 직렬화된 바이트 형태의 데이터를 객체로 변환해서 JVM 으로 상주시키는 형태를 말하기도 한다.
기본(primitive)타입과 java.io.Serializable(현재 우리가 사용중임) 인터페이스를 상속받은 객체는 직렬화 할 수 있는 기본 조건을 가진다.
캐시에서도 직렬화는 사용됩니다. 주로 DB를 조회한 후 가져온 데이터 객체 같은 경우 실시간 형태로 요구하는 데이터가 아니라면 메모리, 외부 저장소, 파일 등을 저장소를 이용해서 데이터 객체를 저장한 후 동일한 요청이 오면 DB를 다시 요청하는 것이 아니라 저장된 객체를 찾아서 응답하게 하는 형태를 캐시를 사용한다라고 말합니다. 캐시를 이용하면 DB 리소스를 절약할 수 있기 때문에 많은 시스템에서 자주 활용됩니다. 이렇게 캐시할 부분을 자바 직렬화된 데이터를 저장해서 사용됩니다.
더더더더더더더더더덛더더더더 단순히 말하면
특정 정보(객체) 등이 메모리상에 올라가 있고 물리적으로 여기저기 분포되어 있거나 또는 메모리 특성에 맞게 data 들이 관리되고 있다.
이러한 정보를 네트워크를 통해 다른곳에 보내거나 파일로 저장하기 위해서 직렬화 라는 변환 과정을 거친다.
Lettuce, Jendis 비교 블로그 링크
Spring boot 2.0 부터는 Jedis가 deprecated 되었고 기본 지원이 Lettuce 로 바뀌었다.
Spring에서는 spring-data-redis라는 라이브러리를 제공하기 때문에 사용하면 쉽게 구현이 가능하다.
보통 jedis와 lettuce가 대표적으로 사용되는데 찾아보니 대부분 lettuce의 성능이 좋다는 말이 많고, 동기냐 비동기냐의 차이기 때문에 맛 보고 싶은 걸로 적용하면된다.
Lettuce는 Netty (비동기 이벤트 기반 고성능 네트워크 프레임워크) 기반의 Redis 클라이언트이다.
비동기로 요청을 처리하기 때문에 고성능을 자랑한다.
Lettuce는 TPS/CPU/Connection 개수/응답속도 등 전 분야에서 우위에 있다.
jedis는 thread-safe 하지 않다.(connection pool을 사용하여 multi thread 상황을 해결해야 한다)
lettuce는 multiple-thread 상황에서 safe하다.
Jedis vs Lettuce
- 이전에는 Jedis를 많이 사용하였지만 현재는 Lettuce를 많이 사용
- Jedis에 비해 성능이 월등히 우수
- 코드가 깔끔하게 디자인 되어 있으며 공식문서 정리가 잘 되어 있음
- Jedis의 경우 피드백을 거의 해주지 않음. but Lettuce는 즉각 처리
레디스 클러스터 기능은 3.0 부터 추가된 기능이다.
일단, 레디스 클러스터를 검토하기 전에 먼저 샤딩 또는 파티셔닝 이라는 단어를 이해해야 한다.
위에서 설명한 복제라는 단어와는 다른 개념이다. 복제는 데이터를 그대로 똑같이 다른 노드에 복사를 하는 것이고, 샤딩(파티셔닝) 은 데이터를 분산해서 저장하는 기법이다.
즉, 복제에 비해서 더 많은 데이터를 나눠서 저장할 수 있다. 아래와 같이 분산해서 저장하면, 위에서 구축했던 인프라에서 각 노드당 절반의 메모리만 사용하면 된다.
참고한 블로그 링크
클래스에 Serializable을 구현하는 이유(class implements Serializable)
질문: 자바책에는 객체를 파일에 저장하거나 파일에서 꺼내오기 위해서 또는 객체를 네트워크를 통해 전송하기 위해서는 미리 객체를 직렬화해야한다고 되어 있네요. 웹 어플 소스 분석하다보
developerhjg.tistory.com
Jedis 보다 Lettuce 를 쓰자
Java의 Redis Client는 크게 2가지가 있습니다. Jedis Lettuce 둘 모두 몇천개의 Star를 가질만큼 유명한 오픈소스입니다. 이번 시간에는 둘 중 어떤것을 사용해야할지에 대해 성능 테스트 결과를 공유하
jojoldu.tistory.com