Elastic Search Engine 을 Data Base 로활용 - 박영민
목차 1. 개요 2. RDB ERD구조를엘라스틱색인구조로변환 3. QUERY DSL -> SQL 쿼리에서바로사용 4. ElasticSearch CRUD 처리 5. 서비스아키텍쳐구성 6. 처리 Performance 비교 (MariaDB vs Elasticsearch) 7. 구성시고려사항 8. Q&A
1. 개요 - 검색엔진은뭔가요? 방대한분량으로흩어져있는자료를가운데원하는정보를쉽게찾을수있도록도와주는소프트웨어 l 단어별검색엔진 (word-oriented searching): 검색하고자하는내용을입력하면, 검색사이트에있는데이터베이스를찾아웹페이지로보여주는검색엔진이다. 2 주제별검색엔진 (sbject-oriented searching): 인터넷상에있는정보를큰범위에서좁은범위로좁혀가며찾는방식의검색엔진이다. 3 메타검색엔진 (Meta-searchengine): 인터넷에서규모가큰검색엔진들에사용자가입력한검색키워드에대하여의뢰한뒤결과를가져오는검색엔진이다
1. 개요 왜검색엔진을 Database 용도로쓸려고했는가? 평균사용자가일 1억대이상이며, 동시요청 REQUEST 가평균 2만대의시스템은운영하는데, 사람이퇴근하고디바이스를동시에켜는시간저녁 6-7시만되면, 긴장을해야합니다. 왜냐하면그시간에트래픽이항상몰려, 서버가중단되는사태가발생하였기때문입니다. 중간에캐쉬서비스도올려사용하였지만, 너무많은트래픽에캐쉬서비스도감당을못하는경우가있었음 => 서비스장애덤프를확인하여보니서비스 Hang의원인이특정 DB 테이블몰려있으며, 일정임계치가넘어가면서느려지는현상이발생 1. 일시적동시접속자사용자때문에, DB 에부하가걸려서서버가뻗는경우가발생하였다 2. 아무리디비를튜닝해도, 좀처럼속도개선의해결의기미가보이지않는다 3. 갱신보다기하급수적으로조회가많은경우라면엘라스틱을이용해처리가가능하였다.
1. 개요 - 엘라스틱서치를 DB 로활용하기위한조건 1. 표준 ANSI SQL문으로제어가가능해야한다. 2. SQL로 CRUD 처리를할수있어야한다. 3. DB에 ENTITY RELATION 구조를엘라스틱인덱스로유사하게컨트롤해야한다. 4. 원본 DB의제어와 ELASTIC의제어가동일아키텍쳐형태로구성되어야한다.
2. ELASTIC ERD 구성 1. RDB 에서는 ENTITY 간에연결을 PK, FK 로구성하여연결하여가능하지만, 엘라스틱인덱스에서는그런게없다, 그러나 PARENT CHILD / CHILD PARENT 방식이용해서을각색인간의비슷하게 Relation 만들수있다. 물론 100% 동일하게는불가능하므로, ERD 에따라중간색인테이블을만들어 하는경우도있음
ERD 예제
INDEX 예제 "mappings": { "main_recipes": { "properties": { "recipes_key": { "type": "string" }, "recipes_title": { "type": "string", "index": "analyzed", "analyzer": "korean_analyzer" }, recipes_rl": { "type": "string", "index": "analyzed", "analyzer": "english" } } }, "food_material": { "_parent": { "type": "main_recipes" }, "properties": { "recipes_key": { "type": "string" }, "recipes_seq": { "type": "integer" }, "material_cd": { "type": "string", "index": "analyzed", "analyzer": "english" }, "material_nm": { "type": "string", "index": "analyzed", "analyzer": "korean_analyzer" }, "material_ratio": { "type": "integer" }
QUERY DSL -> SQL 쿼리로 의외로 Elastic Qert DSL 를이용하여검색문을작성하는것쉽지는않다고, 검색엔진을 DB 로활용하려할때, 이부분이걸림돌이될수있다. 이부분을해결하기위해 NLPCN 자연언어처리단체에서제공하는 elasticsearch-sql 플러그인을이용하여 sql 문을그대로엘라스틱에서사용하도록처리함 https://githb.com/nlpchina/elasticsearch-sql 현재제공버전은 : Elasticsearch 5.4.1 까지제공
Sql 조회화면 위의플러그인을설치하면다음과같은 UI 를통해서엘라스틱의인덱스를 sql 로제어가가능함 Explain 을이용하면 QeryDSL 문장으로도변환처리해줌
SQL 주요명령어 ( 데이터조회 ) Qery SELECT * FROM bank WHERE age >30 AND gender = 'm' Aggregation select COUNT(*),SUM(age),MIN(age) as m, MAX(age),AVG(age) FROM bank GROUP BY gender ORDER BY SUM(age), m DESC Delete DELETE FROM bank WHERE age >30 AND gender = 'm'
SQL 주요명령어 ( 테이블간조인 ) 서로다른인덱스간의조인쿼리 select name from material_code/parent_material a JOIN recipes/food_material b on b.name = a.material_nm 부모자식간의조회쿼리 SELECT recipes_key,recipes_title,material_nm FROM recipes/main_recipes where children(food_material,material_nm)=' 고추장 ' and recipes_title=' 해물탕 ' - 위와같이하면자식인덱스에있는범위를포함하는부모인덱스값만노출
검색엔진조회확인 http://180.70.211.156:29200/_sql?sql-select name from material_code/parent_material limit 0,10 위와같이브라우징을통해서쿼리로동일하게접근이가능하
4. ElasticSearch CRUD 처리 elasticsearch-sql 플러그인은 Read 에대해서만제공한다. 서비스상에서 CUD를하기위해서, 고민을하다가다음과같은방식으로구현처리를해보았다. 편법이긴하지만많은리퀘스트에도문제없이동작이됨 UPDate라는개념이기본적명령어로없으므로, 삭제후신규등록해야함 Parent Child 구조에서 Parent 삭제하면하위노드데이터는재색인등록해야하는경우가생김 elasticsearch-sql 에서 2.4 버전이후에 DeleteQery가엘라스틱라이브러리와 org/elasticsearch/index/reindex/deletebyqeryaction 를호출하고있어서에러가발생하므로 reindex-client.xx.xx.jar 를 %Elasitc_Install%/lib에넣어주어야함 실시간동기화가필요한테이블에대해서는 Spring Data Elasticsearch 와 DridDataSorce 를하여처리함
JDBC 를통한제어 pblic void elasticjdbc() throws Exception { Properties properties = new Properties(); properties.pt( rl, jdbc:elasticsearch://180.70.211.156:9300/ + TestsConstants.TEST_INDEX); DridDataSorce dds = (DridDataSorce) ElasticSearchDridDataSorceFactory.createDataSorce(properties); Connection connection = dds.getconnection(); PreparedStatement ps = connection.preparestatement("select recipes_key,recipes_title,material_nm from " + TestsConstants.TEST_INDEX + " where children(food_material,material_nm)=' 고추장 ' and recipes_title=' 해물탕 '"); ResltSet resltset = ps.execteqery(); List<String> reslt = new ArrayList<String>(); while (resltset.next()) { System.ot.println(resltSet.getString("recipes_key") + "," + resltset.getstring("recipes_title") + "," + resltset.getstring("material_nm")) } ElasticSearch 를 JDBC 로컨트롤할수있는 DridDataSorce 를이용하면나머지 SQL 문장의변경처리없이바로 JDBC 를통해조회처리가가능
5. 서비스아키텍쳐구성 이상적인서비스아키텍쳐의구성을고민 왜? 아무래도검색엔진이다보니 100% DB 를대처하긴힘듬, 현재까진보조하는 수단으로구성함 response response App Svc reqest Serving Search Serer App Svc reqest Serving Search Serer Realtime Indexing DB Server batch indexing Index Server Index Server DB Server 검색서비스장애시에는자동으로 DB로접속해서처리되도록장애대응처리함
6. 처리 Performance 비교 데이터조회건수 : 100 만건 Testing Tool : Jmeter 동접유저 : 1000 명 / 1,000 Reqest * 죄송합니다. 비교장표를못만들었어요
구성시고려사항 DB 보다아무래도엘라스틱이분산노드로구성하다보니, 더많은저장공간을 사용한다. 기본적은엘라스틱은 Schema-Free 하므로성격에맞는, 데이터를전환하였을때동일환경에서 Response 가최대 10배이상향상되는것을보고, 중간데이터조회시늦어지는것을 100% 로방지할수있었음, DB는백업정도의역할로사용하고, 모든데이터를엘라스틱 SEARCH 에서사용함
8. Test Demo 구성설명 Githb : https://githb.com/parkymin/elasticsearch-sql < 추후업로드 > Elastic SQL : http://180.70.211.156:9999/