Category Archives: Tecnologia

Image API

Este post demonstra o conceito da API de tratamento de imagem, publicada no Github.

Introdução

Este projeto foi desenvolvido utilizando Spring Boot, Swagger e REST.

Spring Boot

Spring Boot é um projeto da Spring que veio para facilitar o processo de configuração e publicação de nossas aplicações. Você escolhe os módulos que deseja através dos starters que inclui no pom.xml do seu projeto. Eles, basicamente, são dependências que agrupam outras dependências.

Swagger

O Swagger é um dos frameworks mais usados para se documentar API’s REST. Ele facilita para que os clientes que consomem nossas API’s saibam quais os parâmetros nossas operações recebem, qual o retorno, o modelo, o media type retornado JSON, XML, CSV, binário etc. Sendo assim os clientes não precisam necessariamente discutir com a equipe de desenvolvimento da APIsobre como usá-la.

REST

REST é acrônimo de Representational State Transfer, e tem como objetivo primário a definição de características fundamentais para a construção de aplicações Web seguindo boas práticas.

Veja o post sobre boas práticas REST (http://whs.com.br/dicas/rest-boas-praticas)

Github

https://github.com/lfchaim/image-api

Swagger UI

Para visualizar o Swagger da aplicação, devemos iniciar através da classe ImageApiApplication.

Depois de iniciar, pode-se acessar através do endereço:

http://localhost:8080/swagger-ui.html

Postman

O Postman é uma ferramenta que tem como objetivo testar serviços RESTful (Web APIs) por meio do envio de requisições HTTP e da análise do seu retorno. Com ele é possível consumir facilmente serviços locais e na internet, enviando dados e efetuando testes sobre as respostas das requisições.

Instale o Postman e importe o Collection para efetuar os testes. O download pode ser feito aqui.

https://github.com/lfchaim/image-api/blob/master/postman/ImageAPI.postman_collection.json

 

REST – Boas Práticas

Este post visa apresentar as boas práticas na implementação de serviços REST.

REST – Conceito

REST (Representational State Transfer) é um modelo arquitetural que foi apresentado em uma tese de doutorado de Roy Fielding, co-autor do protocolo HTTP.

RESTful, existe uma confusão entre os dois termos REST e RESTful, resumidamente REST é o modelo arquitetural e RESTful é um sistema que é capaz de aplicar integralmente os princípios de REST. Mais adiante, veremos exemplos de RESTful.

Nomenclatura de URIs

Para facilitar o uso de sua aplicação REST, é bom utilizar versionamento na URI (também conhecido como endpoint).

Exemplo:

  • http://[DOMINIO]/api/v1 (URI sem contexto e subdomínio)
  • http://[SUBDOMINIO].[DOMINIO]/api/v1 (URI sem contexto e com subdomínio)
  • http://[DOMINIO]/[CONTEXTO/api/v1 (URI com contexto e sem subdominio)
  • http://[SUBDOMINIO].[DOMINIO]/[CONTEXTO]/api/v1 (URI com contexto e com subdomínio)

Recursos da URI

Após a definição de Subdomínio, Contexto e Versão, definimos os recursos de nossa API, geralmente, utilizando identificadores no plural.

Exemplo:

  • /customers
  • /products
  • /invoices

Métodos HTTP

É boa prática utilizar métodos HTTP para identificar as operações permitidas.

Exemplo:

  • GET solicita dados do recurso. Requisições utilizando o Método GET devem retornar apenas dados e não devem produzir nenhuma alteração na base.
  • POST solicita que o servidor crie um recurso no banco de dados.
  • PUT solicita que o servidor atualize o recurso.
  • DELETE solicita que os recursos, ou sua instância, sejam removidos do banco de dados.
  • PATCH solicita que o servidor realize modificações parciais em um recurso.

Cadastrar um documento

[POST] /documents

Buscar todos os documentos

[GET] /documents

Buscar o documento de id 1

[GET] /documents/1

Alterar o documento de id 1

[PATCH] /documents/1

Excluir o documento de id 1

[DELETE] /documents/1

Resposta HTTP

Ao invocar um método, o cliente precisa receber uma resposta sobre a execução do método, se ocorreu tudo bem ou se apresentou erro. Para ajudar a identificar o erro, a API deve utilizar o código HTTP da maneira mais usual de mercado.

Categorias:
2xx (Categoria de sucesso)
Esses códigos de status representam que a ação solicitada foi recebida e processada com sucesso pelo servidor.

200 OK
Código de resposta padrão representando sucesso para o GET, PUT ou POST.

201 Created
Deve ser retornado sempre que uma nova instância for criada.

204 No Content
O servidor processa corretamente a requisição, mas não precisa retornar nenhum conteúdo.

4xx (Categoria de erros causados pelo cliente)
Esses códigos de status representam que solicitação realizada pelo cliente está incorreta.

400 Bad Request
Indica que a solicitação realizada pelo cliente não foi processada, pois o servidor não conseguiu entender o que o ele está solicitando.

401 Unauthorized
Indica que o cliente não tem permissão para acessar recursos e deve solicitar novamente com as credenciais necessárias.

403 Forbidden
Indica que a solicitação é válida e o cliente está autenticado, mas o cliente não tem permissão para acessar a página ou recurso por qualquer motivo. Por exemplo, às vezes, o cliente autorizado não tem permissão para acessar o recurso específico.

404 Not Found
Indica que o servidor não encontrou nada que corresponda à URI solicitada.

5xx (categoria de erro do servidor)
Categoria de erros gerados pelo servidor ao processar a solicitação.

500 Internal Server Error
Indica que a solicitação é válida, mas o servidor encontrou uma condição inesperada que impediu o cumprimento da solicitação.

503 Service Unavailable
Indica que o servidor está inoperante ou indisponível para receber e processar a solicitação. Principalmente se o servidor está em manutenção.

A lista completa de Código HTTP pode ser consultada em https://httpstatuses.com

Filtragem(Filtering)

Para filtrar o conjunto de dados, podemos passar várias opções por meio de parâmetros de consulta.
Por exemplo, GET /pessoas?tipo=pf&localizacao=SC filtraria os dados da lista de pessoas físicas de Santa Catarina.

Pesquisa(Searching)

Ao pesquisar o nome da pessoa na lista de pessoas, o endpoint a ser exporto deve ser do tipo GET = /pessoas?Search=fernando

Paginação(Pagination)

Quando o conjunto de dados é muito grande, dividimos o conjunto de dados em partes menores, o que ajuda a melhorar o desempenho e é mais fácil de lidar com a resposta(controlar itens por página e quantas páginas podem ser mostradas).
Por exemplo: GET /pessoas?Page=23 significa obter a lista de pessoas da 23ª página.
Se adicionar muitos parâmetros de consulta em métodos GET tornar o URI muito longo, o servidor poderá responder com 414 URI Status HTTP muito longo. Nesses casos, params também podem ser passados no corpo da solicitação do método POST.

RESTful

Uma API RESTful significa que ela possui a capacidade de evoluir e ajudar a identificação de métodos relacionados. Por exemplo, no método de consulta de um pedido, podemos incluir no retorno, a URI para consultar os dados do Cliente, facilitando a codificação das aplicação que usam a API.

Exemplo (veja o atributo permalink):

{
   "invoiceNumber": 21564879821,
   "invoiceDate": "2012-10-09 12:00:00 +05:30",
   "customer": {
      "document": "01698798166215",
      "name": "John Baker",
      "permalink": "/v2/customers/3a22b041-8d45-496a-946d-bd2252a0d28c"
   }
}

 

Instalando MySQL 8 no Windows

Este post demonstra a instalação e configuração do MySQL 8 (versão 8.0.16) no Windows, via arquivo zip.

Baixando o MySQL

Acesse o site https://dev.mysql.com/downloads/ e baixe o MySQL Community Server 8.0.16 (Zip Archive).

Descompactando o MySQL

Após baixar o arquivo mysql-8.0.16-winx64.zip, descompacte-o no diretório destino. Para este exemplo, descompactamos em C:\opt\mysql-8.0.16-winx64\

Inicializando o MysQL

Abra um Prompt de Comando e digite:

cd C:\opt\mysql-8.0.16-winx64\bin
C:\opt\mysql-8.0.16-winx64\bin\mysqld --initialize

Subindo o MySQL

Na pasta bin, digite:

C:\opt\mysql-8.0.16-winx64\bin\mysqld --console

Testando conexão

Com o servidor no ar, abra outro Prompt de Comando e digite:

C:\opt\mysql-8.0.16-winx64\bin\mysql -u root -h localhost

Ocorrerá um erro de autenticação, pois não foi enviada a senha. Veja o erro abaixo:

ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)

