Pergunta

Estou experimentando o Google App Engine Java, no entanto, a ausência de uma restrição única é dificultar as coisas. Eu estive Através deste post e este blog sugere um método para implementar algo semelhante. Minha formação está em MySQL.Moving para DataStore sem uma restrição exclusiva me deixa nervoso porque nunca tive que me preocupar com valores duplicados antes e verificar cada valor antes de inserir um novo valor ainda tem espaço para erro.

"Não, você ainda não pode especificar exclusivo durante a criação de esquema."

-- David Underhill fala sobre GAE e a restrição única (link de postagem)

O que vocês estão usando para implementar algo semelhante a uma chave única ou primária?

Ouvi falar de uma camada abstrata de dados de dados criada usando a API de baixo nível que funcionou como um RDB comum, que, no entanto, não era gratuito (no entanto, não me lembro do nome do software)

Visão esquemática do meu problema

sNo = biggest serial_number in the db
sNo++
Insert new entry with sNo as serial_number value //checkpoint
User adds data pertaining to current serial_number 
Update entry with data where serial_number is sNo 

No entanto, na linha número 3 (ponto de verificação), sinto que dois usuários podem adicionar o mesmo SNO. E é isso que está me impedindo de trabalhar com o AppEngine.

Foi útil?

Solução

Você pode gerar números de série exclusivos para seus produtos sem precisar impor IDs exclusivos ou consultar todo o conjunto de entidades para descobrir qual é o maior número de série atualmente. Você pode usar transações e uma entidade singleton para gerar o número de série 'próximo'. Como a operação ocorre dentro de uma transação, você pode ter certeza de que dois produtos não receberão o mesmo número de série.

Essa abordagem, no entanto, será um potencial ponto de estrangulamento de desempenho e limitará a escalabilidade do seu aplicativo. Se for o caso de a criação de novos números de série não acontece com tanta frequência que você obtém contenção, pode funcionar para você.

EDIT: Para esclarecer, o singleton que detém o número de série atual - ou o próximo - a ser atribuído é completamente independente de quaisquer entidades que realmente tenham números de série atribuídos a eles. Eles não precisam fazer parte de um grupo de entidades. Você pode ter entidades de vários modelos usando o mesmo mecanismo para obter um novo número de série exclusivo.

Não me lembro de Java bem o suficiente para fornecer código de amostra, e meu exemplo do Python pode estar sem sentido para você, mas aqui está pseudo-código para ilustrar a ideia:

  1. Receba solicitação para criar um novo item de inventário.
  2. Insira transação.
  3. Recupere o valor atual da entidade única do modelo SerialNumber.
  4. Valor de incremento e escreva -o no banco de dados
  5. Valor de retorno conforme você sai da transação.

Agora, o código que faz todo o trabalho de criar o item de inventário e armazená -lo junto com seu novo número de série não precisa ser executado em uma transação.

Advertência: Como afirmei acima, esse pode ser um grande gargalo de desempenho, pois apenas um número de série pode ser criado a qualquer momento. No entanto, ele fornece a certeza de que o número de série que você acabou de gerar é único e não em uso.

Outras dicas

Essas e outras perguntas semelhantes surgem frequentemente ao falar sobre a transição de um RDB tradicional para um armazenamento de dados do tipo BigTable, como o App Engine.

Muitas vezes é útil discutir Por quê O DataStore não suporta teclas exclusivas, pois informa a mentalidade em que você deve estar ao pensar nos esquemas de armazenamento de dados. A razão pela qual as restrições únicas não estão disponíveis é porque limita muito a escalabilidade. Como você disse, aplicar a restrição significa verificar todas as outras entidades para essa propriedade. Se você faz isso manualmente no seu código ou no armazenamento de dados, o faz automaticamente nos bastidores, ele ainda precisa acontecer, e isso significa desempenho mais baixo. Algumas otimizações podem ser feitas, mas ainda precisa acontecer de uma maneira ou de outra.

A resposta para sua pergunta é realmente pensar em por que você precisa dessa restrição única.

Em segundo lugar, lembre -se de que as chaves Faz existe no armazenamento de dados e são uma ótima maneira de aplicar uma restrição exclusiva simples.

my_user = MyUser(key_name=users.get_current_user().email())
my_user.put()

Isso garantirá que não MyUser jamais será criado com esse e -mail novamente, e você também poderá recuperar rapidamente o MyUser Com esse e -mail:

my_user = MyUser.get(users.get_current_user().email())

No tempo de execução do Python, você também pode fazer:

my_user = MyUser.get_or_create(key_name=users.get_current_user().email())

Que inserirá ou recuperará o usuário com esse email.

Qualquer coisa mais complexa do que isso não será escalável. Portanto, pense realmente se você precisa que essa propriedade seja globalmente única ou se existem maneiras de remover a necessidade dessa restrição única. Muitas vezes, você encontrará com algumas pequenas soluções alternativas que não precisava dessa propriedade para ser única, afinal.

Encontrei o mesmo problema em um aplicativo em que os usuários precisavam reservar um intervalo de tempo. Eu precisava "inserir" exatamente uma entidade de intervalo de tempo exclusiva, enquanto esperava que os usuários solicitem simultaneamente o mesmo intervalo de tempo.

Eu isolei um exemplo de como fazer isso no mecanismo de aplicativos, e eu blogou sobre isso. A postagem do blog possui exemplos de código canônicos usando o datastore e também objetivam. (BTW, eu aconselho a evitar o JDO.)

Eu também implantei um demonstração ao vivo onde você pode promover dois usuários para reservar o mesmo recurso. Nesta demonstração, você pode experimentar o comportamento exato do DataStore do mecanismo de aplicativos Clique por clique.

Se você está procurando o comportamento de uma restrição única, isso deve ser útil.

-broc

Primeiro, pensei que uma alternativa à técnica de transação no blog de Broc poderia ser fazer uma classe singleton que contém um método sincronizado (digamos o nome da addusern (nome da string)), adicionando uma nova entrada apenas se for única ou lançando uma exceção. Em seguida, faça um listener de contexto que instancie uma única instância desse singleton, adicionando -o como um atributo ao ServletContext. Os servlets podem chamar o método addUserName () na instância de singleton que eles obtêm através do getServletContext.

No entanto, isso não é uma boa idéia, porque é provável que o GAE divida o aplicativo em várias JVMs para que várias instâncias da classe singleton ainda possam ocorrer, uma em cada JVM. Veja este tópico

Uma alternativa mais GAE seria escrever um módulo GAE responsável pela verificação da singularidade e adicionar novas entradas; Em seguida, use escala manual ou básica com ...

<max-instances>1</max-instances>

Em seguida, você tem uma única instância em execução no GAE que atua como um único ponto de autoridade, adicionando usuários um de cada vez ao armazenamento de dados. Se você estiver preocupado com a instância de ser um gargalo, poderá melhorar o módulo, adicionando filas ou arquitetura de mestre/escravo interna.

Essa solução baseada em módulo permitiria que muitos nomes de usuário exclusivos fossem adicionados ao armazenamento de dados em um curto espaço de tempo, sem arriscar problemas de contenção de grupos de entidade.

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