高并发系统设计(九):数据库和NoSQL如何做到互补?及其缓存加速的两面性
使用NoSQL提升写入性能
数据库系统大多使用的是传统的机械磁盘,对于机械磁盘的访问方式有两种:一种是随机IO;另一种是顺序IO。随机IO就需要花费时间做昂贵的磁盘寻道,一般来说,它的读写效率要比顺序IO小两到三个数量级,所以我们想要提升写入的性能就要尽量减少随机IO。
以MySQL的InnoDB存储引擎来说,更新binlog、redolog、undolog都是在做顺序IO,而更新datafile和索引文件则是在做随机IO,而为了减少随机IO的发生,关系数据库已经做了很多的优化,比如说写入时先写入内存,然后批量刷新到磁盘上,但是随机IO还是会发生。而且一旦发生了页分裂,就不可避免会做数据的移动,也会极大地损耗写入性能。
NoSQL数据库在性能、扩展性上的优势,以及它的一些特殊功能特性
1.在性能方面,NoSQL数据库使用一些算法将对磁盘的随机写转换成顺序写,提升了写的性能;
2.在某些场景下,比如全文搜索功能,关系型数据库并不能高效地支持,需要NoSQL数据库的支持;
3.在扩展性方面,NoSQL数据库天生支持分布式,支持数据冗余和数据分片的特性。
这些都让它成为传统关系型数据库的良好的补充,你需要了解的是,NoSQL可供选型的种类很多,每一个组件都有各自的特点。你在做选型的时候需要对它的实现原理有比较深入的了解,最好在运维方面对它有一定的熟悉,这样在出现问题时才能及时找到解决方案。否则,盲目跟从地上了一个新的NoSQL数据库,最终可能导致会出了故障无法解决,反而成为整体系统的拖累。
缓存分类
开发中,常见的缓存主要就是静态缓存(如静态文件html缓存)、分布式缓存(redis、memcache分布式缓存)和热点本地缓存(热数据缓存降低分布式缓存压力)这三种。
缓存的不足
缓存的主要作用是提升访问速度,从而能够抗住更高的并发。事物都是具有两面性的,缓存也不例外。
首先,缓存比较适合于读多写少的业务场景,并且数据最好带有一定的热点属性。这是因为缓存毕竟会受限于存储介质不可能缓存所有数据,那么当数据有热点属性的时候才能保证一定的缓存命中率。比如说类似微博、朋友圈这种20%的内容会占到80%的流量。所以,一旦当业务场景读少写多时或者没有明显热点时,比如在搜索的场景下,每个人搜索的词都会不同,没有明显的热点,那么这时缓存的作用就不明显了。
其次,缓存会给整体系统带来复杂度,并且会有数据不一致的风险。当更新数据库成功,更新缓存失败的场景下,缓存中就会存在脏数据。对于这种场景,我们可以考虑使用较短的过期时间或者手动清理的方式来解决。
再次,之前提到缓存通常使用内存作为存储介质,但是内存并不是无限的。因此,我们在使用缓存的时候要做数据存储量级的评估,对于可预见的需要消耗极大存储成本的数据,要慎用缓存方案。同时,缓存一定要设置过期时间,这样可以保证缓存中的会是热点数据。
最后,缓存会给运维也带来一定的成本,运维需要对缓存组件有一定的了解,在排查问题的时候也多了一个组件需要考虑在内。