Verificando senha do MySQL

Localize o arquivo com extensão .err (no meu caso o arquivo é Lenovo-I7.err) e abra no editor. Verifique que a senha é apresentada no arquivo.

A temporary password is generated for root@localhost: hjD8X3e8Jq&W

Conectando com a senha

Agora, utilize o comando abaixo, com a senha obtida no arquivo de erro.

C:\opt\mysql-8.0.16-winx64\bin\mysql -u root -h localhost -p

Quando solicitar a senha, informe:

Enter password: hjD8X3e8Jq&W (aparecerá com asteriscos)

Deverá aparecer o prompt com o MySQL conectado

mysql >

Alterando a senha do usuário root

Conectado no MySQL, digite:

mysql> alter user 'root'@'localhost' identified by 'root';
Query OK, 0 rows affected (0.01 sec)

Baixando o servidor

Para baixar o servidor, de forma normal, digite:

C:\opt\mysql-8.0.16-winx64\bin\mysqladmin -u root -p shutdown

Enter password: root

Instalando como serviço

Para instalar o MySQL como serviço do Windows, digite:

C:\opt\mysql-8.0.16-winx64\bin\mysqld --install "MySQL 8.0.16"

Service successfully installed.

NOTA: Importante executar o Prompt de Comando como Administrador!!!

