포스트

2022-07-18-TIL

2022-07-18-TIL

Today I Learned

Elasticsearch

검색엔진이란?

네이버, 다음, 구글 뿐만 아니라 쇼핑몰, SNS 등 여러 분야에서 검색기능을 활용

RDB의 LIKE '%키워드%' 검색은 인덱스를 타지 못해 데이터가 늘수록 느려지고, 형태소 분석이나 관련도 순 정렬 같은 기능도 없다. 검색엔진은 문서를 미리 토큰 단위로 쪼개 “토큰 → 그 토큰이 들어 있는 문서 목록” 형태의 역색인(inverted index)을 만들어 두고, 질의가 오면 토큰으로 문서를 바로 찾은 뒤 관련도 점수로 정렬한다.

Elasticsearch

단순히 검색을 목적으로 하는 것 뿐만 아니라 집계 및 통계 기록을 편리하게 볼 수 있게 해준다.

Elasticsearch는 Lucene 기반의 분산 검색·분석 엔진이다. 데이터는 JSON 문서로 인덱스에 저장되고, 인덱스는 샤드로 나뉘어 여러 노드에 분산되며 복제본(replica)으로 장애에 대비한다. REST API로 문서를 넣고 Query DSL로 검색하며, aggregation으로 그룹별 통계를 낸다. 로그 수집기(Logstash, Beats)와 시각화 도구(Kibana)를 묶어 ELK 스택으로 많이 쓴다. 마지막 링크(엘라스틱서치 가이드북)는 설치부터 시작하는 한국어 입문서다.

  • https://tecoble.techcourse.co.kr/post/2021-10-19-elasticsearch/

https://esbook.kimjmin.net/02-install/2.1


Git

Git은 변경분(diff)이 아니라 스냅샷을 저장한다. .git/objects 아래에 파일 내용(blob), 디렉터리 구조(tree), 커밋 메타데이터와 부모 커밋 포인터(commit)를 내용의 해시를 이름으로 저장하고, 브랜치는 특정 커밋을 가리키는 포인터일 뿐이다. 같은 내용의 파일은 같은 해시를 가지므로 한 번만 저장된다. 이 구조를 알면 브랜치 생성이 왜 가벼운지, rebase가 왜 커밋 해시를 바꾸는지 이해하기 쉽다.

  • https://inpa.tistory.com/entry/GIT-%E2%9A%A1%EF%B8%8F-%EA%B0%9C%EB%85%90-%EC%9B%90%EB%A6%AC-%EC%89%BD%EA%B2%8C%EC%9D%B4%ED%95%B4

https://medium.com/happyprogrammer-in-jeju/git-%EB%82%B4%EB%B6%80-%EA%B5%AC%EC%A1%B0%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90-1-%EA%B8%B0%EB%B3%B8-%EC%98%A4%EB%B8%8C%EC%A0%9D%ED%8A%B8-81b34f85fe53


액션로그, 액세스로그, 서비스로그

로그는 목적에 따라 나누어 다루는 것이 좋다.

  • 액세스 로그: 웹 서버나 WAS가 요청마다 한 줄씩 남기는 기록이다. 시각, 클라이언트 IP, 메서드, URL, 응답 코드, 응답 시간 등이 들어간다. Tomcat은 AccessLogValve를 Engine, Host, Context 중 하나에 두어 남긴다(Tomcat 8.5: Access Logs).
  • 서비스(애플리케이션) 로그: 애플리케이션 코드가 남기는 처리 과정과 에러 기록이다. 장애 분석의 주된 근거가 된다.
  • 액션 로그: 사용자가 어떤 화면에서 무엇을 클릭하고 구매했는지 같은 행동 기록이다. 분석과 지표 산출이 목적이라 스키마를 미리 정의하고 일관되게 남기는 것이 중요하다.

Elastic의 머신러닝 기능 중 이상 탐지(anomaly detection)는 이런 시계열 로그 데이터에서 평소와 다른 패턴을 찾아 준다. 요청 수나 에러율이 평소 범위를 벗어나는 시점을 사람이 임계값을 정하지 않아도 잡아낼 수 있다는 것이 장점이다.

https://www.elastic.co/guide/en/kibana/current/xpack-ml-anomalies.html


로그파일 남기기

Spring Boot는 기본적으로 콘솔에만 로그를 출력하고, logging.file.name이나 logging.file.path를 지정하면 파일에도 쓴다. 보존 기간, 파일 크기 기준 분할, 압축 같은 세부 정책은 logback-spring.xml에서 RollingFileAppender로 정한다.

