Home > programming > 程序运行时的数据存储

程序运行时的数据存储

  想了半天也不知道到底如何命名这个标题,暂且就这样将就吧。

程序在运行的过程中肯定会涉及到保留很多运行时数据在内存里面,服务器程序就更是这样了。在我们的服务器程序里面,有很多事需要同时服务大量的客户端,每一个客户端都会相应的数据被记录在程序的进程中,有的时候过多的程序数据对系统来说是一个压力,例如300K的session数据,每一个session数据平均有大概10K,这样的话将会有3G的内存需要,如果某一个session上有特别多的操作,那么根据协议要求将会保存更多的信息,可能多达50K到100K。这样的话对于服务来说是一个不小的负担。而且,如果程序非正常死亡了(crash掉了),那么当服务程序起来以后,以前的session数据就都不见了,这个是一个正常运行中非常严重的问题。

这么多的数据同时保存在内存中对系统要求是一个问题,而且重启以后数据会丢失,并且,在程序运行的过程中的一个短的时间内,并不是所有的session都会被访问到,例如300K sessions,可能每秒也就是1000个session上面有操作。这样的话自然想到把数据放到缓存中去,当某个session的数据需要被访问的时候再冲缓存中读出、实例化。我们的程序采用了Ice的freeze来作为缓存,freeze采用BerkeleyDB作为存储层,然后freeze自己控制数据的序列化/反序列化、刷新、储存以及实例化,同时可以设置保存在内存中的session的个数。

  采用了freeze以后,基本上解决了内存占用的问题,因为内存中只保存最近使用的一部分session的数据(例如,只保存1000个session的instance)。其他的暂时不使用的session数据就保存在Freeze(实际上是BerkeleyDB)里面。当一个是新的请求到了,并且发现需要的session不在内存中,freeze将会从DB中把数据读出并且重新实例化成为内存数据结构。然后交给程序继续处理。这样对于程序来说看起来就像所有的数据都在内存中,但是实际的内存消耗又比较小。这样看来,好处是大大地了。而实际应用下来发现确实好处多多。即便程序重新启动,保存在数据库中的session数据还是可以直接回复为内存session数据结构。这样的话在现场部署的程序升级的时候将不需要选择一个基本上没有用户操作的时间点了(当然为了将session数据丢失的概率减小,基本上还是选择一个用户操作较少的时间点)。

但是最近发生的事情却让人有点郁闷。由于每一个session的建立在时延方面是有规定的,例如(500ms)。在大多数时候这个都不是一个问题。这里我先讲一下Freeze的大体操作流程:

Freeze基本上设计三个操作,添加一个session到Freeze,从Freeze中删除一个session, 内存中session的数据更改。

1.当要向Freeze中添加一个session,或者从Freeze中删除一个session时候的操作基本差不多,首先是lock住整个Freeze(在我们的应用中实际上是Evictor,这里就说成是Freeze了 ^_^)。然后如果是添加的话就先检查这个session是否存在,如果不存在的话就把这个session添加到一个队列中去,并且标志为modified,也就是说表明这个session的数据需要保存到DB中去。如果是删除的话就直接标志这个session为destroyed,意即这个session的数据需要从DB中删除。

2.当内存中的session被修改以后,在freeze中这个session会被标志位modified。以便将来保存数据到DB中去。 而且Freeze有一个后台线程,每隔一段时间(或者被唤醒),就会把当前被置为modified的session的数据保存到DB中去,或者从DB中删除那些被标识为destroyed的session的数据。但是在这个保存的过程中Freeze(evictor)会被lock住。

好了,上面大致讲述了Freeze工作方式,在大部分时候这种方式是可以应付需求的。但是当在某一个时间段上,突然有相当多的client发出session的操作,当Freeze决定flush数据到DB的时候就会发现有很多的数据需要被存储。于是Freeze锁住自己,然后开始对每一个session的数据进行序列化,并且把新的数据保存在DB中。而且相当不幸的是这个过程尽然耗费令人发指的10秒钟,于是在这宝贵的10s中那些新的session建立的请求由于session不能及时被加入到Freeze中而超时(通常500ms就会超时),于是乎遭到一大堆的抱怨。

初看起来,解决方法也很直接:

  1. 增加Freeze flush的频率,也就是每一次写入的DB的session的数量尽量的少
  2. 尽量减少锁住Freeze的范围,让session add remove的等待的时间尽量缩短
  3. 不知道是否有无锁的方案
  4. 不知道了

也许还有其他的解决办法,还需要仔细想想

Categories: programming Tags: ,
  1. No comments yet.
  1. No trackbacks yet.