有很多事情需要考虑,但总的来说,我会在您的情况下将关系映射基于行数据网关模式 (RDG)。如果您没有太多不同的对象类型,那么这种架构方法应该可以很好地扩展。如果您将缓存簿记约束到 Finder 类,RDG 应该有助于您的缓存实现。
如果您有时间并且愿意,请查看Martin Fowler 的企业应用程序架构模式。这是一个很好的信息。
现在到具体...
通常,您会为此在数据库中使用一些自动递增的整数列。您可以使用 unordered_map 快速从缓存中提取这些对象。由于您的缓存中有所有对象,为了优化,您还可以实现一些find*
函数来首先搜索缓存。您可以使用 unordered_map/unordered_multimap 来“索引”一些数据,如果您的搜索时间受到高度限制,或者只是坚持使用良好的旧地图/多地图。但是,这会使工作加倍,并且您已经在数据库中免费获得了这些类型的查询。
在您实际将脏数据写入数据库之前,系统的其余部分不应该看到脏数据。启动更新后,如果一切按预期进行,您可以将缓存中的对象替换为您用于更新的对象,或者简单地删除缓存中的对象并让其他读者从数据库中获取它(这将导致再次缓存对象)。您可以通过克隆原始网关对象来实现这一点,但底线是您应该实现一些锁定策略。
在这里,您只需从缓存中删除对象,然后尝试从数据库中删除。如果在数据库中删除失败,其他读者将缓存它。只要确保您在删除过程中没有客户端可以访问相同的记录。添加新记录时,您只需实例化网关对象,将其传递给域级别对象,完成更改后,在网关对象上调用 insert。您可以将新的 Gateway 对象放入缓存中,也可以让第一个读者将其放入缓存中。
- 按某种优先级排序数据(最后使用)
- 根据提供的信息缓存数据/对象的最佳方法是什么?为什么?
这是选择最佳缓存算法的问题。这不是一个容易回答的问题,但 LRU 应该可以正常工作。没有实际的指标,就没有正确的答案,但是 LRU 很容易实现,如果它不符合您的要求,只需执行指标并决定新算法。确保您可以通过良好的缓存接口无缝地做到这一点。要记住的另一件事是您的域级别对象永远不应该依赖于缓存的限制。如果您需要 100k 个对象,但只有 50k 个缓存,那么您仍然在内存中拥有所有 100k 个对象,但其中有 50k 个对象在缓存中。换句话说,你的对象不应该依赖于你的缓存状态,也不应该关心你是否有缓存。
接下来,如果您仍然坚持使用 RDG 的想法,那么您只是在缓存中缓存网关对象。您可以通过 shared_ptr 将网关对象的实例保存在缓存中,但如果您想避免脏写,还应该考虑锁定策略(乐观与悲观)。此外,您的所有网关(每个表一个)都可以继承相同的接口,因此您可以概括您的保存/加载策略,并且您可以在保持简单的同时使用单个池。(查看 boost::pool。也许它可以帮助您实现缓存。)
最后一点:
蛋糕是一个谎言!:D 无论您决定做什么,请确保它基于大量的性能指标。如果您将性能提高了 20%,并且您花了 2 个月的时间来做这件事,那么考虑在您的硬件上增加几 GB 的 RAM 可能是值得的。做一些简单的可验证的概念证明,这将为您提供足够的信息,是否实现您的缓存支付,如果没有,请尝试一些经过测试且可靠的现成解决方案(memcached 等,正如@Layne 已经评论的那样)。