Há muitas coisas a considerar, mas em geral eu basearia o mapeamento relacional no seu caso no Row Data Gateway padrão (RDG). Se você não tiver muitos tipos de objetos diferentes, essa abordagem de arquitetura deve ser dimensionada o suficiente. O RDG deve facilitar sua implementação de cache se você restringir a manutenção de cache à classe Finder.
Se você tiver tempo e vontade, confira os Patterns of Enterprise Application Architecture de Martin Fowler . É um poço de boas informações.
Agora vamos aos detalhes...
- identifique os dados por algum tipo de ID
Normalmente, você usaria alguma coluna de número inteiro incrementada automaticamente no banco de dados para isso. Você pode usar unordered_map para puxar esses objetos do cache rapidamente. Como você tem todos os objetos em seu cache, para fins de otimização, você também pode implementar alguns dos métodos
find*
funções para pesquisar o cache primeiro. Você pode usar unordered_map/unordered_multimap para 'indexar' alguns dos dados, se seu tempo de pesquisa for altamente restrito, ou apenas manter o bom e velho mapa/multimap. No entanto, isso está dobrando o trabalho, e você já tem gratuitamente no banco de dados esses tipos de consultas. - editar os dados/objetos armazenados em cache
Dados sujos não devem ser visíveis para o resto do sistema até que você os grave no banco de dados. Depois de iniciar a atualização, e se tudo correr como pretendido, você pode substituir o objeto no cache pelo que você usou para atualização ou simplesmente excluir o objeto no cache e deixar que outros leitores o peguem no banco de dados (o que resultará no cache do objeto novamente). Você pode implementar isso clonando o objeto Gateway original, mas o resultado final é que você deve ter alguma estratégia de bloqueio implementada.
- excluir dados/objetos antigos e adicionar novos dados/objetos
Aqui você simplesmente exclui o objeto do cache e tenta excluir do banco de dados. Se a exclusão falhar no banco de dados, outros leitores o armazenarão em cache. Apenas certifique-se de que nenhum cliente possa acessar o mesmo registro enquanto você estiver no processo de exclusão. Ao adicionar novos registros, você simplesmente instancia o objeto Gateway, passa-o para o objeto de nível de domínio e, quando terminar as alterações, chama insert no objeto Gateway. Você pode colocar o novo objeto Gateway no cache ou simplesmente deixar o primeiro leitor colocá-lo no cache.
- ordenar os dados por algum tipo de prioridade (último usado)
- Qual seria a melhor maneira de armazenar em cache os dados/objetos com base nas informações fornecidas E POR QUÊ?
É uma questão de selecionar o melhor algoritmo de cache. Esta não é uma pergunta fácil de responder, mas o LRU deve funcionar bem. Sem métricas reais, não há resposta certa, mas o LRU é simples de implementar e, se não atender às suas necessidades, basta fazer as métricas e decidir sobre um novo algoritmo. Certifique-se de que você pode fazer isso sem problemas, tendo uma boa interface para o cache. Outra coisa a ter em mente é que seus objetos de nível de domínio nunca devem depender dos limites do seu cache. Se você precisar de 100 mil objetos, mas tiver apenas 50 mil de cache , ainda terá todos os 100 mil objetos na memória, mas 50 mil deles estão no cache. Em outras palavras, seus objetos não devem depender do estado do seu cache e também não devem se importar se você tem cache.
Em seguida, se você ainda está com a ideia de RDG, você está simplesmente armazenando em cache o objeto Gateway em seu cache. Você pode manter instâncias dos objetos Gateway em seu cache por meio de shared_ptr, mas também deve considerar sua estratégia de bloqueio (otimista vs pessimista), se quiser evitar gravações sujas. Além disso, todos os seus Gateways (um para cada mesa) podem herdar a mesma interface, para que você possa generalizar suas estratégias de salvamento/carregamento e, além disso, você poderá usar um único pool, mantendo as coisas simples. (Confira boost::pool. Talvez possa ajudá-lo com a implementação do cache.)
Um último ponto:
O bolo é uma mentira! :D Não importa o que você decida fazer, certifique-se de que seja baseado em uma quantidade razoável de métricas de desempenho. Se você melhorar o desempenho em 20% e passou 2 meses fazendo isso, talvez valha a pena pensar em colocar mais alguns gigas de RAM no seu hardware. Faça uma prova de conceito fácil e verificável, que fornecerá informações suficientes se a implementação do seu cache vale a pena e, se não, tente algumas das soluções testadas e confiáveis da prateleira (memcached ou algo assim, como @Layne já comentou).