Os bancos de dados de grafos ajudam você a descobrir insights com a modelagem das entidades de dados e os relacionamentos entre elas. O JanusGraph é um banco de dados gráfico compatível com grandes volumes de dados. Neste tutorial, mostramos como executar o JanusGraph no Google Cloud com o Google Kubernetes Engine funcionando como a plataforma de orquestração e o Bigtable como back-end de armazenamento. Ele é destinado a arquitetos de sistemas, administradores de bancos de dados e profissionais de DevOps, interessados em executar o banco de dados de grafos do JanusGraph no Google Cloud usando um banco de dados gerenciado como back-end de armazenamento. Pressupomos que você conheça o Google Kubernetes Engine (GKE), os pods do Kubernetes, gráficos do Helm, Bigtable e Elasticsearch. O conhecimento do framework de computação de grafos Apache TinkerPop e da máquina e linguagem de transversal em grafos Gremlin (links em inglês) não é obrigatório, mas é necessário para usar o Janusgraph além dos exemplos fornecidos neste tutorial.
Visão geral
Na terminologia de grafos, as entidades são chamadas de nós ou vértices e as relações são chamadas de arestas. No JanusGraph, os vértices e as arestas podem ter outros dados associados, disponibilizados pelas propriedades.
A ilustração anterior é um exemplo de um grafo de propriedade.
Os bancos de dados de gráficos ajudam a modelar vários domínios e atividades:
- redes sociais
- Transações financeiras (para análise de fraude)
- Redes de sistema físicas ou virtuais
Ao criar bancos de dados de grafos, às vezes são criados milhões ou até bilhões de vértices e arestas. Quando você usa o JanusGraph com o Bigtable como camada de armazenamento subjacente, é possível executar consultas rápidas (conhecidas como transversais em grafos) e escalonar a camada de armazenamento de maneira independente, de acordo com o tamanho e a capacidade de processamento que você necessita. O JanusGraph também usa um back-end de indexação plugável para fornecer indexação de texto completo para propriedades de vértice e aresta. Neste tutorial, você implanta uma infraestrutura escalonável do JanusGraph no GKE. O Elasticsearch é usado como back-end de indexação para execução em pods de um StatefulSet. O Bigtable é usado como back-end de armazenamento. Quando terminar, transfira os relacionamentos atuais dos dados do grafo. No diagrama a seguir, você vê como esses elementos se encaixam.
Esse diagrama exibe a implantação do JanusGraph no GKE com o ElasticSearch e o Bigtable.
Dados do JanusGraph no Bigtable
Os dados do grafo são armazenados pelo JanusGraph como uma lista de adjacências. Cada linha representa um vértice, todos os vértices adjacentes (arestas) e metadados de propriedade sobre os vértices e as arestas. A chave de linha é o identificador exclusivo do vértice. Cada relação entre o vértice e outro vértice e quaisquer propriedades que definam melhor o relacionamento são armazenados como uma aresta ou coluna de propriedades de arestas. O qualificador de coluna e o valor da coluna armazenam dados que definem a borda, de acordo com as práticas recomendadas do Bigtable. Cada propriedade de vértice é armazenada como uma coluna separada, mais uma vez usando o qualificador de coluna e o valor da coluna para definir a propriedade.
No diagrama a seguir, você vê essa estrutura de armazenamento.
O diagrama mostra a estrutura de armazenamento lógico para um pequeno fragmento de grafo com detalhes lógicos para duas linhas de vértices. No diagrama, as duas linhas de exemplo representam dois vértices. O primeiro vértice é rotulado com uma única propriedade de vértice e está relacionado a dois outros vértices por duas arestas separadas. O segundo vértice contém colunas com duas propriedades e uma aresta.
A ilustração a seguir, do modelo de dados lógico de borda do vértice, mostra alguns detalhes sobre os qualificadores e valores de coluna para uma coluna de borda ou de propriedade de borda.
Para cada vértice adjacente, uma coluna armazena os metadados sobre a aresta. O qualificador de coluna contém metadados sobre o relacionamento da aresta e sobre a direção da aresta, além de um ponteiro para o vértice adjacente. O valor da coluna contém o rótulo da aresta e quaisquer outras propriedades dela. Como as transversais podem ser seguidas em qualquer direção, as bordas são armazenadas duas vezes, uma para cada extremidade da relação da borda. O armazenamento bidirecional da aresta aumenta de forma significativa o desempenho da transversal, mas tem algumas compensações devido à redundância do espaço de armazenamento extra e de mutações de arestas não atômicas.
O diagrama a seguir é o modelo de dados lógico de uma coluna de propriedade de vértice.
A ilustração anterior fornece detalhes sobre os qualificadores de coluna e os valores de uma coluna de aresta.
Cada propriedade de vértice é armazenada como uma coluna separada. O qualificador de coluna é um identificador exclusivo da chave de propriedade. O valor da coluna contém um identificador da propriedade e o valor da propriedade.
O JanusGraph também depende da ordenação lexicográfica de linhas e qualificadores de coluna do Bigtable para melhorar o desempenho da consulta.
Objetivos
- Criar uma instância do Bigtable.
- Crie um cluster do GKE.
- Instalar o Helm.
- Usar um gráfico do Helm para implantar o JanusGraph e o ElasticSearch.
- Use o console do Gremlin e se conecte ao JanusGraph.
- Carregar e consultar dados de amostra.
Custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
- Google Kubernetes Engine (GKE)
- Compute Engine VMs are provisioned by GKE
- Bigtable
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.
Pré-requisitos
- Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Bigtable, Compute Engine, and GKE APIs.
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Make sure that billing is enabled for your Google Cloud project.
-
Enable the Bigtable, Compute Engine, and GKE APIs.
Prepare o ambiente
Neste tutorial, você usa o Cloud Shell para inserir comandos. O Cloud Shell fornece acesso à linha de comando no Console do Google Cloud e inclui a Google Cloud CLI e outras ferramentas necessárias para desenvolver no Google Cloud. O Cloud Shell aparece como uma janela na parte inferior do Console do Google Cloud. A inicialização leva vários minutos, mas a janela aparece imediatamente.
-
In the Google Cloud console, activate Cloud Shell.
No Cloud Shell, defina as variáveis de ambiente para a zona do Compute Engine em que você vai criar o cluster do Bigtable e o cluster do GKE, sendo que, para este último, você precisa também dar um nome e especificar o tipo de nó e a versão:
export PROJECT_ID=PROJECT_ID export GCP_ZONE=REGION export GKE_CLUSTER_NAME=GKE_CLUSTER_NAME export GKE_NODE_TYPE=n1-standard-4 export GKE_VERSION=1.20
Substitua:
PROJECT_ID
pelo identificador do projeto;REGION
pela zona em que o cluster do Bigtable e o do GKE serão criados;GKE_CLUSTER_NAME
pelo nome do cluster do GKE.
O comando será semelhante ao seguinte exemplo:
export PROJECT_ID=bt-janusgraph-project-id export GCP_ZONE=us-central1-f export GKE_CLUSTER_NAME=janusgraph-gke export GKE_NODE_TYPE=n1-standard-4 export GKE_VERSION=1.20
Crie o cluster do GKE em que o JanusGraph será implantado:
gcloud container clusters create ${GKE_CLUSTER_NAME} \ --zone=${GCP_ZONE} \ --cluster-version=${GKE_VERSION} \ --machine-type ${GKE_NODE_TYPE} \ --scopes "https://www.googleapis.com/auth/cloud-platform"
Criar uma instância do Bigtable
Como back-end de armazenamento do JanusGraph, este tutorial usa o Bigtable, que pode ser escalonado rapidamente para atender às suas necessidades. Neste tutorial, usamos um cluster de desenvolvimento de nó único, que é econômico e suficiente para o este propósito. Inicie projetos com um cluster menor e mova para um maior quando estiver pronto para trabalhar com dados de produção. A documentação do Bigtable inclui uma abordagem detalhada sobre desempenho e escalonamento para ajudar você a escolher um tamanho de cluster para seu próprio trabalho.
No Cloud Shell, defina a variável de ambiente para o identificador da instância do Bigtable:
export BIGTABLE_INSTANCE_ID=BIGTABLE_INSTANCE_ID
Substitua
BIGTABLE_INSTANCE_ID
pelo identificador da instância do Bigtable.Crie a instância do Bigtable:
gcloud bigtable instances create ${BIGTABLE_INSTANCE_ID} \ --cluster-config=id=${BIGTABLE_INSTANCE_ID}-${GCP_ZONE},zone=${GCP_ZONE},nodes=1 \ --display-name=${BIGTABLE_INSTANCE_ID}-${GCP_ZONE}
Instalar e configurar o Helm
Você usa o Helm para implantar aplicativos em seu cluster do Kubernetes. Neste tutorial, você usa o Helm para implantar os serviços do JanusGraph e do Elasticsearch no cluster do GKE.
No Cloud Shell, instale o Helm:
curl -fsSL -o get_helm.sh \ https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 chmod 700 get_helm.sh DESIRED_VERSION=v3.5.0 ./get_helm.sh
Adicione o repositório de gráfico
elastic
para que a dependência de gráfico do Elasticsearch seja encontrada durante a implantação do gráfico do JanusGraph:helm repo add elastic https://helm.elastic.co
Esse repositório de gráfico é hospedado pelo Elastic, criador do Elasticsearch.
Usar o Helm para instalar o JanusGraph e o Elasticsearch
Nesta seção, você usa um gráfico do Helm para implantar o JanusGraph e o Elasticsearch no cluster do Kubernetes.
O gráfico Helm é extraído do GitHub. A implantação incluída no repositório do gráfico Helm implanta um conjunto de três pods JanusGraph por trás de um serviço que iniciará um balanceador de carga de aplicativo interno. Quando os pods estão em execução, as sondagens de inicialização e atividade fazem solicitações HTTP para realizar verificações de integridade no servidor JanusGraph em cada pod. Além disso, o gráfico inclui uma tabela de dependências fornecida pelo Elastic que implanta três pods do Elasticsearch em um StatefulSet.
No Cloud Shell, defina as variáveis de ambiente para os nomes do Helm e do JanusGraph:
export HELM_REPO=bigtable-janusgraph-helm export JANUSGRAPH_VERSION=0.5.3 export HELM_CHART_RELEASE_VERSION=1 export HELM_CHART_RELEASE_TAG=${JANUSGRAPH_VERSION}-${HELM_CHART_RELEASE_VERSION} export HELM_CHART_RELEASE_TAG_HASH=f8b271a4854d4a553dd5e9ba014d077fb098d9ab export HELM_CHART_NAME=janusgraph-bigtable
Extraia o gráfico do Helm do GitHub:
git clone https://github.com/GoogleCloudPlatform/${HELM_REPO} \ --branch ${HELM_CHART_RELEASE_TAG}
Navegue até o diretório do gráfico Helm:
cd ${HELM_REPO}
Por motivos de segurança, use o hash de confirmação para verificar:
HEAD_COMMIT_HASH=$(git rev-parse --verify HEAD) if [ _${HEAD_COMMIT_HASH} == _${HELM_CHART_RELEASE_TAG_HASH} ] then echo "Commit hash verified" fi
Se a resposta não for semelhante ao seguinte, não continue, porque a integridade da tag clonada não foi verificada.
Commit hash verified
Atualize as dependências do gráfico:
helm dep update
Navegue até o diretório pai:
cd ..
Defina variáveis de ambiente para os nomes das entidades Helm e JanusGraph:
export HELM_RELEASE_NAME=janusgraph-bigtable-elastic export ELASTICSEARCH_CLUSTER_NAME=${HELM_RELEASE_NAME}-elasticsearch export BIGTABLE_JANUSGRAPH_TABLE=janusgraph-table
Crie um arquivo
values.yaml
, que forneça ao Helm as propriedades de configuração a serem usadas ao implantar o gráfico do JanusGraph:cat > values.yaml << EOF image: repository: docker.io/janusgraph/janusgraph tag: 0.5.3 pullPolicy: IfNotPresent replicaCount: 3 service: type: LoadBalancer port: 8182 serviceAnnotations: networking.gke.io/load-balancer-type: "Internal" elasticsearch: deploy: true clusterName: ${ELASTICSEARCH_CLUSTER_NAME} properties: storage.backend: hbase storage.directory: null storage.hbase.ext.google.bigtable.instance.id: ${BIGTABLE_INSTANCE_ID} storage.hbase.ext.google.bigtable.project.id: ${PROJECT_ID} storage.hbase.ext.hbase.client.connection.impl: com.google.cloud.bigtable.hbase2_x.BigtableConnection storage.hbase.short-cf-names: true storage.hbase.table: ${BIGTABLE_JANUSGRAPH_TABLE} index.search.backend: elasticsearch index.search.hostname: ${ELASTICSEARCH_CLUSTER_NAME}-master index.search.directory: null index.search.elasticsearch.health-request-timeout: 90s cache.db-cache: true cache.db-cache-clean-wait: 20 cache.db-cache-time: 180000 cache.db-cache-size: 0.5 cluster.max-partitions: 1024 graph.replace-instance-if-exists: true persistence: enabled: false debugLevel: INFO EOF
Implante o gráfico JanusGraph do Helm usando o arquivo
values.yaml
que você criou:helm upgrade --install \ --wait \ --timeout 600s \ ${HELM_RELEASE_NAME} \ ./${HELM_REPO} \ -f values.yaml
O processo de instalação aguarda até que todos os recursos estejam prontos antes de ser concluído. Esse processo pode levar vários minutos.
Verificar a implantação do JanusGraph
Quando o processo de instalação do Helm é concluído, é exibida uma seção NOTES
que
descreve uma experiência de primeiros passos. Siga as etapas descritas na seção
NOTES
para verificar se o ambiente do JanusGraph está
funcionando.
No Cloud Shell, verifique se os componentes do gráfico Helm foram implantados no GKE:
Verifique a implantação do JanusGraph:
kubectl get deployments
Quando a implantação é bem-sucedida, a resposta é a seguinte:
NAME READY UP-TO-DATE AVAILABLE AGE janusgraph-bigtable-elastic 3/3 3 3 3m28s
Verifique o StatefulSet do Elasticsearch:
kubectl get statefulsets
Quando tudo está funcionando, a resposta é a seguinte:
NAME READY AGE janusgraph-bigtable-elastic-elasticsearch-master 3/3 4m13s
Defina uma variável de ambiente para o nome de um pod do Kubernetes que está executando o servidor JanusGraph Gremlin. O rótulo
app
do pod que está executando o servidor Gremlin é derivado do nome do gráfico Helm definido no arquivoChart.yaml
.export APP_LABEL_FROM_CHART_NAME=${HELM_CHART_NAME} export POD_NAME=$(kubectl get pods \ --namespace default \ -l "app=${APP_LABEL_FROM_CHART_NAME}, \ release=${HELM_RELEASE_NAME}" \ -o jsonpath="{.items[0].metadata.name}")
Conecte-se ao pod e execute o console do Gremlin, um shell de loop de impressão de avaliação de leitura (REPL, na sigla em inglês). O nome do contêiner também é derivado do nome do gráfico Helm em
Chart.yaml
.export GREMLIN_CONTAINER=${HELM_CHART_NAME} kubectl exec \ -c ${GREMLIN_CONTAINER} \ -it $POD_NAME \ -- /opt/janusgraph/bin/gremlin.sh
No console do Gremlin, conecte-se ao servidor Apache TinkerPop:
Inicie a sessão:
:remote connect tinkerpop.server conf/remote.yaml session
A resposta será semelhante a:
==>Configured localhost/127.0.0.1:8182-[b08972f2-a2aa-4312-8018-bcd11bc9812c]
Conecte-se ao servidor:
:remote console
A resposta será semelhante a:
==>All scripts will now be sent to Gremlin Server - [localhost/127.0.0.1:8182]-[b08972f2-a2aa-4312-8018-bcd11bc9812c] - type ':remote console' to return to local mode>
No console do Gremlin, verifique se o servidor dele está sendo executado corretamente, para isso, inspecione a variável
graph
, que representa a instância do grafo:graph
A resposta mostra que o servidor JanusGraph está sendo executado com um banco de dados compatível com o HBase, neste caso, o Bigtable, como o back-end de armazenamento.
==>standardjanusgraph[hbase:[127.0.0.1]]
No Gremlin, crie dois vértices
v1 = graph.addVertex(label, 'hello') v2 = graph.addVertex(label, 'world')
Uma resposta do console semelhante à seguinte mostra que os dois vértices foram adicionados:
==>v[4344] ==>v[4152]
Crie uma aresta que faça a conexão de ambos os vértices:
v1.addEdge('followedBy', v2)
Uma resposta do console semelhante à seguinte mostra que a borda entre os dois vértices foi adicionada:
==>e[17j-3co-4fmd-oe054][4344-followedBy->4152]
Confirme a transação:
graph.tx().commit()
Uma resposta do console com a palavra
null
mostra que as operações foram confirmadas:==>null
O diagrama a seguir ilustra o grafo criado pelos comandos.
O vértice identificado
hello
está conectado por uma aresta direcionada, identificada comofollowedBy
para o vérticeworld
identificado.Emita uma consulta do Gremlin para ver qual rótulo é para o vértice que segue uma aresta rotulada com
followedBy
do vértice que foi rotulado comohello
:g.V().has(label, 'hello').out('followedBy').label()
A sintaxe da consulta é explicada na próxima seção. Por enquanto, você verá a palavra
world
como resposta à consulta:==>world
Carregar e consultar um conjunto de dados de amostra
Agora que você implantou o JanusGraph e pode se conectar a ele usando o Gremlin, comece a carregar e consultar seus próprios dados. Para ver como é esse processo, carregue o conjunto de dados de amostra que está incluído no JanusGraph, o Gráfico dos deuses, que mostra divindades mitológicas do panteão romano e os respectivos imóveis no local.
No Gremlin, carregue o grafo criado anteriormente:
GraphOfTheGodsFactory.load(graph)
A resposta é a seguinte:
==>null
Emita uma consulta de transversal em grafo que encontre todos os irmãos de Júpiter:
g.V().has('name', 'jupiter').out('brother').values('name')
A tabela a seguir contém explicações sobre as etapas que a consulta percorre.
Etapa de análise Explicação g.V()
Comece com a coleção de vértices. has('name', 'jupiter')
Encontrar um que tenha a propriedade name
com o valorjupiter
.out('brother')
Deste ponto, seguir as arestas com o rótulo brother
.values('name')
Para os vértices de destino dessas arestas, usar a propriedade name
.==>neptune ==>pluto
Para se familiarizar mais com as consultas de percurso que são possíveis no conjunto de dados "Gráfico dos Deuses", teste outras consultas de amostra dos documentos do JanusGraph.
Verificar se os dados estão armazenados no Bigtable
Agora que você criou alguns dados de amostra no cluster do JanusGraph, verifique se o Bigtable foi usado como back-end de armazenamento.
Feche o console do Gremlin:
:q
No Cloud Shell, verifique se os dados foram mantidos na tabela
janusgraph
no Bigtable:cbt -project=${PROJECT_ID} \ -instance=${BIGTABLE_INSTANCE_ID} \ count ${BIGTABLE_JANUSGRAPH_TABLE}
A resposta será semelhante a esta:
2021/03/02 02:32:19 -creds flag unset, will use gcloud credential 101
O valor
101
na resposta representa o número de linhas emjanusgraph table
e pode ser diferente para você.
Verificar a criação do índice de pesquisa no Elasticsearch
No Cloud Shell, defina as variáveis para o índice e o nome do pod do Elasticsearch:
export ELASTICSEARCH_POD_ORDINAL=0 export ELASTICSEARCH_POD_NAME_ROOT=${ELASTICSEARCH_CLUSTER_NAME}-master export ELASTICSEARCH_POD=${ELASTICSEARCH_POD_NAME_ROOT}-0
Os nomes dos pods do Elasticsearch são definidos pelas dependências do Elasticsearch Helm. Os nomes do pod são compostos pelo nome do cluster, conforme fornecido no arquivo
values.yaml
que você criou, com a palavramaster
e um número ordinal indexado por zero, todos separados por hifens. Para esta etapa, escolha o primeiro pod, representado como zero (0).Use a API REST Aliases Elasticsearch para inspecionar os índices:
kubectl exec \ -c elasticsearch \ -it ${ELASTICSEARCH_POD} \ -- \ curl -XGET "127.0.0.1:9200/_aliases?pretty=true";
A resposta mostra dois índices,
janusgraph_vertices
ejanusgraph_edges
, que foram criados pelo JanusGraph para fornecer pesquisas eficientes usando propriedade de vértice e borda:{ "janusgraph_vertices" : { "aliases" : { "janusgraph" : { } } }, "janusgraph_edges" : { "aliases" : { "janusgraph" : { } } } }
Consulte os valores de um dos índices usando a API REST Search Elasticsearch:
kubectl exec \ -c elasticsearch \ -it ${ELASTICSEARCH_POD} \ -- \ curl -XGET "127.0.0.1:9200/janusgraph_edges/_search?pretty=true&q=*";
Os resultados da pesquisa mostram que há entradas nos índices criados pelo JanusGraph. A resposta que você vê é semelhante aos seguintes resultados truncados que indicam a presença dessas entradas no índice
janusgraph_edges
.{ "took" : 94, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 6, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "janusgraph_edges", "_type" : "_doc", "_id" : "6bvp-5ovc-b2t-2yko", "_score" : 1.0, "_source" : { "reason" : "loves waves" } }, { …
Excluir o projeto
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
A seguir
- Leia mais sobre o JanusGraph e os bancos de dados gráficos.
- Saiba mais sobre o framework de computação de grafos Apache TinkerPop e conheça a linguagem de percurso de grafos Gremlin.
- Saiba mais sobre como o JanusGraph armazena dados no Bigtable.
- Para ver mais detalhes sobre casos de uso de grafos, implante um exemplo de aplicativo do JanusGraph.