Para verificar o serviço, execute o comando abaixo (na janela que se abrirá, perceba que existe o serviço MySQL 8.0.16:

services.msc

 

Instalando Anaconda no Ubuntu

Este post demonstra a instalação e comandos básicos do Anaconda no Ubuntu.

Baixando o Anaconda

Acesse a URL

https://www.anaconda.com/distribution/

Instalando o Anaconda

Executar o arquivo Anaconda3-2018.12-Linux-x86_64.sh

$ sh Anaconda3-2018.12-Linux-x86_64.sh

A instalação será efetuada na pasta padrão ~/anaconda3

Configurando Path

Para adicionar o caminho dos programas no Path, digite:

$ export PATH=~/anaconda3/bin:$PATH

Atualizando o Conda

$ conda update -n base -c defaults conda

Criando ambiente

Para criar um ambiente, digite:

$ conda create --name myenv

Ativando ambiente

$ source activate myenv

Rodando o Jupyter

$ jupyter notebook

Executando o Anaconda Navigator

O Anaconda Navigator é uma interface gráfica incluída no Anaconda que permite que você inicie aplicativos e gerencie pacotes, ambientes e canais Conda sem a necessidade de usar linha de comando.

$ anaconda-navigator

Docker – Kubernetes – Openshift

Docker

Docker surgiu em 2013 inicialmente como uma camada sobre a funcionalidade do Kernel do Linux chamada LXC (Linux Containers), que permite a execução de processos de maneira isolada e restrita. Posteriormente trocaram a LXC pela libcontainer, permitindo seu uso além do Linux.
A tecnologia de containers possibilita rodar processos, serviços e aplicativos de maneira isolada, ou seja, um não enxerga o outro, e de forma limitada, no qual cada um possui um limite dos recursos de hardware disponíveis como quantidade de memória e espaço em disco.
Containers são mais “leves” do que máquinas virtuais pois não precisam simular o hardware e não precisam carregar um sistema operacional completo antes de executar uma aplicação. Utilizam como base Imagens Docker que são arquivos compactados contendo um sistema de arquivos e a aplicação a ser executada.
Basicamente uma aplicação é empacotada na forma de uma Imagem Docker e cada instância em execução é chamada de container.

Kubernetes

Orquestração de containers é a capacidade de provisionar automaticamente a infraestrutura necessária para atender às solicitações das aplicações web por meio de de containers do Docker.
Kubernetes, também conhecido como k8s, é uma ferramenta open source criada pela Google e distribuída em 2014 para automatização de deploys e gerenciamento de containers. Com ele é possível criar um cluster de containers em clouds privadas ou públicas (AWS, Google Cloud, etc.).
Algumas vantagens do Kubernetes:

  • Container sempre online: verifica a saúde da aplicação e recria o container se identificar alguma anomalia.
  • Autoscaling: obtém métricas e verifica se há necessidade de crescer horizontalmente.
  • Descoberta de Serviço: containers recebem um endereço IP e conseguem enxergar um ao outro por meio de uma rede virtual.
  • Crescimento Horizontal: com um simples comando é possível aumentar o número de containers da mesma imagem.
  • Balanceador de Carga: utiliza load balancer para dividir a carga de requisições recebidas entre os containers.
  • Rollbacks automáticos: se algo der errado, Kubernetes volta automaticamente à versão anterior da aplicação.
  • Execução em Batch: permite rodar comandos em batch como containers.

Openshift

Openshift é uma plataforma desenvolvida pela Red Hat que utiliza como base o Kubernetes. Atualmente há 3 distribuições:

  1. Openshift Origin: versão open source utilizada para quem deseja criar um cluster sem precisar pagar licenças.
  2. Openshift Enterprise: versão comercializada pela Red Hat baseada no Origin e suportada oficialmente pelo Red Hat Linux.
  3. Openshift Online: plataforma de serviço fornecida pela Red Hat concorrente do Heroku e Google App Engine.

Mas quais são as vantagens e diferenças entre o Openshift e Kubernetes? O Openshift introduziu algumas camadas que o tornam mais amigável e fácil de integrar com soluções de softwares utilizadas no mundo corporativo. Algumas das vantagens do Openshift em relação ao Kubernetes:

  • Source to Image (S2I) e Build Config: capacidade de obter o código fonte da aplicação a partir de um repositório Git e criar uma Imagem Docker pronta para uso. Um Build é disparado quando há uma mudança no código do repositório através de um Webhook.
  • Integrated Docker Registry: possui um Docker Registry privado utilizado para armazenar as Imagens Docker criadas pelo processo de Source to Image.
  • Image Stream: o Openshift faz tracking das Imagens Docker e recria os containers quando detecta uma mudança na Imagem.
  • Deployment Config: um macro serviço que detecta quando há uma alteração na configuração, por exemplo uma mudança no valor de uma variável de ambiente, e recria os containers.
  • Policies: políticas de autorização para usuários, permitindo por exemplo que um determinado usuário consiga apenas visualizar logs dos containers.
  • Webconsole: uma interface web amigável que possibilita escalar containers, visualizar logs de aplicações e containers e alterar configurações de pods, services, routes, deployments, etc.

Cursos gratuitos – Data Science Academy

Abaixo, alguns cursos gratuitos da Data Science Academy

Curso Gratuito de Microsoft Power BI (Carga Horária: 54 Horas):
Clique aqui
Curso Gratuito de Fundamentos de Big Data (Carga Horária: 8 Horas): 
Clique aqui
Curso Gratuito de Python Fundamentos para Análise de Dados (Carga Horária: 54 Horas):
Clique aqui
Curso Gratuito de Introdução a Ciência de Dados (Carga Horária: 8 Horas):
Clique aqui
Curso Gratuito de Fundamentos de Inteligência Artificial (Carga Horária: 8 Horas): 
Clique aqui

Exemplo de Modelagem Cassandra

Escolher o modelo de dados certo é a parte mais difícil de usar o Cassandra. Se você tiver um histórico relacional, o CQL parecerá familiar, mas a maneira como você o utiliza pode ser muito diferente. O objetivo deste post é explicar as regras básicas que você deve ter em mente ao projetar seu esquema para o Cassandra. Se você seguir essas regras, obterá um bom desempenho imediato. Melhor ainda, seu desempenho deve ser dimensionado linearmente à medida que você adiciona nós ao cluster.

Não-objetivos

Os desenvolvedores que vêm de um background relacional geralmente carregam regras sobre modelagem relacional e tentam aplicá-las a Cassandra. Para evitar perder tempo com regras que realmente não importam com o Cassandra, quero destacar algumas não- metas:

Minimize o número de gravações

As gravações em Cassandra não são gratuitas, mas são muito baratas. O Cassandra é otimizado para alta taxa de transferência, e quase todas as gravações são igualmente eficientes [1] . Se você pode realizar gravações extras para melhorar a eficiência de suas consultas de leitura, quase sempre é uma boa compensação. As leituras tendem a ser mais caras e são muito mais difíceis de ajustar.

Minimize a duplicação de dados

Desnormalização e duplicação de dados é um fato da vida com Cassandra. Não tenha medo disso. Geralmente, o espaço em disco é o recurso mais barato (comparado à CPU, memória, IOPs de disco ou rede), e Cassandra é arquitetada em torno desse fato. Para obter as leituras mais eficientes, você geralmente precisa duplicar os dados.

Além disso, a Cassandra não tem o JOIN s, e você não quer realmente usá-los de maneira distribuída.

Objetivos Básicos

Estas são as duas metas de alto nível para seu modelo de dados:

  1. Espalhar dados uniformemente ao redor do cluster
  2. Minimize o número de partições lidas

Há outras metas menores a serem lembradas, mas estas são as mais importantes. Na maioria das vezes, vou me concentrar no básico de alcançar esses dois objetivos.Existem outros truques que você pode usar, mas você deve saber como avaliá-los primeiro.

Regra 1: espalhar dados uniformemente em torno do cluster

Você deseja que todos os nós do cluster tenham aproximadamente a mesma quantidade de dados. Cassandra torna isso fácil, mas não é um dado. As linhas são espalhadas pelo cluster com base em um hash da chave de partição , que é o primeiro elemento da PRIMARY KEY . Então, a chave para espalhar dados uniformemente é esta: escolha uma boa chave primária . Vou explicar como fazer isso daqui a pouco.

Regra 2: Minimizar o número de partições lidas

Partições são grupos de linhas que compartilham a mesma chave de partição. Quando você emite uma consulta de leitura, deseja ler as linhas do menor número possível de partições.

Por que isso é importante? Cada partição pode residir em um nó diferente. O coordenador geralmente precisará emitir comandos separados para separar nós para cada partição solicitada. Isso adiciona muita sobrecarga e aumenta a variação na latência. Além disso, mesmo em um único nó, é mais caro ler de várias partições do que de uma única, devido à maneira como as linhas são armazenadas.

Regras conflitantes?

Se é bom minimizar o número de partições das quais você lê, por que não colocar tudo em uma única partição grande? Você acabaria violando a Regra nº 1, que é espalhar dados uniformemente pelo cluster.

O ponto é que esses dois objetivos geralmente estão em conflito, então você precisa tentar equilibrá-los.

Modelo em torno de suas consultas

A maneira de minimizar as leituras de partição é modelar seus dados para atender às suas consultas. Não modele em torno de relações. Não modele em torno de objetos.Modelo em torno de suas consultas. Veja como você faz isso:

Etapa 1: determine quais consultas devem ser suportadas

Tente determinar exatamente quais consultas você precisa dar suporte. Isso pode incluir muitas considerações que você pode não pensar no início. Por exemplo, você pode precisar pensar sobre:

  • Agrupamento por um atributo
  • Ordenação por um atributo
  • Filtrando com base em algum conjunto de condições
  • Impondo exclusividade no conjunto de resultados
  • etc …

As alterações em apenas um desses requisitos de consulta geralmente garantirão uma alteração do modelo de dados para máxima eficiência.

Etapa 2: tente criar uma tabela onde você possa satisfazer sua consulta lendo (aproximadamente) uma partição

Na prática, isso geralmente significa que você usará aproximadamente uma tabela por padrão de consulta. Se você precisar oferecer suporte a vários padrões de consulta, geralmente precisará de mais de uma tabela.

Para colocar isso de outra forma, cada tabela deve pré-construir a “resposta” para uma consulta de alto nível que você precisa dar suporte. Se você precisa de diferentes tipos de respostas, geralmente precisa de tabelas diferentes. É assim que você otimiza para leituras.

Lembre-se, a duplicação de dados está bem. Muitas de suas tabelas podem repetir os mesmos dados.

Aplicando as regras: exemplos

Para mostrar alguns exemplos de um bom processo, vou orientá-lo no design de um modelo de dados para alguns problemas simples.

Exemplo 1: pesquisa de usuário

O requisito de alto nível é “nós temos usuários e queremos procurá-los”. Vamos seguir os passos:

Etapa 1 : Determinar quais consultas específicas para suporte 
Digamos que queremos ser capazes de procurar um usuário pelo nome de usuário ou pelo e-mail. Com o método de pesquisa, devemos obter o conjunto completo de detalhes do usuário.

Etapa 2 : tente criar uma tabela onde você possa satisfazer sua consulta lendo (aproximadamente) uma partição 
Como queremos obter todos os detalhes para o usuário com o método de pesquisa, é melhor usar duas tabelas:

1234567891011CREATE TABLE users_by_username (username text PRIMARY KEY,email text,age int) CREATE TABLE users_by_email (email text PRIMARY KEY,username text,age int)

Agora, vamos verificar as duas regras para este modelo:

Espalha os dados uniformemente? Cada usuário recebe sua própria partição, então sim. 
Partições mínimas são lidas? Nós só temos que ler uma partição, então sim.

Agora, vamos supor que tentamos otimizar para os não- objetivos e, em vez disso, criamos esse modelo de dados:

12345678910111213141516CREATE TABLE users (id uuid PRIMARY KEY,username text,email text,age int) CREATE TABLE users_by_username (username text PRIMARY KEY,id uuid) CREATE TABLE users_by_email (email text PRIMARY KEY,id uuid)

Esse modelo de dados também distribui os dados de maneira uniforme, mas há uma desvantagem: agora temos que ler duas partições, uma de users_by_username (ou users_by_email ) e outra de usuários . Portanto, as leituras são aproximadamente duas vezes mais caras.

Exemplo 2: grupos de usuários

Agora o requisito de alto nível mudou. Os usuários estão em grupos e queremos que todos os usuários entrem em um grupo.

Etapa 1 : Determinar quais consultas específicas para suporte 
Queremos obter as informações completas do usuário para cada usuário em um grupo específico. Ordem dos usuários não importa.

Etapa 2 : tente criar uma tabela onde você possa satisfazer sua consulta lendo (aproximadamente) uma partição 
Como podemos encaixar um grupo em uma partição? Podemos usar um PRIMARY KEY composto para isso:

1234567CREATE TABLE groups (groupname text,username text,email text,age int,PRIMARY KEY (groupname, username))

Observe que a PRIMARY KEY tem dois componentes: groupname , que é a chave de particionamento, e username , que é chamado de chave de clustering. Isso nos dará uma partição por nome de grupo . Dentro de uma determinada partição (grupo), as linhas serão ordenadas por nome de usuário . Buscar um grupo é tão simples quanto fazer o seguinte:

1SELECT * FROM groups WHERE groupname = ?

Isso satisfaz o objetivo de minimizar o número de partições que são lidas, porque precisamos apenas ler uma partição. No entanto, ele não funciona tão bem com o primeiro objetivo de espalhar uniformemente os dados ao redor do cluster. Se tivermos milhares ou milhões de pequenos grupos com centenas de usuários cada, teremos uma distribuição bastante uniforme. Mas se houver um grupo com milhões de usuários, todo o fardo será suportado por um nó (ou um conjunto de réplicas).

Se quisermos distribuir a carga de maneira mais uniforme, há algumas estratégias que podemos usar. A técnica básica é adicionar outra coluna à PRIMARY KEY para formar uma chave de partição composta. Aqui está um exemplo:

12345678CREATE TABLE groups (groupname text,username text,email text,age int,hash_prefix int,PRIMARY KEY ((groupname, hash_prefix), username))

A nova coluna, hash_prefix , contém um prefixo de um hash do nome de usuário. Por exemplo, pode ser o primeiro byte do hash módulo quatro. Juntamente com groupname , essas duas colunas formam a chave de partição composta. Em vez de um grupo residindo em uma partição, ela agora está espalhada em quatro partições.Nossos dados estão mais uniformemente distribuídos, mas agora temos que ler quatro vezes mais partições. Este é um exemplo dos dois objetivos conflitantes. Você precisa encontrar um bom equilíbrio para seu caso de uso específico. Se você fizer um monte de leituras e grupos não ficarem muito grandes, talvez mudar o valor do módulo de quatro para dois seria uma boa escolha. Por outro lado, se você fizer muito poucas leituras, mas qualquer grupo pode crescer muito, mudar de quatro para dez seria uma escolha melhor.

Existem outras maneiras de dividir uma partição, que abordarei no próximo exemplo.

Antes de prosseguirmos, deixe-me apontar algo sobre esse modelo de dados: estamos duplicando as informações do usuário muitas vezes, uma vez para cada grupo. Você pode ser tentado a tentar um modelo de dados como esse para reduzir a duplicação:

123456789101112CREATE TABLE users (id uuid PRIMARY KEY,username text,email text,age int) CREATE TABLE groups (groupname text,user_id uuid,PRIMARY KEY (groupname, user_id))

Obviamente, isso minimiza a duplicação. Mas quantas partições precisamos ler? Se um grupo tiver 1000 usuários, precisamos ler 1001 partições. Isso é provavelmente 100 vezes mais caro para ler do que nosso primeiro modelo de dados. Se as leituras precisam ser eficientes, isso não é um bom modelo. Por outro lado, se as leituras são extremamente raras, mas as atualizações das informações do usuário (digamos, o nome de usuário) são extremamente comuns, esse modelo de dados pode realmente fazer sentido. Certifique-se de levar em consideração sua proporção de leitura / atualização ao projetar seu esquema.

Exemplo 3: grupos de usuários por data de associação

Suponha que continuemos com o exemplo anterior de grupos, mas precisemos adicionar suporte para obter os usuários X mais recentes em um grupo.

Podemos usar uma tabela semelhante à última:

12345678CREATE TABLE group_join_dates (groupname text,joined timeuuid,username text,email text,age int,PRIMARY KEY (groupname, joined))

Aqui estamos usando um timeuuid (que é como um timestamp, mas evita colisões) como a coluna de clustering. Dentro de um grupo (partição), as linhas serão ordenadas no momento em que o usuário ingressou no grupo. Isso nos permite obter os usuários mais novos em um grupo da seguinte forma:

1234SELECT * FROM group_join_datesWHERE groupname = ?ORDER BY joined DESCLIMIT ?

Isso é razoavelmente eficiente, pois estamos lendo uma fatia de linhas de uma única partição. No entanto, em vez de sempre usar o DESC associado ao ORDER BY , o que torna a consulta menos eficiente, podemos simplesmente inverter a ordem de cluster:

12345678CREATE TABLE group_join_dates (groupname text,joined timeuuid,username text,email text,age int,PRIMARY KEY (groupname, joined)) WITH CLUSTERING ORDER BY (joined DESC)

Agora podemos usar a consulta um pouco mais eficiente:

123SELECT * FROM group_join_datesWHERE groupname = ?LIMIT ?

Como no exemplo anterior, poderíamos ter problemas com os dados sendo distribuídos uniformemente ao redor do cluster, caso algum grupo ficasse muito grande. Nesse exemplo, dividimos as partições de forma aleatória, mas, nesse caso, podemos utilizar nosso conhecimento sobre os padrões de consulta para dividir as partições de uma maneira diferente: por um intervalo de tempo.

Por exemplo, podemos dividir partições por data:

123456789CREATE TABLE group_join_dates (groupname text,joined timeuuid,join_date text,username text,email text,age int,PRIMARY KEY ((groupname, join_date), joined)) WITH CLUSTERING ORDER BY (joined DESC)

Estamos usando uma chave de partição composta novamente, mas desta vez estamos usando a data de associação. Cada dia, uma nova partição será iniciada. Ao consultar os usuários mais novos do X, primeiro consultaremos a partição de hoje, depois a de ontem e assim por diante, até que tenhamos usuários X. Talvez tenhamos que ler várias partições antes que o limite seja atingido.

Para minimizar o número de partições que você precisa consultar, tente selecionar um intervalo de tempo para dividir as partições que geralmente permitem que você consulte apenas uma ou duas partições. Por exemplo, se normalmente precisamos dos dez usuários mais novos, e os grupos geralmente adquirem três usuários por dia, devemos dividir por intervalos de quatro dias em vez de um único dia [2] .

Resumo

As regras básicas de modelagem de dados cobertas aqui aplicam-se a todas as versões (atualmente) existentes do Cassandra e são muito prováveis ​​de se aplicarem a todas as versões futuras. Outros problemas de modelagem de dados menores, como lidar com marcas de exclusão , também podem precisar ser considerados, mas esses problemas têm maior probabilidade de mudar (ou serem atenuados) por versões futuras do Cassandra.

Além das estratégias básicas abordadas aqui, alguns dos recursos mais extravagantes do Cassandra, como coleções , tipos definidos pelo usuário e colunas estáticas , também podem ser usados ​​para reduzir o número de partições que você precisa ler para satisfazer uma consulta. Não se esqueça de considerar essas opções ao projetar seu esquema.

Fonte: https://www.datastax.com/dev/blog/basic-rules-of-cassandra-data-modeling

Cassandra e Docker – Ubuntu

Este post apresenta a instalação e utilização do Apache Cassandra, usando Docker.

Baixando a Imagem Docker

$ sudo docker pull cassandra

Esse comando efetuará o download da última versão do Cassandra (latest)

Verificando a Imagem

$ sudo docker images

Resultado

REPOSITORY TAG     IMAGE ID      CREATED     SIZE
cassandra latest 8ea89760ce2b 5 weeks ago 323MB

Subindo o Cassandra

$ sudo docker run --name node1 -d cassandra:lastest

Resultado

f451246389a40761b5a70cbb2d665801f3b2356afcd3abf6ee9a7aa4bd1fe064

Baixando o Cassandra

$ sudo docker stop f451246389a40761b5a70cbb2d665801f3b2356afcd3abf6ee9a7aa4bd1fe064

Removendo

$ sudo docker rm node1

Verificando processos

$ docker exec -it node1 nodetool status

Ferramenta shell CQL

Dentro do container é possível executar o cqlsh.

$ docker exec -it node1 cqlsh
Connected to Test Cluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.0 | CQL spec 3.4.4 | Native protocol v4]
Use HELP for help.
cqlsh>

