Skip to content
ScutGame edited this page Apr 21, 2015 · 4 revisions

此章节介绍服务端缓存的持久化存储机制

持久化存储概述

持久化存储是将服务器中的缓存Cache转存储到电脑磁盘的过程,服务器关掉重启数据不会丢失掉,它会重新从电脑磁盘中读取数据恢复到服务器缓存Cache中。

Scut缓存持久化

Scut的存储分为:服务器的缓存,Redis缓存数据库,DB数据库(SQL/MySql);

先说说Scut的数据加载步骤

  1. 根据定义实体的EntityTable信息,判断StorageType属性是从Redis数据库还是从DB数据库加载数据;

  2. 如果是Redis,则使用实体名和实体主键(EntityField(True))做为Redis的Key,取出数据;

  3. 如果是DB数据库,则从表名为实体名,查询字段为实体主键的数据;

  4. 如果实体的是ShareEntity的子类,它是加载全部的数据,不再使用实体主键筛选数据;

数据加载到服务器缓存Cache后,需要取出来使用或修改其中的数据,那修改完后,它怎么存储到DB数据库或Redis数据库呢?

接下来看看Scut的数据更新步骤

  1. 从缓存中取出的实体对象,当修改它的属性时会触发Changed事件,会告诉Scut有数据改变了需要持久化数据到DB数据库或Redis数据库中;

  2. 当收到Changed件事通知时,会将此实体对象先放入内存队列(是服务器的内存)中,会有一个子线程负责每间隔100ms处理内存队列,将数据写入到Redis的消息队列中,这时还并没有更新到DB数据库或Redis数据库(为了因Changed事件触发频繁造成拥堵,这里使用内存队列作层缓冲而不是直接写入Redis消息队列);

  3. 接着会有多个线程间隔100ms处理Redis消息队列(每个线程只负责相应的子队列,默认启用2个,可以配置增加),它将实体数据存储到Redis数据库中,如果有开启Db数据库存储会提交给另一个Redis的Sql消息队列;

  4. Sql消息队列负责将Sql语句更新DB数据库,由于DB数据库它写入性能不高,这里采用的延迟时间默认为5分钟来缓冲实体数据的写入量(实体主键相同只会写入一次),默认启用2个线程来处理Sql消息队列;

  5. 到这时实体数据才持久化成功,如果在此之前业务层有调用Cache的ReLoad或LoadFrom方法,它加载的数据是旧的数据会造成修改的实体数据丢失,因此只有在服务器启动初始化时使用LoadFrom和Reload方法,其它地方谨慎使用;

以上步骤数据更新由DataSyncQueueManager类负责处理。

另外提示

  • Redis数据库中带'__'开头的是Key是Redis消息队列,带'$'开头的是实体存储数据;
  • '__'开头并且有Error结束的Key,表示处理异常的队列,这个队列需要手机处理,判断是否可以直接删除掉;
  • 消息队列产生的异常会记录在Log目录的Exception子目录下,监控消息则在Warn目录;
Clone this wiki locally