View
627
Download
0
Category
Preview:
Citation preview
Real-time full-text search with Luwak and Samza
by Alan Woodward and Martin Kleppmann번역: 이명현 thicliwin@gmail.com
이 자료는...
• Martin Kleppmann 이 confluent.io 블로그로 올린 글을 번역한 자료입니다.
• 때문에 글의 진행과 내용이 원문의 그것과 같습니다.
• 번역 과정에서 다소 주관적인 해석이 들어가기도 했습니다.
• 원문을 읽어보시기를 추천드립니다.
검색의 변화
검색의 변화
• 전통적인 데이터
• 큰 규모의 코퍼스(corpus)
• 사용자의 필요에 따라서 그때 그때 필요한 내용을 코퍼스에서 검색한다
• 때때로 코퍼스 문서 내용에 변화가 있긴 하지만, 크게 변하지 않는다
• 빠르게 변화하는 데이터
• 문서가 들어오는대로 검색을 할 수 있으면 유용하다
• 뉴스 모니터링, 트위터 검색과 같은 경우에 적용 가능
여기서 소개하고자 하는 것은
• Luwak과 Samza를 연동해서 효율적이고 확장가능한 stream 검색엔진을 만드는 것
• Luwak
• Lucene-based library
• 단일 문서에 여러 쿼리를 수행할 수 있다
• Samza (+Kafka)
• Kafka 기반의 stream 처리 프레임워크
• 실시간 스트림 처리를 분산된 컴퓨터들에서 할 수 있도록 한다
Full-text search on stream
Full-text search on stream
• Solr나 Elasticsearch 와 같은 일반적인 검색엔진과 다른 문제들을 다뤄야 한다
• 데이터가 급속히 변화하는 경우에 그 중요성이 더 커진다
여기서 말하는 Stream은 무엇인가?
• 데이터의 모음
• 데이터의 ‘추가’만 가능하다
• 데이터들이 일정한 순서를 가지고 있다
• 예
• log file
• exception stack trace
• Producer
• Stream에 쓰기 작업을 하는 프로세스
• Consumer
• Stream으로 부터 읽는 프로세스
• can read entire file sequentially
• can use tail -f to watch new records
그렇다면 Stream을 어떻게 full-text 검색을 할까?
• 전통적인 방법
• 모든 것을 큰 색인에 올린다
• Elasticsearch 나 Solr 등을 사용해서
• ELK (Elasticsearch, Logstash and Kibana) is a trendy way
• 새로운 데이터가 추가된다
• 검색을 할 수 있도록 색인에 추가한다
• 색인 구성의 예: index of different time periods
• 어제
• 지난 1시간
• 지난 1분
• Near-real-time search 을 구성할 수 있다
• 위에 구성한 모든 색인에 검색을 한다
그렇다면 Stream 검색을 하는 곳은 어디가 있을까?
• 검색을 하면 지난 얼마간의 트윗들을 검색한다
• 어느 정도 시간이 지나면 새로운 트윗들이 결과에 추가된다
• 트위터는 검색 쿼리를 기억하고 새로운 트윗들 중에서 검색을 계속 수행한다.
• called firehose of tweets
• Google Alerts
• 사용자가 쿼리를 등록한다
• 검색에 매칭되는 페이지가 새로 등장하면 시스템이 알림을 보내준다
• Google Alerts 는 수집되는 문서들의 stream에서 등록된 쿼리와 매칭되는 문서를 검색하는 것
검색은 두가지로 나눠볼 수 있다
• After-the-fact search
• 과거의 문서들을 검색한다
• 모든 문서들을 큰 색인에 담는다
• Streaming search
• 쿼리를 문서보다 먼저 등록한다
• Stream에 나타나는 문서들을 등록된 쿼리들에 매칭한다
• 이 둘을 결합하는게 좋은 결과를 가져오기도 한다
• 7day search + stream search
• 비슷한 제품: Elasticsearch Percolator
Implementing Stream Search
Stream search, 단순한 접근 방법
• 극단적으로는 한 문서당 색인을 생성하고 등록된 모든 쿼리를 날려볼 수 있다.
• 하지만 위 방법은 효율적이지 못하다.
• 쿼리가 많아지면: 느려진다
• 쿼리가 복잡할수록: 느려진다
• 예: Media monitoring service
• “which” magazine 의 복잡한 쿼리 사례
옵티마이징을 해야한다
• The fastest query is a query that you never execute
• 절대 실행되지 않을 쿼리를 찾아낼 수 있다면 그 쿼리들을 건너뜀으로써 많은 시간을 아낄수있다
Luwak: A java library for stored queries
Luwak
• “A library that we (Flax) wrote in order to do efficient streaming search. Luwak is open source and builds upon Apache Lucene"
• 쿼리를 먼저 등록하고 새로운 문서들을 매칭한다
• 문서를 먼저 색인하는 것이 아니다
• 매칭해야하는 쿼리의 수를 줄이기 위해 몇 가지 옵티마이징을 한다
Index of Queries
• Conjunction 쿼리
• Q1: “WHEELS” NEAR “BUS”
• Q2: “WHEELS” NEAR “CAR”
• 모든 단어들이 문서에 등장해야한다
• Q1 쿼리와 매칭되는 문서는 “wheels” 와 “bus” 가 등장하는 문서
• 만일 문서에 “bus”/“wheels” 중 하나가 없다면 Q1하고 매칭이 안된다
• 쿼리에서 단어를 하나 골라서 어떤 문서와 전체 쿼리가 매칭되는지를 확인할 수 있다
• Disjunction 쿼리
• Q3: “WHEELS” OR “BUMPERS”
• 단어 중 하나만 문서에서 등장 해도 쿼리가 문서와 매치가 된다
• 반대로 어떤 쿼리가 문서와 매칭되지 않는지를 확인하려면 모든 단어를 문서와 매칭해봐야 한다
• Query 글에서 추출한 단어들을 가지고 색인을 만든다.
• Q1: “bus”
• Q2: “car”
• Q3: “bumpers” and “wheels”
• 이 색인은 term들을 실제의 query 와 매핑하는 역할을 한다.
Document as a Query
• 어떤 문서와 매칭되는 모든 쿼리들을 찾기위해 문서를 쿼리로 던져야 한다
• 문서의 모든 단어들로 disjunction(OR) query 를 만든다
• 문서의 단어 중에서 하나라도 나타나는 모든 쿼리를 찾는다
• 하나의 문서로부터 inverted index를 만들면 자동으로 이 term 들이 생성된다
문서와 매칭되는 쿼리들을 찾는 과정
1. 쿼리의 색인을 만든다
2. 문서의 disjunction query 를 퀴리의 색인에 검색해서 어떤 쿼리들이 매칭될 가능성이 있는지 찾는다
3. 이 쿼리들을 가지고 실제로 문서에 검색을 해서 매칭이 되는지 확인한다
• 문서: “The wheels on the bus go round and round”
• disjunction query:“and” OR “bus” OR “go” OR “on” OR “round” OR “the” OR “wheels”
• 쿼리 색인 term
• Q1: “bus”
• Q2: “car”
• Q3: “wheels”, “bumpbers”
• Q1와 Q3는 전체 쿼리를 검색을 해서 문서와 매칭되는지 확인한다
• Q2는 검색을 할 필요가 없으므로 건너뛴다
• 이 작업이 복잡해 보일수있지만 전체 99%의 쿼리들을 수행하지 않아도 되게 한다
• 가장 빠른 쿼리는 수행하지 않는 쿼리다
More Optimizations
Term Frequency Analysis
• Conjunction query 의 단어를 선택할때 기준을 term frequency 로 잡을 수 있다.
• “car” AND “bumpers”
• Query 색인과 문서를 매칭할때 한 단어라도 나타나지 않으면 그 문서와 매칭되지 않는 다는 것을 안다
• “bumpers” 라는 단어가 나타나는 빈도가 적으므로 선택한다
More Optimization
• 지금까지 세운 규칙
• Conjunction(AND)인 경우 그 중 하나의 단어만 추출
• Disjunction(OR) 인 경우 모든 단어를 추출
• 규칙에 의해 예제 트리에서 3가지의 다른 조합을 추출할 수 있다
• 조합에 따라서 매치가 될수도 있고 안될수도 있다
• 문서의 내용이 “term1 term2 term3” 라면 세번째 경우에 매치가 안된다.
• 세번째: term4 term5
• 조금 더 정확하게 query pre-selection을 만들 수 없을까?
• 위 조합을 다시 조합하면 된다. 각각의 경우의 수를 다른 필드에 색인하고, 문서를 각 필드에 검색한 결과를 AND 한다.
• _a:(term1 OR term2 OR term3) AND
• _b:(term1 OR term2 OR term3) AND
• _c:(term1 OR term2 OR term3)
• 여전히 실제로 문서가 매칭되는지는 검색을 통해야 알 수 있지만, 많이 줄일 수 있다.
Luwak stream search 정리
• Luwak은 위 optimizations들을 다 구현했다
• Luwak은 library 이다
• Single machine 에서 돌리는 건 한계가 있다.
• 어떤 시점 부터는 쿼리양이 늘어나서 위에서 설명한 optimization들로도 감당이 되지 않는다.
• 그렇다면 어떻게 확장할 것인가?
Scaling Stream Searching
어떻게 확장 할 것인가?
• Scaling search across a cluster of machines
• 분산프레임워크를 새로 구축하는 것은 어렵다
• Apache Kafka 와 Apache Samza를 사용하기로 했다
Kafka
• “Kafka is a kind of message broker or message queue”
• 하나의 프로세스(producer)에서 생성한 메세지를 다른 프로세스(consumer)로 전달한다
• Scalable
• Fault-tolerant
• 매우 큰 append-only file이라고 생각할 수 있다.
• Producer는 이 파일 맨 마지막에 메세지를 쓸 수 있다
• Consumer는 tail -f 와 같다
• 각 consumer는 순차적으로 메세지를 읽는다
• 각 consumer 별로 파일의 position을 가지고 있다
• Kafka 는 누가 어디까지 읽었는지 추적하지 않아도 된다.
• Consumer는 자기 위치만 기록해두면 된다.
Kafka Stream
Kafka: for scaling
• Kafka의 stream은 partition 되어있다
• hash 방식의 partitioning 이다
• Kafka는 replication을 지원한다
• Leader/follower 모델을 사용한다. Leader가 broker 역할
• 새로운 메세지는 모두 leader에게 가고 follower들에게 복제된다
• Leader였던 노드가 죽으면 follower 중 하나가 leader가 된다
Kafka: Messages
• Kafka의 모든 메세지는 key, value 형태로 되어있다.
• Key는 메세지를 구분짓는 값이다
• Partition할때 사용한다
• Compaction을 할때 사용한다 (다음장에)
• Value는 임의의 길이의 문자열
Kafka: Compaction
• Compaction 은 append-only 정책의 예외
• 스트림에 동일한 key를 가진 스트림이 여럿 있다면 가장 최신의 메세지만 남기고 나머지를 삭제한다
• 즉, 나중에 들어온 메세지들이 그 전 메세지들을 overwrite 한다
• 이것은 바로 일어나지 않고 특정 시간에 이루어진다. GC처럼.
• Compaction을 사용하지 않으면 메세지 개수가 늘면서 stream크기가 증가
• Compaction을 사용하면 유일한 key 개수에 비례해서 stream이 커진다. 즉, DB와 비슷하다.
• DB에 모든 key value 를 저장할 수 잇다면 Kafka에도 그렇게 할 수 있다
Kafka 와 Luwak의 관계는?
• Luwak은 메모리에 모든 쿼리를 로딩한다
• Luwak은 누군가 query를 새로 등록하거나, 수정하거나, 삭제했을 때 알림을 받을 수 있어야 한다
• Query ID을 key 로 사용하고 query string을 value 로 사용한다.
• Stream compaction 으로 stream이 너무 커지는 것을 방지
• Luwak을 처음 실행할때 stream을 처음부터 끝까지 읽는다
• bootsrap stream이라고 부른다.
Samza
Samza
• “A framework for writing stream processing jobs on top of Kafka”
Samza: Jobs
• 특정 stream을 consume 하도록 지정
• StreamTask Interface를 상속해서 구현
• process() 함수에서 stream message를 처리한다
• Output stream에 메세지를 출력하도록 할 수도 있다
Samza: Scaling
• Samza의 StreamTask를 Kafka의 partition 별로 생성
• 각 stream의 partition들의 message들을 순차적으로 처리한다
• Output은 자신의 stream 중 어떠한 partition으로도 보낼 수 있다
• Partition별로 작업을 처리하는 특성을 이용해서 두 개 이상의 stream 작업을 join 할 수 있다
• 두 개의 stream
• 각 stream의 partition1 들을 join 처리하는 StreamTask
• 각 stream의 partition2 들을 처리하는 StreamTask
• 단, input stream 들이 같은 수의 partition을 가지고 있어야 한다.
• 이러한 특성때문에 stream join을 scale 할 수 있다
• 각 stream이 user ID로 partition
• 각 stream 에서 user ID가 동일한 message들을 하나의StreamTask에서 처리한다
이 둘을 이용해서 어떻게 full-text search on stream을 할 수 있는 것일까?
Luwak & Samza
• Query Stream
• Bootstrap stream with compaction
• 사용자 쿼리를 추가/수정/삭제 할 수 있다
• 쿼리를 Luwak의 in-memory 에 반영한다
• Document Stream
• 쿼리와 매칭될 문서들
• Samza job이 문서를 읽어서 query색인에 매칭한다
• 결과를 output stream에 쓴다
• Does it scale?
• Samza 의 partition 모델은 다음과 같다.
• Stream A는 query stream
• Stream B는 document stream
• 각자 자신과 관련된 query-document 끼리 partition을 구성할 수 있으면 예제와 같은 모델을 사용할 수 있다.
• 하지만, 실제로는 다음과 같은 모델이 필요하다
• 모든 query 들과 모든 document들을 매칭할 방법이 필요하다
• SimpleTask8는 쿼리 파티션 4와 문서 파티션 2를 처리
• 쿼리와 문서 모두 여러개의 task에서 처리되는 것이다
• 그러면 마지막에 모든 matches를 합치면 된다.
• 안타깝게도 지금 Samza는 이러한 기능을 지원하지 않는다
• SAMZA-353 이슈에서 다뤄지는 중
• Samza와 Luwa 연동의 POC (Proof of Concept)를 Github에서 찾을 수 있다.
마무리 Luwak + Kafka + Samza
Luwak & Samza를 이용한 stream 검색의 시사점
• Luwak
• 쿼리를 색인하고 문서와 매칭하는 과정의 옵티마이징에서 배울 점이 있다
• Kafka
• Streaming framework 에 대한 이해
• Samza
• Streaming framework 을 어떻게 처리해야할지에 대해 시사
출처
• Blog post: Real-time full-text search with Luwak and Samza
• http://www.confluent.io/blog/real-time-full-text-search-with-luwak-and-samza/
• Samza-Luwak Proof of Concept
• https://github.com/romseygeek/samza-luwak#high-level-architecture
• Luwak GitHub
• https://github.com/flaxsearch/luwak
• Apache Kafka
• http://kafka.apache.org
• Apache Samza
• http://samza.apache.org
• Blog post: Elasticsearch Percolator & Luwak: a performance comparison of streamed search implementations
• http://www.flax.co.uk/blog/2015/07/27/a-performance-comparison-of-streamed-search-implementations/
Recommended