Criando Keyspace

cqlsh> CREATE KEYSPACE myspace WITH replication = {'class': 'SimpleStrategy', 'replication_factor' : 3};

Criando uma tabela

CREATE TABLE myspace.exam (
patient_id int,
id int,
date timeuuid,
details text,
PRIMARY KEY (patient_id, id));

Inserindo dados

INSERT INTO exam (patient_id,id,date,details) values (1,1,now(),'first exam patient 1');
INSERT INTO exam (patient_id,id,date,details) values (1,2,now(),'second exam patient 1');
INSERT INTO exam (patient_id,id,date,details) values (2,1,now(),'first exam patient 2');
INSERT INTO exam (patient_id,id,date,details) values (3,1,now(),'first exam patient 3');

Consultando dados

cqlsh:patient> select * from exam where patient_id=1;

Instalando MySQL no Ubuntu usando Docker

Baixando a Imagem

$ sudo docker pull mysql/mysql-server:latest

Rodando o MySQL

$ sudo docker run -it –name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql

Verificando Logs

$ sudo docker logs mysql

Parando o MySQL

$ sudo docker stop mysql

Reiniciando o MySQL

$ sudo docker start mysql

Removendo o MySQL

$ sudo docker rm mysql

Forma alternativa

$ sudo docker run -d –name=mysql-server -p 3306:3306 -v mysql-data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root mysql

