PHP Experience 2016 - [Workshop] Elastic Search: Turbinando sua aplicação PHP

82
Breno Oliveira @brenoholiveira [email protected] BRENO OLIVEIRA Tech Leader at Moip ElasticSearch Turbinando sua aplicação PHP

Transcript of PHP Experience 2016 - [Workshop] Elastic Search: Turbinando sua aplicação PHP

Breno Oliveira @brenoholiveira

[email protected] R E N O O L I V E I R ATech Leader at Moip

ElasticSearchTurbinando sua apl icação PHP

+ 86k de contas vendendo

+ 100K de pedidos por dia

VENDAS AUMENTAM

VENDEDOR QUER SABER

Ordenação

Ful lText Search

PaginaçãoAgregação

Fi l tros

REALTIME

E O SEU SERVER DEPOIS DE VÁRIOS F5 …

NOSSA VONTADE É DE …

SEU CLIENTA VAI…

PHP + MySQL

PHP + postgresql

PHP + nosql

PHP + ????

CASO DE USO

+

502 200 304

+

Aplicação MOIP

Base de Dados Master

Single Term

SELECT * FROM pedidos p INNER JOIN cliente ON p.cliente_id = c.id WHERE p.descricao LIKE "%superman%"

multi Term

SELECT * FROM pedidos p INNER JOIN cliente ON p.cliente_id = c.id WHERE p.descricao LIKE "%superman%" OR p.descricao LIKE "%batman%"

ORDER

ARRGH ! ! ! !

SELECT * FROM pedidos p INNER JOIN cliente ON p.cliente_id = c.id WHERE p.descricao LIKE "%superman%" OR p.descricao LIKE "%batman%" ORDER BY ??

PROBLEMAS• Dif íci l manter • Muitos JOINS • Lento

.Primeiro REFACTOR

MICRO SERVIÇO + BANCO denormalizado

APLICAÇÃO MOIP

Base de Dados Master

REPORTS API

Base de Dados denormalizada

MELHORIAS• Micro serviço • Concorrência no banco de dados • No more JOINS • Ful l-Text Search • Melhorias de desempenho

PROBLEMAS•Periodos longos •Fi l tros •Lentidão

.SEgundo REFACTOR

MICRO SERVIÇO + Banco colunar

APLICAÇÃO MOIP

Base de Dados Master

REPORTS API

MELHORIAS

• Consultas signif icantemente mais rápidas

PROBLEMAS

•BULK INSERTs

Too Slow

.terceiro REFACTOR

MICRO SERVIÇO + Elasticseach

APLICAÇÃO MOIP

Base de Dados Master

REPORTS API

Elasticsearch

MELHORIAS• Bulk INSERT • Desempenho • Aggregations • Scalable • Redundancy

.Atualmente

Last Black Friday

.não é banco da dados

.nem nosql

I T ' ’ N O T K E Y- V A L U E S T O R A G E

.Escalável

.Alta resiliencia

.restful api

.orientado a documentos

.full-text search

.free schema

.Eventualmente consistente

.apache lucene

.Conceitos básicosElasticsearch

MySQL Elasticsearch

Database Index

Table Type

Column Field

Schema Mapping

Partition Shard

curl -XPUT http://localhost:9200/tips/tip/1 -d '{"tip": "Using Elasticsearch in Production", "tags":["protip","success"]} '

Endpoint

Index

Type

Document ID

Document

{ "_index": "tips", "_type": "tip", "_id": "1", "_version": 1, "created": true}

Response

$ curl http://localhost:9200/tips/tip/1?pretty

{ "_index": "tips", "_type": "tip", "_id": "1", "_version": 1, "found": true, "_source": { "tip": "Using Elasticsearch in Production", "tags": [ "protip", "success" ] }}

VAGRANT

$ git clone [email protected]:brenooliveira/elastic-php-demo.git$ cd elastic-php-demo$ vagrant up —provision$ vagrant sshvagrant@default:~/$

