你的位置:首页 > ASP.net教程

[ASP.net教程]EventStore的新的核心设计思路简要总结


  1. 在内存中维护每个聚合根的版本索引eventVersion,eventVersion中维护了当前聚合根的所有的版本、每个版本对应的cmdId,以及每个版本的事件在event文件中的物理位置;当一个事件过来时,通过这个eventVersion来判断version,cmdId是否合法(version必须是currentVersion+1,cmdId必须唯一);
  2. 当写入一个事件时,只写入一个文件,event.file文件;假设一个文件的大小为512MB,一个事件的大小为1KB,则一个文件大概存储52W个事件;
  3. 一个event.file文件写满后:
    • 完成当前event.file文件,然后新建一个新的event.file文件,接下来的事件写入新的event.file文件;
    • 用一个异步线程,在内存中对当前完成的event.file文件中的event按照聚合根ID和事件版本号进行排序;
    • 排序完成后,我们就知道了该文件中的事件涉及到哪些聚合根,他们的顺序,以及最大最小聚合根ID分别是什么;
    • 新建一个和event.file文件一样大小的临时文件;
    • 将最大最小聚合根ID写入到临时文件的header中,并写入一个是否已经排序过的标记字段到header中;
    • 将事件按排序后的顺序写入临时文件文件的数据区域;
    • 都写入完成后,将临时文件替换当前已完成的event文件;
    • 新建一个事件索引eventIndex.file文件,将当前event文件中的聚合根的事件索引信息写入索引文件,事件索引信息是指每个聚合根的事件在event文件中的开始和结束位置;eventIndex.file文件的作用是加快查找某个聚合根的事件信息;如果内存足够,eventstore可以自动将这些eventIndex.file文件缓存到内存中;
    • 每个event.file文件的最小和最大聚合根的ID也在内存中缓存:aggregateIdRangeCache;以方便快速定位某个聚合根在哪些event.file文件中存在事件;
  4. 因为内存大小有限,所以eventVersion不可能全部缓存在内存;所以,当某个聚合根的eventVersion不在内存中时,需要从磁盘加载。加载的思路是:扫描aggregateIdRangeCache,快速找出该聚合根的事件在哪些event.file文件中存在;然后通过查找这些event.file文件对应的eventIndex.file文件,就能快速查找到每个event.file文件中的事件信息了;
  5. eventstore启动时,最好需要预加载一些热门聚合根的eventVersion信息到缓存。那该预加载哪些聚合根呢?我们可以在内存中维护一个固定大小(N)的环形数组,环形数组中维护了最近修改的聚合根的ID;当某个聚合根有事件产生,则将该聚合根ID的hashcode取摸N得到环形数组的下标,然后将该聚合根ID放入该下标;定时将该环形数组中的聚合根ID dump到文件preloadAggregateId.file进行存储;这样当eventstore启动时,就可以从preloadAggregateId.file加载指定聚合根的eventVersion;