Listando imagens

$ sudo docker images

REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest ecac195d15af 23 hours ago 516MB
mongo latest 0e120e3fce9a 3 months ago 449MB
amazon/dynamodb-local latest 7984b9b533e7 5 months ago 613MB

$ sudo docker rmi ecac195d15af

Instalando ELK no Ubuntu

Este post apresenta de forma fácil, a instalação do ELK no Ubuntu.

Baixando a imagem Docker

Para baixar a imagem ELK, execute o comando abaixo.

$ sudo docker pull sebp/elk:latest

Subindo a imagem ELK

Para subir a aplicação, execute o comando abaixo.

$ sudo docker run -p 5601:5601 -p 9200:9200 -p 5044:5044 -it --name elk sebp/elk

OBS: Se apresentar erro de memória, execute o comando abaixo.

$ sudo sysctl -w vm.max_map_count=262144

Esse comando é uma solução temporária, ao reiniciar o sistema, volta o valor padrão.

Para configurar a memória de forma definitiva, utilize o comando:

$ sudo gedit /etc/sysctl.conf

Adicionar a linha abaixo e salvar o arquivo.

vm.max_map_count=262144

Após subir a aplicação, pode-se testar os ambientes.

Elasticsearch:

http://localhost:9200

Kibana:

http://localhost:5601

Para a imagem

$ sudo docker ps

Resultado:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b1600afd168 sebp/elk “/usr/local/bin/star…” 15 minutes ago Up 14 minutes 0.0.0.0:5044->5044/tcp, 0.0.0.0:5601->5601/tcp, 0.0.0.0:9200->9200/tcp, 9300/tcp elk

Para com o id do container

$ sudo docker stop 7b1600afd168

Remover o nome elk

$ sudo docker rm elk