文章目录
- 引用极客兔兔博客中的一句话,因为我感觉这句话说得很NB。
商业世界里,现金为王;架构世界里,缓存为王。
1.1 背景
- 有很多应用场景中涉及到频繁访问一些数据,例如:我们看见的一些点赞量、转发量、网站访问量等,如果我们从数据库中去读取会很慢,因为数据库中的数据存在磁盘上(需要通过IO操作将磁盘数据取到内存中,再从内存中读取数据),而为了增加访问效率,加快访问速度,因此将频繁访问的数据存在内存中,从内存去读,远远快于从磁盘访问数据(如下图)。
1.2 面临的问题
1.2.1 内存
- 将数据存到内存中,但是内存是有限的,那么对于内存中的数据就需要采用相关的策略来淘汰一些数据,常用的有FIFO(先进先出)、LRU(最近最少使用)等。
1.2.2 并发写
- 对于这些数据肯定是涉及到修改等操作的,例如:常看到的一条热门消息的点赞量和转发量在实时的变化,因此对于并发操作涉及到加锁,以保证写入的正确性和一致性。
1.2.3 单机性能
- 单个机器的各种计算资源、存储资源都是有限的,因此对于大型的系统的数据量而言,采用多节点的分布式部署是一种好的选择。
2. 分布式内存对象缓存系统介绍补充
如果利用多台计算机的资源,并行处理提高性能就要缓存应用能够支持分布式,这称为水平扩展(scale horizontally)。与水平扩展相对应的是垂直扩展(scale vertically),即通过增加单个节点的计算、存储、带宽等,来提高系统的性能,硬件的成本和性能并非呈线性关系,大部分情况下,分布式系统是一个更优的选择。
2.1 Memcached
2.1.1 介绍
Memcached是一个自由开源的,高性能,分布式内存对象缓存系统。
Memcached是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象)。这些数据可以是数据库调用、API调用或者是页面渲染的结果。
Memcached简洁而强大。它的简洁设计便于快速开发,减轻开发难度,解决了大数据量缓存的很多问题。它的API兼容大部分流行的开发语言。
本质上,它是一个简洁的key-value存储系统。
一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。
2.1.2 常见的提速方法
- 传统 : 模拟cached方法(存储到数据库时生成一份静态文件到磁盘中)
- 直接操作内存(内存表,memcached服务维持了一张内存表hashdata)
- CPU寄存器(最高速的,但是代价成本高,就是贵)
2.1.3 memcached特征
1.协议简单(文本行协议)
2.基于libevent事件处理(注:libevent是一个程序库,封装了linux的epoll,BSD等操作系统的kqueue等事件处理功能,即使对服务器的连接数添加,也能发挥O(1)的性能,memcached在linux,BSD等操作系统上能发挥其高性能)
3.内置内存存储方式(存储在memcached内置的内存存储空间中,提高性能。问题:memcached重启或操作系统重启数据会丢失,达到一定量后会启动算法自动删除不使用的缓存)
4.不互相通信的分布式(不互相通信共享信息)
2.1.4 使用场景
1.访问频繁的字典数据
2.大量的hot数据(热门数据缓存)
3.页面缓存(web站常用)
4.搜索的查询条件和结果(热门搜索的内存缓存起来)
5.临时处理数据(不需要入库,排重)
2.2 groupcache
- groupcache是一个kv缓存,用于在某些方面替代memcache,groupcache 不像其它的一些缓存数据库有个服务端,需要客户端去连接,换句话说,它本没有服务端或者人人都是服务端。相对于 memcached,groupcache 提供更小的功能集和更高的效率,以第三方库的形式提供服务。
- 还有一个问题,当多个客户端同时访问memcache中不存在的键时,会导致多个客户端从mysql获取数据并同时插入memcache中,而在相同情况下,groupcache只会有一个客户端从mysql获取数据,其他客户端阻塞,直到第一个客户端获取到数据之后,再返回给多个客户端。
2.3 GeeCache
- GeeCache基本上模仿了groupcache的实现,实现了单机缓存和基于 HTTP 的分布式缓存、最近最少访问(Least Recently Used, LRU) 缓存策略、使用 Go 锁机制防止缓存击穿、使用一致性哈希选择节点,实现负载均衡、使用 protobuf 优化节点间二进制通信等。