缓存设计与更新

业务场景:

          我们需要有有一个留言板,可以进行发帖,用户登录以后可以对帖子进行回复。用户可以对帖子和留言进行点赞。由于我们有并发量,如果直接对数据库,有可能出现问题,所以我们需要对数据列表进行缓存处理。

处理方案:

         将数据存储到NoSql中,当进行数据读取的时候直接从NoSql中读取数据,我们可以选择的Nosql有Memcache和Redis,两者之间的区别和使用,我们可以从Googel上面查看一下,这里我们缓存列表使用的是Memcache,因为Memcache是多线程,非阻塞IO复用的网络模型,Redis是单线程的网络IO复用模型。两者区别可以参考这篇文章:http://blog.jobbole.com/101496/

memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe传递给worker线程,进行读写IO,网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如:memcached最常用的stats命令,实际memcached所有操作都要对这个全局变量加锁,进行技术等工作,带来了性能损耗。

redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll, kqueue和select,对于单存只有IO操作来说,单线程可以将速度优势发挥到最大,但是redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型施加会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞的。

因为我们需要考虑性能以及当多个用户访问的时候,不会被阻塞,所以我们选择Memcache作为缓存数据库。

缓存数据库我们选择完了,但是我们设计缓存的时候,需要考虑到如果数据频繁更新,这样的数据不适合放到缓存列表当中。如场景中的点赞数,这样的数据,会经常发生变化,当用户点赞的时候,然后缓存数据就会进行更新,这样的话缓存就没有意义了。

    所以我们需要把这些经常变化的数据放到缓存列表数据之外,当用户点赞以后,再次刷新页面的时候点赞数就会更新。我们是这样处理的,如我们使用memcache存储列表数据,取出列表数据以后,我们从Reids中获取每条数据的点赞数,当用户点赞的时候更新Redis中的数据,这样点赞数就独立于缓存之外进行更新处理了。

   还有一个问题,如果有很多条数据,我们如何做缓存,是对每一页作为单位进行缓存,还是全部放到一个key中,直接读取出来。其实这两种方式都是可以的,但是如果数据量特别大,我们放到一个key中读取的速度会特别慢,我们就要对每一页进行缓存,但是对每一页进行缓存的时候,我们会发现,现在一共是8页数据,每页数据是10条,但是我们删除10条数据,假设现在变成了7条,如果我们不把最后一页数据删掉,会导致数据不一致的状况,所以我们这里需要记录,上一次的页数,如果页数比上一次的页数少了,证明我们删除了数据,我们更新完数据以后,需要把多余缓存的页数删除掉。

    第一次去思考如何去使用缓存,有的是主动更新缓存,一个是被动更新缓存。这些都是要分析和考虑的,哪些数据适合做缓存,哪些数据不适合,这些也是需要我们去分析和思考的,上面是我遇到的一些问题。有兴趣的可以看看哈





猜你喜欢

转载自blog.csdn.net/zpf_nevergiveup/article/details/81023336