Pergunta

Preciso inserir uma enorme quantidade de nós com os relacionamentos entre eles no Neo4J através do ponto final do lote da API REST, aproximadamente 5k registros/s (ainda aumentando).

Esta será a inserção contínua 24x7. Cada registro pode exigir a criação de um nó apenas, mas outro pode exigir dois nós e um relacionamento que está sendo criado.

Posso melhorar o desempenho das inserções alterando meu procedimento ou modificando as configurações do Neo4J?

Meu progresso até agora:

1. Eu tenho testado com Neo4J há um tempo, mas não consegui o desempenho que precisava

Caixa de servidor de teste: 24 núcleos + 32 GB de RAM

NEO4J 2.0.0-M06 instalado como um serviço independente.

Executando meu aplicativo Java no mesmo servidor. (O aplicativo Neo4J e Java precisarão executar em seu próprio servidor no futuro, para que o modo incorporado não possa ser usado)

REST API ENDpoint: /db /data /lote (Target: /cypher)

Usando o índice de esquema, restringe, mescla, crie exclusivo.

2. Meu esquema:

neo4j-sh (0)$ schema
==> Indexes
==>   ON :REPLY(created_at)   ONLINE                             
==>   ON :REPLY(ids)          ONLINE (for uniqueness constraint) 
==>   ON :REPOST(created_at) ONLINE                             
==>   ON :REPOST(ids)        ONLINE (for uniqueness constraint) 
==>   ON :Post(userId)      ONLINE                             
==>   ON :Post(postId)    ONLINE (for uniqueness constraint) 
==> 
==> Constraints
==>   ON (post:Post) ASSERT post.postId IS UNIQUE
==>   ON (repost:REPOST) ASSERT repost.ids IS UNIQUE
==>   ON (reply:REPLY) ASSERT reply.ids IS UNIQUE

3. minhas consultas de cifra e solicitações JSON

3.1. Quando um registro requer criação de um único nó, a descrição do trabalho se parece abaixo

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (child:Post {postId:1001, userId:901})"}}

3.2. Quando um registro requer dois nós com um relacionamento a ser criado, a descrição do trabalho parece abaixo

{"method" : "POST","to" : "/cypher","body" : {"query" : "MERGE (parent:Post {postId:1002, userId:902}) MERGE (child:Post {postId:1003, userId:903}) CREATE UNIQUE parent-[relationship:REPOST {ids:'1002_1003', created_at:'Wed Nov 06 14:06:56 AST 2013' }]->child"}}

3.3. Normalmente, envio 100 descrições de trabalho (misto 3.1 e 3,2) por lote, que leva cerca de 150 ~ 250ms para fazê -lo.

4. Problemas de desempenho

4.1. Simultaneidade:

/db/dados/lote (Target:/cypher) parece não segura, testado com dois ou mais threads simultâneos que reduziram o servidor NEO4J em segundo (s) ~ minuto (s).

4.2. Mesclar com restrições nem sempre funciona.

Ao criar dois nós e um relacionamento com uma única consulta (mencionada acima em 3.2.), algum dia funciona como um encanto; Mas, em algum momento, falha com uma cypherexecutionException e dizendo um dos nó xxxx já existe com o rótulo AAAA e a propriedade "bbbbb" = [ccccc]; Pelo meu entendimento, a mesclagem não é supor que retorne nenhuma exceção, mas retorne o nó se já existir.

Como resultado da exceção, todo o lote falhará e rolará, o que afeta minha taxa de inserção.

Eu abri um problema no github para esta edição, https://github.com/neo4j/neo4j/issues/1428

4.3. Criar único com restrições nem sempre funciona para a criação de relacionamento.

Isso também é mencionado na mesma questão do Github.

4.4. Atuação:

Na verdade, antes de usar o lote com o Cypher, tentei a indexação herdada com get_or_create (/db/data/index/node/post?

Devido à natureza desses pontos de extremidade do índice herdado (eles retornam a localização dos dados no índice em vez de localização dos dados no armazenamento de dados real), para que eu não pudesse usá -los no lote (precisava do recurso de referência do nó criado anteriormente no mesmo lote )

Sei que poderia ativar o Auto_indexing e lidar com o armazenamento de dados diretamente em vez do índice herdado, mas eles mencionaram a partir do 2.0.0, o índice de esquema é recomendado sobre o índice de legado, por isso decido mudar para a abordagem de índice de lotes + cypher + esquema.

No entanto, com o lote + Cypher, só posso obter cerca de 200 descrições de emprego por taxa de inserção, teria sido muito maior se a fusão com restrições sempre funcionasse, digamos cerca de 600 ~ 800/s, mas ainda for muito menor que 5k /s. Eu também tentei o índice de esquema sem restrições, ele acabou ainda mais baixo em termos de taxa de inserção.

Foi útil?

Solução

Com 2.0, eu usaria o terminal transacional para criar suas instruções em lotes, por exemplo, 100 ou 1000 por solicitação HTTP e cerca de 30k-50k por transação (até você se comprometer).

Veja isso para o formato do novo terminal transacional:

http://docs.neo4j.org/chunked/milestone/rest-api-transaction.html

Também para um endpoint de inserção contínuo e de alto desempenho, recomendo escrever uma extensão de servidor que seja executada contra a API incorporada e posso inserir facilmente 10k ou mais nós e relacionamentos por segundo, veja aqui a documentação:

http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html

Para inserções puras, você não precisa de Cypher. E para a simultaneidade, basta pegar uma fechadura em um nó bem conhecido (por subgraf tx.acquireWriteLock() ou removendo uma propriedade inexistente de um nó (REMOVE n.__lock__).

Para outro exemplo de escrever uma extensão não gerenciada (mas que usa o Cypher), confira este projeto. Ele ainda possui um modo que pode ajudá -lo (publicando arquivos CSV no terminal do servidor a ser executado usando uma instrução Cypher por linha).

https://github.com/jexp/cypher-rs

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top