事件与TTL
正如介绍页面所述,SmartEDB 提供了通过生存时间(TTL)特性自动删除过时数据库对象的能力,并且能够管理数据库对象的新增、删除、更新和检查点事件。这些功能的 C# API 在以下各节中进行了说明。
Time-To-Live
生存时间(TTL)机制有助于根据 TTL 策略自动删除对象。支持两种 TTL 策略:最大计数和最大时间。前者设置对象计数阈值,而后者设置对象年龄阈值。这两种策略可以同时为单个类设置。 TTL 策略通过类注解进行设置,就像设置其他 SmartEDB 属性一样。(请注意,在 C# 中,对象年龄阈值始终以微秒为单位指定。)
[TTL(MaxCount=10, MaxTime=5000000)]
class A
{
// ...
}
请注意,MaxTime 策略依赖于当前系统时间。更改系统时钟将会影响此策略。在分布式数据库中,这可能会产生重要影响。
分布式环境中的副作用
在网络中的分布式数据库(使用 SmartEDB 集群)中,当启用 MaxTime 策略时,各节点之间的时钟同步至关重要。请注意以下几点:
TTL 时钟仅在事务发起方的提交阶段 1 开始时验证。远程节点不验证时钟时间,无论其实际时钟如何,都会应用事务。一旦远程节点成功应用事务,通知将返回给发起方并完成提交。即使各节点时钟不同步,数据库内容保持一致。
如果远程节点的时钟超前于发起节点,某些数据可能违反 TTL 要求而未被删除。例如,按远程节点的时钟,记录应已被删除,但仍然保留在该节点的数据库中。
即使某节点上的 TTL 尚未到期,对象也可能因其他节点的 TTL 过期而被移除。例如,节点 1 的时钟为下午 1 点,节点 2 的时钟为下午 2 点。事务在节点 1 发起并成功提交到两个节点,尽管记录在节点 2 上已过期。不久后,节点 2 发起另一事务并删除了该对象,删除操作传播至整个集群,导致记录存活时间比预期短。
事件接口
“事件”属性定义了触发应用程序通知的事件类型。应用程序如何处理这些事件由运行时的事件处理程序决定。对于 C# 应用程序,仅支持异步事件处理。每个事件类型会启动一个单独的线程,该线程调用 Connection 方法 WaitEvent() 等待事件。当事件发生时,线程被释放并继续与其他线程并行运行,直到完成处理并再次调用 WaitEvent()。
在事件处理程序完成任务并重新等待事件之前,存在一个小窗口期,可能会再次发生同一事件(事件不会排队)。通过将事件处理委托给另一个线程,可以让处理程序线程立即重新等待事件,从而最小化此窗口期。如果无法容忍未处理事件的风险,应用程序可以维护一个未处理事件表。异步事件在事务提交后激活。如果一个事务中添加、删除或更新了多个对象或字段,所有相关事件处理程序将同时被激活。
处理每个事件的各个线程将具有如下所示的线程过程:
private class ThreadParams
{
public Connection con;
public string event_name;
public ThreadParams(Connection con, string EventName)
{
this.con = con;
this.event_name = EventName;
}
}
private static void ThreadProc(object param)
{
ThreadParams tp = (ThreadParams)param;
try
{
while (!exit)
{
tp.con.WaitEvent(tp.event_name);
}
}
catch (DatabaseError x)
{
if (x.errorCode >= 50)
{
// Errors
}
else
{
// Normal return codes including MCO_S_EVENT_RELEASED
}
}
}
主应用程序线程将休眠若干毫秒,然后继续进行正常的数据库处理。在终止时,应用程序将调用 Connection 方法 ReleaseAllEvents(),然后停止事件处理程序线程。当事件被释放时,事件处理程序将捕获带有错误代码 MCO_S_EVENT_RELEASED 的异常。(有关进一步的实现细节,请参阅 SDK 示例 samples/csharp/events/basic。)
C# 应用程序还可以通过委托机制处理异步事件,方法是向 Connection 属性 AsynchEvent 和 AsyncEventError 添加处理程序,然后调用 StartEventListeners() 方法。(有关进一步的实现细节,请参阅 SDK 示例 samples/csharp/events/AsyncDelegate。)