memcached

  许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示。但随着数据量的增大、访问的集中,就会出现RDBMS的负担加重、数据库响应恶化、网站显示延迟等重大影响。memcached通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度、提高可扩展性。

  第一次访问:从关系型数据库(RDBMS)中取得数据保存到memcached中;

  之后的访问:从memcached中去的数据显示页面。

Memcached作为高速运行的分布式缓存服务器具有以下特点:

1.协议简单

  memcached的服务器客户端通信并不使用复杂的MXL等格式,而是使用简单的基于文本的协议。

2.基于libevent的事件处理

  libevent是个程序库,他将Linux 的epoll、BSD类操作系统的kqueue等时间处理功能封装成统一的接口。memcached使用这个libevent库,因此能在Linux、BSD、Solaris等操作系统上发挥其高性能。

3.内置内存存储方式

  为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached,重启操作系统会导致全部数据消失。另外,内容容量达到指定的值之后memcached回自动删除不适用的缓存。

4.Memcached不互通信的分布式

  memcached尽管是“分布式”缓存服务器,但服务器端并没有分布式功能。各个memcached不会互相通信以共享信息。他的分布式主要是通过客户端实现的。

Slab Allocation机制

  最近的memcached默认情况下采用了名为Slab Allocator的机制分配、管理内存。 在该机制出现以前,内存的分配是通过对所有记录简单地进行malloc和free来进行的。 但是,这种方式会导致内存碎片,加重操作系统内存管理器的负担,最坏的情况下, 会导致操作系统比memcached进程本身还慢。Slab Allocator就是为解决该问题而诞生的。

  Slab Allocator的基本原理是按照预先规定的大小,将分配的内存分割成特定长度的块, 以完全解决内存碎片问题。Slab Allocation的原理相当简单。 将分配的内存分割成各种尺寸的块(chunk), 并把尺寸相同的块分成组(chunk的集合)。但是分成组由于分配的是特定长度的内存,因此无法有效利用分配的内存。

  例如,将100字节的数据缓存到128字节的chunk中,剩余的28字节就浪费了(如下图)。

   就是说,如果预先知道客户端发送的数据的公用大小,或者仅缓存大小相同的数据的情况下,只要使用适合数据大小的组的列表,就可以减少浪费。

数据过期方式

1.Lazy expiration

  memcached内部不会监视记录是否过期,而是在get时查看记录的时间戳,检查记录是否过期。这种技术被称为lazy(惰性)expiration。假如我们所存储的数据项相当多的时候,在这时候进行监控的话,花费的代价是相当大的,所以memcached不会在过期监视上耗费过多的CPU时间,从而在性能方面也起到一定的优化作用。

2.LRU

  memcached会优先使用已超时的记录的空间,但即使如此,也会发生追加新记录时空间不足的情况,此时就要使用名为 Least Recently Used(LRU)机制来分配空间。顾名思义,这是删除“最近最少使用”的记录的机制。因此,当memcached的内存空间不足时(无法从slab class 获取到新的空间时),就从最近未被使用的记录中搜索,并将其空间分配给新的记录。从缓存的实用角度来看,该模型十分理想。

基于客户端的memcached分布式

  memcached的分布式,通过键值进行hash计算,获得一个hash值,然后,通过通过该hash值对已有的服务器台数进行求余,把该需缓存对象存到相应的服务器上,不过该方式也存在严重的问题,接下来再讨论,先从简单的谈起。

  假设memcached服务器中有node1-node3三台服务器,应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据.

1.准备

  首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后, 客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。 服务器选定后,即命令它保存“tokyo”及其值。

2.添加时

“kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存。接下来获取保存的数据。获取时也要将要获取的键“tokyo”传递给函数库。 函数库通过与数据保存时相同的算法,根据“键”选择服务器。 使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。 只要数据没有因为某些原因被删除,就能获得保存的值。

3.获取时

讲不通的键保存在不同的服务器上,就实现了memcached的分布式,memcached服务器增多,键就会分散,即使一台服务器发生故障无法使用,也不会影响其他的缓存,系统可以继续运行下去。

   实现了memcached的分布式,但是对于服务器端的分布式还是没有实现,当考虑到一个问题,如果新增或者是移除服务器的话,会导致一个严重的问题,就是缓存的命中率严重下降,以为算法中的余数计算没有考虑到服务器数量的变动,如果服务器数量保持不变,那肯定是个不错的选择,但是在实际中,我们的系统在不断增强,所需要的缓存的数据量不断提高,面对这种情况,出现宕机或者是服务器数量的变动问题是正常的,所以我们需要想一个合适的办法去解决这个问题,把损失降到最小,不能因服务器的变动而导致缓存命中率严重下降,这样的话就失去了使用memcached的意义了。

  所以需要结合一致性哈希算法来分析,关于一致性哈希算法的细节,在另外一篇博客中详细介绍了。在此不再赘述。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

几种服务器端IO模型的简单介绍及实现(下)

5、使用事件驱动库libevent的服务器模型 Libevent 是一种高性能事件循环/事件驱动库。 为了实际处理每个请求,libevent 库提供一种事件机制...

3739
来自专栏linux驱动个人学习

cyclictest 简介

1. cyclictest 简介以及安装 1.1 cyclictest 简介       cyclictest 是什么? 看名字应该就能大致猜出来它是一种 te...

5504
来自专栏JavaEdge

操作系统之内存管理内存管理3.1 内存管理的概念3.2 内存覆盖与内存交换3.3 内存连续分配管理方式3.4 内存非连续分配管理方式

5906
来自专栏Java技术分享

dubbo工作原理,集群容错,负载均衡

dubbo主要核心部件 Remoting:网络通信框架,实现了sync-over-async和request-response消息机制。 RPC:一个远程过程调...

4086
来自专栏逍遥剑客的游戏开发

Direct3D资源

3507
来自专栏Golang语言社区

几种服务器端IO模型的简单介绍及实现(下)

5、使用事件驱动库libevent的服务器模型 Libevent 是一种高性能事件循环/事件驱动库。 为了实际处理每个请求,libevent 库提供一种事件机制...

2917
来自专栏用户2442861的专栏

操作系统内存管理——分区、页式、段式管理

内存管理主要包括虚地址、地址变换、内存分配和回收、内存扩充、内存共享和保护等功能。

1431
来自专栏JavaEdge

GET和POST到底啥区别???

最普遍的答案 我一直就觉得GET和POST没有什么除了语义之外的区别,自打我开始学习Web编程开始就是这么理解的。 可能很多人都已经猜到了,他要的答案是:

1072
来自专栏Django中文社区

拓展 User 模型

Django 用户认证系统提供了一个内置的 User 对象,用于记录用户的用户名,密码等个人信息。对于 Django 内置的 User 模型, 仅包含以下一些主...

3405
来自专栏蓝天

使用异步I/O大大提高应用程序的性能

aio_return 异步 I/O 和标准块 I/O 之间的另外一个区别是我们不能立即访问这个函数的返回状态,因为我们并没有阻塞在 read 调用上。在标...

982

扫码关注云+社区

领取腾讯云代金券