当你想到要用缓存时,肯定是系统性能遇到瓶颈了,比如
- rt太高了,想要快一点
- 并发量太高了,数据库连接不够用
也有可能是想用缓存比较好的特质,比如
- 自动失效,应用一些临时数据
- 修改方便,不用数据订正,当开关
在这里我想分析下针对系统性能方面如何使用缓存。
首先考虑的第一个要素,缓存空间够不够,我放到缓存中的数据有多大。
还有单key的数据量会有多大,比如redis 单key最好控制在128MB之内。
然后是实时性,如果是准实时,比如缓存的是离线数据,那只要设置一个失效时间就可以了。如果是需要实时,那在数据库更新后,就需要更新缓存。
那怎么保证数据库和缓存的一致性就是另一个需要考量的问题。监听数据库的binlog日志消息,然后去更新缓存是一个比较不错的想法,但是缓存更新失败怎么办呢?可以搞一个队列,失败了放到队尾不断重试或者搞个定时任务,比较数据库和缓存的数据,可行,但并不优雅。
mysql 有一个 InnoDB memcached Plugin,支持 memcached协议读写数据,这样数据就不需要放在传统的sql表里面了,一致 大专栏 缓存性问题也没有了。或者以后mysql会支持普通sql和插件的事务?或者又出现了一个新的数据库?
这个问题跟分布式事务的问题很像,既然是分布式问题,那如果能利用paxos这样的分布式一致性算法实现的库,那也不失为一种优雅的方式。
好了,现在我们回到查询缓存数据本身的问题。
命中率,首先想到这个,如果命中率为0,那缓存就失去了意义。或者某一段时间突然并发量增大,而且都没有命中缓存,那就会拖垮数据库。
最根本的解决方案是什么?那就是所有数据都上缓存啦,评估一下数据量以及之前说的缓存空间,如果成本允许的话,确实是个好方案。
那如果要节约成本呢?可以统计热点数据,把热点数据上缓存。
以下一些问题需要再设计方案是考虑:
- null值击穿;对不存在的key预先设计值
- 缓存失效,不同的key同一时间失效;失效时间随机
- 缓存失效,同一个key失效,多个线程并发访问;要做并发控制
多级缓存,使用缓存时,推荐使用多级缓存。多级缓存分为本地缓存,堆外缓存,分布式缓存。因为本地缓存会引发gc,所以一般使用堆外缓存来减轻分布式缓存的压力。