vagrant@default:$ curl http://localhost:9200{ "status" : 200, "name" : "Corruptor", "cluster_name" : "elasticsearch", "version" : { "number" : "1.5.2", "build_hash" : "62ff9868b4c8a0c45860bebb259e21980778ab1c", "build_timestamp" : "2015-04-27T09:21:06Z", "build_snapshot" : false, "lucene_version" : "4.10.4" }, "tagline" : "You Know, for Search"}

{ "require": { "elasticsearch/elasticsearch": "~2.0@beta" }}

composer.json

$ curl -s http://getcomposer.org/installer | php$ php composer.phar install --no-dev

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create() ->build();

$params = array(); $params['index'] = 'tips'; $params['type'] = 'tip'; $params['id'] = '1'; $result = $client->get($params)?><pre> <?= print_r($result); ?></pre>

exemplo1.php

Array( [_index] => tips [_type] => tip [_id] => 1 [_version] => 1 [found] => 1 [_source] => Array ( [tip] => Using Elasticsearch in Production [tags] => Array ( [0] => protip [1] => success )

)

)

exemplo2.php

<?php require 'vendor/autoload.php';

$client = Elasticsearch\ClientBuilder::create() ->build(); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '2', 'body' => [ 'tip' => 'Using Marvel to get metrics from Elasticsearch', 'tags' => ['protip', 'metrics'] ] ];

// Documento indexado em tips/tip/2 $response = $client->index($params);?><pre> <?= print_r($response) ?></pre>

exemplo3.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create() ->build(); for($i = 0; $i < 100; $i++) { $params['body'][] = [ 'index' => [ '_index' => 'jobs', '_type' => 'job', ] ];

$params['body'][] = [ 'title' => 'Job position '. $i, 'email' => 'email-'. $i . '@gmail.com' ]; }

$responses = $client->bulk($params);?>

exemplo4.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create()->build(); $json = '{ "query" : { "match" : { "tags" : "protip" } } }'; $params = [ 'index'=> 'tips', 'type' => 'tip', 'body' => $json ]; $responses = $client->search($params);?><pre> <?= print_r($responses) ?></pre>

exemplo5.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create()->build(); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '3', 'body' => [ 'tip' => 'Wrong insert', 'tags' => ['missing', 'error', 'no_logs'] ] ]; $response_insert = $client->index($params); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '3' ]; $responde_delete = $client->delete($params);?>

exemplo6.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create()->build(); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '4', 'body' => [ 'tip' => 'Loren Ipsum', 'tags' => ['lorem'] ] ];

$response_insert = $client->index($params); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '4', 'body' => [ 'doc' => [ 'text' => 'lipsum generator' ] ] ]; $response_update = $client->update($params); $params = [ 'index' => 'tips', 'type' => 'tip', 'id' => '4' ]; $response_search = $client->get($params);?>

exemplo7.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create()->build(); $json = '{ "my-suggestion" : { "text" : "Elastiscearch", "term" : { "field" : "tip" } } }'; $params = [ 'index' => 'tips', 'body' => $json ]; $response = $client->suggest($params);?>

exemplo8.php

<?php require 'vendor/autoload.php'; $client = Elasticsearch\ClientBuilder::create()->build(); $json = '{ "query" : { "more_like_this" : { "like_text" : "In production", "min_term_freq" : 1, "min_doc_freq" : 1 } } }'; $params = [ 'index' => 'tips', 'type' => 'tip', 'body' => $json ]; $response = $client->search($params);?>

.Vamos falar de arquitetura

.Como devo sincronizar mysql & Elasticsearch

E-commerce app

Base de Dados Elasticsearch

Cadastrar novo produto

E-commerce app

Base de Dados

Elasticsearch

rabbitmqPublish Message

php workerConsume Message & Sync

Cadastrar novo produto

.Lessons learned

Utilize mais mappings

Em produção use alias