Er zijn veel dingen om te overwegen, maar in het algemeen zou ik relationele mapping in uw geval baseren op de Row Data Gateway patroon (RDG). Als je niet te veel verschillende objecttypen hebt, zou deze benadering van architectuur goed genoeg moeten schalen. RDG zou uw caching-implementatie moeten vergemakkelijken als u cacheboekhouding beperkt tot de Finder-klasse.
Als je tijd en zin hebt, bekijk dan de Patterns of Enterprise Application Architecture van Martin Fowler . Het is een bron van goede informatie.
Nu naar de details...
- identificeer de gegevens met een soort id
Normaal gesproken zou u hiervoor een auto-incremented integer-kolom in de database gebruiken. U kunt unordered_map gebruiken om die objecten snel uit de cache te halen. Aangezien je alle objecten in je cache hebt, zou je omwille van de optimalisatie ook enkele van de find*
kunnen implementeren. functies om eerst de cache te doorzoeken. U kunt unordered_map/unordered_multimap gebruiken om een deel van de gegevens te 'indexeren', als uw zoektijd zeer beperkt is, of u kunt gewoon vasthouden aan de goede oude kaart/multimap. Dit is echter een verdubbeling van het werk, en je hebt het al gratis in de database voor dit soort zoekopdrachten.
- bewerk de gegevens/objecten in de cache
Vuile gegevens zouden niet zichtbaar moeten zijn voor de rest van het systeem totdat u ze daadwerkelijk naar de database schrijft. Zodra je de update hebt geschopt, en als alles gaat zoals bedoeld, kun je ofwel het object in de cache vervangen door degene die je voor de update hebt gebruikt, of gewoon het object in de cache verwijderen en andere lezers het uit de database laten ophalen (wat resulteert in in het opnieuw cachen van het object). U kunt dit implementeren door het originele Gateway-object te klonen, maar het komt erop neer dat u een bepaalde sluitstrategie moet implementeren.
- verwijder oude gegevens/objecten en voeg nieuwe gegevens/objecten toe
Hier verwijdert u eenvoudig het object uit de cache en probeert u het uit de database te verwijderen. Als het verwijderen in de database mislukt, zullen andere lezers het in de cache opslaan. Zorg ervoor dat geen enkele klant toegang heeft tot hetzelfde record terwijl u bezig bent met het verwijderen. Wanneer u nieuwe records toevoegt, start u eenvoudig het Gateway-object, geeft u het door aan het object op domeinniveau en wanneer u klaar bent met de wijzigingen, roept u insert op het Gateway-object aan. U kunt het nieuwe Gateway-object in de cache plaatsen of de eerste lezer het in de cache laten plaatsen.
- sorteer de gegevens op een bepaalde prioriteit (laatst gebruikt)
- Wat is de beste manier om de gegevens/objecten te cachen op basis van de verstrekte informatie EN WAAROM?
Dit is een kwestie van het beste caching-algoritme selecteren. Dit is geen gemakkelijke vraag om te beantwoorden, maar LRU zou prima moeten werken. Zonder daadwerkelijke statistieken is er geen juist antwoord, maar LRU is eenvoudig te implementeren en als het niet aan uw vereisten voldoet, voert u gewoon de statistieken uit en kiest u een nieuw algoritme. Zorg ervoor dat u dat naadloos kunt doen door een goede interface naar de cache te hebben. Een ander ding om in gedachten te houden is dat uw objecten op domeinniveau nooit afhankelijk mogen zijn van de limieten van uw cache. Als je 100k objecten nodig hebt, maar je hebt maar 50k cache, dan heb je nog steeds alle 100k objecten in het geheugen, maar 50k van hen zijn in de cache. Met andere woorden, je objecten zouden niet afhankelijk moeten zijn van de status van je cache, en het zou ook niet moeten uitmaken of je caching hebt.
Vervolgens, als je nog steeds het idee van RDG koestert, cache je eenvoudig het Gateway-object in je cache. U kunt instanties van de Gateway-objecten in uw cache bewaren door middel van shared_ptr, maar u moet ook rekening houden met uw vergrendelingsstrategie (optimistisch versus pessimistisch), als u vuile schrijfacties wilt vermijden. Ook kunnen al uw gateways (één voor elke tafel) dezelfde interface erven, zodat u uw opslag- en laadstrategieën kunt generaliseren, en u kunt ook een enkele pool gebruiken terwijl u de zaken eenvoudig houdt. (Bekijk boost::pool. Misschien kan het je helpen met de cache-implementatie.)
Een laatste punt:
De taart is een leugen! :D Wat je ook besluit te doen, zorg ervoor dat het gebaseerd is op een behoorlijk aantal prestatiestatistieken. Als je de prestaties met 20% verbetert, en je hebt er 2 maanden aan besteed, is het misschien de moeite waard om na te denken over het toevoegen van een paar extra RAM-geheugen aan je hardware. Maak een eenvoudig verifieerbaar proof-of-concept, dat je voldoende informatie geeft of het implementeren van je cache loont, en zo niet, probeer dan een aantal van de geteste en betrouwbare oplossingen van de plank (memcached of iets dergelijks, zoals @Layne al opmerkte).