Share
Embed
Mercari Item Search: Behind The Scenes (20min)
Mercari Item Search:
Behind The Scenes (20min)
第22回 Lucene/Solr勉強会 2019.10.28
kazeburo
October 28, 2019
Transcript
39 slides
-
Mercari Item Search: Behind The Scenes (20min) Masahiro Nagano
(kazeburo) ୈ22ճ Lucene/Solrษڧձ 2019.10.28 -
Me • Masahiro Nagano • @kazeburo • ISUCON9 ग़ •
Mercari, Inc. ӡ༻ܥখݼ -
Softwares for Search • 2013.7 (?) ~ • Solr on
BareMetal Servers • Nginx as LB • 2019.7 ~ New Architecture • Elasticsearch on GKE -
Cretaceous period PHP Master update select Slave Slave Slave Nginx
Replication pollInterval 30s -
Cretaceous period PHP Master update select Slave Slave Slave Nginx
Replication pollInterval 30s -
K-Pgڥք • ͬͱ૿͑Δɺͬͱ৳ͼΔDAU • Tuning JVM/GC • Tried CMS ,
Parallel GC and G1GC. Parallel GC was better for this Era • Tuning Query • Use filter query correctly • Split Index and Fallback in Nginx -
Paleogene period PHP Recent Master update select Recent Slave Recent
Slave Recent Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min -
• ݕࡧIndexͷׂ • Mercari ͷݕࡧͷσϑΥϧτͷฒͼॱʮ৽ணʯ • ৽ண͕ೖΔRecent Indexͱશͯͷ͕ೖΔAll Indexʹׂ •
Recent IndexυΩϡϝϯτ͕ݮΔ͜ͱͰෛՙݮ • All Indexࢀর͕ݮΓɺෛՙ͕খ͘͞ -
• IndexͷׂOpenResty ʹΑΔ Recent͔ΒAllͷࣗಈFall back • OpenResty • Nginx͓Αͼɺngx_luaΛ͡Ίͱ͢ΔCͰॻ͔Ε֤ͨछαʔυύʔςΟϞδϡʔϧͳ ͲͰιϑτΣΞɾσΟετϦϏϡʔγϣϯ
• ݕࡧrequestΛड͚ͨࡍʹɺ·ͣRecent Indexʹରͯ͠ݕࡧΛ࣮ߦ͠ɺಘΒΕͨJSONΛ NginxͷLuaͰॲཧɺऔಘݸ(rows)ʹରͯ݁͠Ռ͕ෆ͍ͯ͠ΕɺAll Indexʹର͠ ͯΫΤϦΛ͠ͳ͓͢ -
Paleogene period PHP Recent Master update select Recent Slave Recent
Slave Recent Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min -
Paleogene period PHP Recent Master update select Recent Slave Recent
Slave Recent Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min -
• ઐ༻ Slave ͷ࡞ • Bot, ScaperͷΞΫηεىҼͷݕࡧϦΫΤετͷఆ • ৽ண͓Βͤϝʔϧͷݕࡧॲཧͷ •
ʮDescription͕ΩʔϫʔυʯͷՁ֨ɾΧςΰϦαδΣετͷॏ͍ΫΤϦͷ • Query Rewriting by Lua -
Neogene period Recent Master update select Recent Slave Recent Slave
Condition Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min Condition Slave Suggest Slave Suggest Slave Replication pollInterval bit long PHP General Specific purpose -
local create_t = string.match(token, "^fq=created_time_t%%3A%%5B(%d%d%d%d%-%d%d%-%d%dT%d%d%%3A%d%d%%3A%d) %dZ%+TO%+%%2A%%5D$") if create_t then --
conditionsͰfilter queryͷhitΛ͋͛ΔͨΊɺcreated_time_tͷ࠷ޙΛ9ඵʹͯ͠͠·͏ create_t_filter = "created_time_t%3A%5B" .. create_t .. "9Z+TO+%2A%5D" -- ͷঢ়ଶ: શ෦ࢦఆ͞ΕͯΔͷͰফ͢ args = string.gsub(ngx.var.args,"&fq=item_condition_id%%3A%%281%+OR%+2%+OR%+3%+OR%+4%+OR%+5%+OR%+6%%29","") -- ࠷Ձ͕֨300ԁͳͷͰফͤΔ args = string.gsub(args,"&fq=price_t%%3A%%5B300%%2BTO%%2B*%%5D", "") -- ͷՁ֨: frangeʹॻ͖͑ɹ args = string.gsub(args,"&fq=price_t%%3A%%5B%%2A%+TO%+(%d+)%%5D","&fq=%%7B%%21frange%+cache%%3Dfalse%+cost% %3D150%+u%%3D%1%%7Dprice_t") -- "͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑͑" ରࡦɻ10ճҎ্࿈ଓͰ10จࣈ·ͰΓ٧Ί args, _, _ = ngx.re.gsub(args, "(%[0-9a-f][0-9a-f]%[0-9a-f][0-9a-f]%[0-9a-f][0-9a-f])\\1{9,}", "$1$1$1$1$1$1$1$1$1$1", "i") -
Neogene period Recent Master update select Recent Slave Recent Slave
Condition Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min Condition Slave Suggest Slave Suggest Slave Replication pollInterval bit long PHP General Specific purpose -
Neogene period Recent Master update select Recent Slave Recent Slave
Condition Slave OpenResty Replication pollInterval 30s All Master All Slave All Slave update Replication pollInterval 1min Condition Slave Suggest Slave Suggest Slave Replication pollInterval bit long PHP General Specific purpose -
• εϜʔζͳSolr ͷόʔδϣϯΞοϓͷ࣮ݱ (4 → 6 → 8) • ΠϯσοΫεΛมߋ͍ͨ͠
(BigramԽ) • BigramͰͷύϑΥʔϚϯεҡ࣋ͷͨΊBareMetal αʔόͷεέʔϧΞοϓඞཁ • Microservices Խ/ϦΞʔΩςΫνϟ͍ͨ͠ • Master ͷোͷඋ͑ -
• தؒ queue αʔϏε (solr-queue-app) • Solrͷߋ৽ϦΫΤετͷJSONΛҰΩϡʔʹ֨ೲ͔ͯ͠Βɺࢦఆ͞ΕͨαʔόʹPOST͢͠ • PHPͷίʔυΛมߋͤͣʹ Master
ՃɾมߋͰ͖ΔΑ͏ʹ • Solr-DB (MySQL) • ߋ৽σʔλΛID͝ͱʹׂ͠ɺMySQLʹ֨ೲ • MySQLͷσʔλ͔ΒશΠϯσοΫεͷ࡞͕࣌ؒͰߦ͑Δ • ͜Ε·Ͱ͔Βिؒ • Cloud PubSub ͷૹ৴ -
Quaternary period PHP Solr6 Master Solr8 Master Solr6’ Master MySQL
Q4M API Worker Q4M API Worker API solr-queue-app API -
• ௨ৗͷ৽ணɾΧςΰϦλΠϜϥΠϯ • MySQL ͔Β৽ணΛऔಘ • ߋ৽΄΅ϦΞϧλΠϜ • ͓͢͢ΊλΠϜϥΠϯ •
ӾཡཤྺͳͲ͔ΒSolrΫΤϦΛ࡞ɺSolr͔ΒϢʔβ͝ͱʹҟͳΔΛ৽ண ॱʹදࣔ • ߋ৽΄΅ϦΞϧλΠϜ -
• ϦΞϧλΠϜͳΠϯσοΫεө • ϨϓϦέʔγϣϯͤͣɺશ෦Master • soft commitΛ1ඵҎԼʹઃఆ • ߴͳϨεϙϯεͷ࣮ݱ •
ࢄΠϯσοΫεʹΑΓαʔό͋ͨΓͷυΩϡϝϯτΛݮΒ͢ • ৽ணʹेͳυΩϡϝϯτͷΈอ࣋ / εΩʔϚγϯϓϧʹ -
PHP PHP API MySQL blackhole black hole Q4M Solr (master)
worker trigger dequeue black hole Q4M Solr (master) worker trigger dequeue black hole Q4M Solr (master) worker trigger dequeue black hole Q4M Solr (master) worker trigger dequeue soft commit several times per second Update Update item selected by consistent hashing Use MySQL replication as PubSub -
black hole Q4M Solr (master) worker trigger dequeue consul my
$res = $ua->get(‘http://localhost/v1/health/service/".$SRV.'?passing'); my $ref = JSON::XS::decode_json($res->content); my @list = sort { $a cmp $b } map { $_->{Node}{Address} } @$ref; my $ketama = Algorithm::ConsistentHash::Ketama->new(); $ketama->add_bucket($_ . '_' . $timestamp, 1) for @list; my $s1 = $ketama->hash($item_id); return $s1 eq $my_ip; Get server list from Consul Make Consistent Hash Drawing by consistent-hashing Update Solr consistent-hashingͷ݁Ռ͕trueͳΒɺupdate consistent-hashingͷ݁Ռ͕falseͳΒɺdelete -
black hole Q4M Solr (master) worker trigger dequeue consul black
hole Q4M Solr (master) worker trigger dequeue consul black hole Q4M Solr (master) worker trigger dequeue consul black hole Q4M Solr (master) worker trigger dequeue consul API/Go PHP PHP select distribute select request to all Solr servers and merge their resposne select select select select