1
2
3
4
5
6
7
8
9
10
11
12
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>logs/app.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
        <fileNamePattern>logs/app.%d{yyyy-MM-dd}.%i.log.gz</fileNamePattern>
        <maxFileSize>100MB</maxFileSize>
        <maxHistory>30</maxHistory>
        <totalSizeCap>10GB</totalSizeCap>
    </rollingPolicy>
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

Logback 문서에 따르면 롤링 주기는 fileNamePattern의 날짜 형식에서 추론된다. %d{yyyy-MM-dd}이면 하루 단위다. 시간·크기 기준 정책은 %d와 함께 %i 인덱스가 반드시 있어야 하고, 하루 안에서 maxFileSize를 넘으면 0, 1, 2 순서로 파일이 나뉜다. maxHistory는 남길 보관 파일 수, totalSizeCap은 보관 파일 전체 크기의 상한이며, 패턴이 .gz나 .zip으로 끝나면 롤링 직후 압축한다(Logback: RollingFileAppender). 위 예시의 숫자는 설명용 값이다.

  • https://harrydony.tistory.com/245
  • https://starseeds.tistory.com/48
  • https://awse2050.tistory.com/72
  • https://stackoverflow.com/questions/42648195/how-to-set-logback-xml-properties-in-application-yaml
  • https://stackoverflow.com/questions/29918323/how-to-configure-rolling-file-appender-within-spring-boots-application-yml
  • https://www.baeldung.com/logback
  • https://ayoteralab.tistory.com/entry/Spring-Boot-07-Logback-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0
  • https://gofnrk.tistory.com/107
  • https://frozenpond.tistory.com/88
  • https://dennis-xlc.gitbooks.io/the-logback-manual/content/en/chapter-4-appenders/logback-core/rollingfileappender/timebasedrollingpolicy.html
  • https://docs.spring.io/spring-boot/docs/current/reference/html/application-properties.html
  • https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.logging
  • https://www.tutorialworks.com/spring-boot-log-to-file/#:~:text=To%20make%20Spring%20Boot%20write%20its%20log%20to,set%20the%20path%20and%20filename.&text=With%20this%20configuration%2C%20Spring%20Boot,at%20the%20path%20you%20specify.
  • https://velog.io/@rivernine/Spring-boot-Logback%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%9C-%EB%A1%9C%EA%B7%B8%EC%A0%80%EC%9E%A5
  • https://shortstories.gitbook.io/studybook/logstash-_beats_c815_b9ac
  • https://tomcat.apache.org/tomcat-8.5-doc/config/context.html#Access_Logs

MySQL 데이터를 Elasticsearch로 옮기기

MySQL의 데이터를 Elasticsearch에서 검색하려면 데이터를 인덱스로 옮겨야 한다. 자주 쓰이는 방법은 Logstash의 JDBC input 플러그인이다. 지정한 SQL을 cron 형식 schedule로 주기 실행하고, 결과의 각 행을 이벤트 하나로, 각 컬럼을 필드로 바꾸어 Elasticsearch output으로 보낸다. use_column_value와 tracking_column을 설정하면 마지막으로 읽은 값(sql_last_value)을 파일에 기록해 두고 다음 실행에서 그 이후 데이터만 가져올 수 있다. JDBC 드라이버 jar는 플러그인에 포함되어 있지 않아서 jdbc_driver_library로 직접 지정해야 한다(Logstash JDBC input plugin).

이 방식은 SELECT 결과만 가져오므로 원본에서 삭제된 행은 알아채지 못한다. 삭제까지 반영하려면 소프트 삭제 컬럼을 두고 조회 조건에 포함하거나, binlog를 읽는 CDC 방식을 검토해야 한다.

  • https://velog.io/@broccoliindb/mysql-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A5%BC-elasticsearch%EB%A1%9C-%EA%B2%80%EC%83%89%ED%95%98%EA%B8%B0
  • https://drhot552.github.io/web/Logstash-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-mysql%EC%99%80-ElasticSearch-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0/#
  • https://m.blog.naver.com/olpaemi/221644176875
  • https://cyworld.tistory.com/815
  • https://hello-startup.tistory.com/4
  • https://choi-yud.tistory.com/10
  • https://meetup.toast.com/posts/149
참고한 자료외부 출처 3

외부 출처

이 글은 저작권자의 CC BY 4.0 라이선스를 따릅니다.

댓글

아직 댓글이 없습니다