NCache,一个 内存分布式缓存,将您的数据完整地保存在临时存储中,以便更快地体验读写操作。 我们已经看到 NCache 在表演方面以速度创造奇迹 对缓存存储的操作. 然而,保持 NCache 在数据一致性方面,与主数据源同步是一项重大挑战。 数据源可以是任意数据库; 然而,这个博客是关于保持你的缓存与 PostgreSQL 同步的。
两个独立的数据副本——挑战
您的应用程序堆栈适用于 NCache 例如缓存作为缓存层驻留在数据库和应用程序之间。 您的应用程序直接连接到缓存,因此将所有操作调用直接发送到缓存,例如读取或写入。 让我们假设另一个用户在不让缓存知道的情况下更改了数据库中的某些内容。 现在数据库中的数据与缓存中的数据不同。 两个独立的数据副本导致数据不一致,这是一个很大的挑战。
NCache 更多信息 NCache 配套文档 与 PostgreSQL 同步缓存
NCache 保持数据同步
鉴于数据不一致的挑战, NCache 就像其他一切一样,猛扑过来修复它。 您需要做的是,将缓存与数据库同步使用 NCache 数据库同步 技巧。 如前所述,本博客中讨论的数据库是 PostgreSQL——一个开源对象关系数据库,具有完善的功能集和高性能和可靠性。 我们在 GitHub 上制作并上传了一个解决方案 将缓存与 PostgreSQL 同步 这显示了您的缓存如何提高可伸缩性和数据一致性。
下图显示了如何 NCache 帮助您保持数据与 PostgreSQL 数据库同步。
正在同步 NCache 使用 PostgreSQL 数据库
NCache 让您使用 PostgreSQL 保持数据同步 通知可扩展依赖,这是由提供的同步技术 NCache 保持缓存和数据库同步。 NotifyExtensibleDependency 用于使用 PostgreSQL 依赖通知系统实现数据失效技术。 PostgreSQL 依赖建立在 LISTEN/NOTIFY 机制上,类似于 发布/订阅模型。
除了数据库依赖, 读通提供者 用于直接与数据源通信。 NCache 调用提供程序以使用您的自定义逻辑直接从数据源加载数据。 这使数据保持同步和新鲜,以避免过时数据等问题,同时提供改进的可扩展性和更快的读取操作。
因此,涉及的基本组件是:
-
- NotifyExtensibleDependency: NCache 通过在 NotifyExtensibleDependency 中调用 LISTEN 向特定通道注册
Initialize
方法。 在数据库上,调用 TRIGGER 函数将有效负载发送到通道,并在侦听时,如果数据不一致,则从缓存中删除数据。 - ReadThruProvider:此提供程序在数据库中的数据修改时直接从数据库中自动获取更新的数据。
- NotifyExtensibleDependency: NCache 通过在 NotifyExtensibleDependency 中调用 LISTEN 向特定通道注册
使用 NotifyExtensibleDependency 同步缓存
通知可扩展依赖 用于使用 PostgreSQL 依赖机制使数据无效,该机制适用于 Pub/Sub 消息传递 该模型称为 Listen/Notify。 根据这种机制,数据库中的任何更新都会通过 NOTIFY 命令传递给在特定通道上侦听的客户端,并带有包含该信息的附加有效负载。 在我们的具体案例中,客户是 NCache 并且在收到有关数据库中任何更改的通知时,相应的项目将从缓存中删除。
让我们看看下面的代码,看看如何使用 PostgreSQL 依赖项添加项目:
1 2 3 4 5 6 7 8 9 10 11 |
const string connectionString = "your-connection-string"; var customer = new Customer(); var cacheItem = new CacheItem(customer) { Dependency = new PostGreSQLDependency(connectionString, customer.customerid, "public", "customers", "customer_channel") }; var key = customer.customerid; var cache = CacheManager.GetCache("democache"); cache.Insert(key, cacheItem); |
但是,您需要了解 PostgreSQLDependency
下面的代码会有所帮助。 这 Initialize
方法包含一个连接字符串以连接到数据库,并在特定数据中的任何数据修改时注册通知。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
public PostGreSQLDependency(string connectionString, string dependencyKey, string schema, string table, string channel) { _connectionString = connectionString.Trim(); _dependencyKey = dependencyKey.Trim(); _schema = schema.Trim(); _table = table.Trim(); _channel = channel.Trim(); } public override bool Initialize() { connection = new NpgsqlConnection(_connectionString); connection.Open(); ((NpgsqlConnection)connection).Notification += (o, e) => { var entity = JsonConvert.DeserializeObject(e.AdditionalInformation); if (entity.DependencyKey == _dependencyKey && entity.Table == _table && entity.Schema == _schema) { done = true; } }; using (var cmd = new NpgsqlCommand($"LISTEN {_channel};", (NpgsqlConnection)connection)) { cmd.ExecuteNonQuery(); } task = Task.Run(() => { while (true) { ((NpgsqlConnection)connection).Wait(); if (done) { break; } } this.DependencyChanged.Invoke(this); }); return true; } |
NCache 更多信息 NCache 配套文档 与 PostgreSQL 同步缓存
使用 Read-Through 自动重新加载数据
使用依赖关系,每当数据源中的数据被修改时,它就会从缓存中清除。 但是,我们仍然需要重新加载缓存中的数据,为此 NCache 有一个功能叫做 支持来源. 我们为 Read-Through 提供者提供了在实现中添加自定义逻辑的自由。 在指定的情况下,Read-Through 提供程序从 PostgreSQL 数据库加载数据。 你需要 配置 Read-Through 提供程序 使用之前的管理工具。
在通读提供程序中使用重新同步选项可使数据与数据库保持同步。 然而,内 ProviderCacheItem
, CacheItem 添加了依赖项,这意味着添加到缓存中的新项目已经添加了依赖项。 它为您节省了一遍又一遍地添加依赖项的工作。 看着那(这 LoadFromSource
Read-Through 提供程序中的方法来查看实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
public ProviderCacheItem LoadFromSource(string key) { var query = $"SELECT customerid, address, country, city FROM customers WHERE customerid = '{key}'"; // Define a query returning a single row result set NpgsqlCommand command = new NpgsqlCommand(query, _connection as NpgsqlConnection); var reader = command.ExecuteReader(); ProviderCacheItem providerCacheItem = null; while (reader.Read()) { if (providerCacheItem == null) { var customer = new Customer() { customerid = reader[0] as string, address = reader[1] as string, country = reader[2] as string, city = reader[3] as string, }; providerCacheItem = new ProviderCacheItem(customer) { Dependency = new PostGreSQLDependency(_connectionString, customer.customerid, "public", "customers", "customer_channel"), ResyncOptions = new ResyncOptions(true) }; } } } |
现在添加具有通读功能的项目,只需使用将修改后的项目直接加载到缓存中 数据库依赖. 因此,您的缓存与 PostgreSQL 数据库保持同步,所有过时的数据问题都消失了。
结论
简而言之,将博客中的所有内容都放在博客中,您的缓存和数据库需要保持彼此同步。 如果缓存不知道在数据库中进行的任何修改,您的应用程序可以继续工作并使用过时的缓存数据。 这个问题非常有效地解决了 NCache PostgreSQL 依赖特性。 还有很多其他很酷的功能,您只需转到 NCache 官网.