第六章 memcached剖析

注:本篇博客参考于两本书。

  • 《memcached全面剖析》,该书籍市面上应该没有,我传到了百度云盘,链接如下:http://pan.baidu.com/s/1qXqXmri
  • 《大型网站技术架构:核心原理与案例分析》

前提:

  • 本文是基于memcached1.4版本的,之前的版本与该版本在一些地方是不一样的(eg.《memcached全面剖析》的memcached1.2的内存管理方式就与1.4不同)
  • 在看本文之前,最好先看一下memcached在实际开发中怎么进行操作的,链接《第八章 企业项目开发--分布式缓存memcached

1、memcached特征

  • 协议简单(文本协议、二进制协议)
  • 基于libevent的事件处理,libevent封装了Linux的epoll模型的时间处理功能。
  • slab存储模型
  • 集群中服务器间互不通信(在大集群的情况下,其性能远超其他同步更新缓存的缓存器,当然小集群下,memcached的性能也十分优秀)

2、memcached访问模型

说明:

Xmemcached的具体使用代码查看"Java企业项目开发实践"系列博客的《第八章 企业项目开发--分布式缓存memcached》,下面的解释会依据该代码进行。

在上图中,memcached客户端假设使用XMemcached

  • 服务器列表:在根pom.xml文件中进行了配置
  • 路由算法有两种:(可以在程序中指定)
    • 一致性hash算法(推荐)
    • 简单求余法
  • 通信模块:
    • 通信协议:TCP协议
    • 序列化协议:二进制协议(推荐)、文本协议
  • Memcached API(缓存的增删改查):在程序中编写

整个流程:

应用程序(AdminService)调用Memcached API(假设为add操作),向memcached服务器添加缓存,这时候,程序会首先根据配置的路由算法(假设是一致性hash算法)在服务器列表中选出一台服务器(假设是node1),之后该API通过序列化协议序列化对象(当然,这个是可无的,eg.value是一个String),并通过TCP协议将将要存储的key-value对存入相应的服务器。在get时,只要采用的是与add时相同的hash算法,就会选中add时的那一台服务器。

看完这一段,流程明白了。但是有几点疑问:

  • 两种路由算法是怎样实现的?为什么使用一致性hash算法
  • 缓存到达服务器的时候究竟怎么存储?(slab内存模型)
  • 当缓存超过一定的容量后,缓存的自动删除是采用什么策略,怎样删除的?(LRU)
  • 两种序列化协议有什么优缺点?

3、hash算法

3.1、简单求余法

原理步骤:求得key的整数hash值(对于Java对象而言,直接使用其hashCode()方法就好),再除以服务器台数,获取余数,根据该余数选择服务器。

注意:如果选择的服务器无法连接时,会进行rehash,即:将连接次数添加到键中,重新计算hash值后,再重新连接。当然可以禁止rehash。

优点:

  • 简单
  • hash分散性好(因为hashCode()的值具有随机性)

缺点:

  • 添加或删除服务器的时候,缓存的获取就会出问题了(因为服务器台数变了,求余的时候分母变了,余数也就可能变了),假设在99台memcached服务器中又新添加而一台,则缓存的不命中率是99%,即n/(n+1),n表示原有的服务器。

注意:

  • 在XMemcached中仍保留了该算法
  • 适用于不需要考虑集群伸缩性的时候(即机器总数不变)

3.2、一致性hash算法

对于绝大部分系统,集群的伸缩性是五个非功能需求中比较重要的一个,也就是说必须克服"简单求余法"的缺点。

  • 原理:先构造一个长度为0~232的整数环(使用二叉树构造),根据节点(memcached服务器)名称的hash值将缓存服务器节点放置在这个hash环上,然后根据需要缓存的数据的key来计算其hash值,然后在hash环上顺时针查找距离这个key的hash值最近的缓存服务器节点,完成key到服务器的hash映射查找。

    • 如果超过232还找不到,则存在第一台memcached上(依旧是顺时针)
  • 存在的问题:当服务器数量比较少的情况下,有可能造成负载不均衡的情况,为了防止这种情况的发生,使用将物理服务器先虚拟化成多台虚拟服务器,然后将这些虚拟服务器的hash值放在环上,当客户端路由到某台虚拟服务器上时,找到该虚拟服务器所对应的物理服务器即可。
    • 一般而言,一台物理服务器虚拟化为150台虚拟服务器最合适,太少会造成负载不均,太多会影响性能
  • Memcached采用这样的算法,在我们新加入服务器或集群中的某台服务器宕机时,都不会有太大的影响,只会影响一小段(见下图),确保了集群的可用性与伸缩性

注意:

  • hash环是一个二叉树,最后边叶子与最左边相连成环
  • 整个缓存的查找过程就是找一个刚刚大于等于查找数的最小值

疑问:(这一点没查到资料)

  • 服务器的hash算法是怎样的
  • 计算缓存key的hash算法是否要与服务器的一致,还能不能使用原来的hashCode()

4、slab内存模型

4.1、为什么使用slab内存模型?

  在最一开始的内存分配与回收是通过malloc和free来处理的,该方式会产生内存碎片,加重内存管理器的负担,严重缓存操作影响效率。

slab模型的出现就是为了:

  • 提高缓存操作效率
  • 完全的解决内存碎片问题。

注意:

  • 第一个目的:已经实现了(因为直接定位合适的chunk会很快)
  • 第二个目的:采用slab机制依旧会产生内存碎片,或者说成是内存浪费

4.2、slab模型原理

说明:该图摘自一篇博客(图中有标记,但是看不清),但是是很久以前摘的了,忘记了。以后找到了,我会标明出处的。

memcached的内存分配就是下面这一句话:采用分组管理预分配方式。

4.2.1、分组管理

  • 分组方式:Memcached将内存空间分为一组slab,每个slab的大小固定为1M,每个slab里又包含一组chunk,同一个slab里的每个chunk大小相同。根据这些slab中的chunk的大小,将这些slab编号slab class(也就是上图中的Classes i)。
  • 存储原理:当来一个要存储的key-value对时,我们查看这个数据的大小,选择最适合的slab class中的空闲chunk放置该对象。
    • 最合适的chunk:即该chunk的大小刚刚大于等于所存储数据的大小,而比该chunk小一级的大小刚刚比所要存储的数据小。

以上这种方式会造成内存大量浪费(我认为这也是内存碎片)。

  • 减少内存浪费的方式:预估自己的缓存数据的大小,然后在启动Memcached时合理的指定参数-f(增长因子)和-n(chunk最小尺寸)来划分内存大小,根据公式chunk size = 80*f*(n-1)将内存分配为若干个slab class。

疑问:上边这个若干到底是多少?

我们可以根据f,n,以及一个slab最大为1M来确定。(例子,我不举了,自己想想)

4.2.2、预分配

  在启动Memcached时通过-m参数为Memcached分配可用内存(假设-m 1024,即分配了1G内存),但是启动的时候不会把这些内存一次全部分配出去,而是默认先分配若干个slab class(数量取决于-f与-n参数),当其中的一个slab class被用完之后,Memcached就会再次申请1M空间,产生一个该slab class。这一块儿结合缓存删除机制中的LRU算法来看。(这一块如果有误,请大神帮忙指出来)

5、缓存删除机制

  • memcached不会释放已分配的内存,记录超时后,其存储空间即可重复使用
  • memcached内部不会监视缓存是否过期(即memcached不会在过期监视上耗费CPU时间),在get时查看缓存的时间戳,检查缓存是否过期
  • memcached会优先使用已超时的缓存的空间,但是当所有空间都没有超时,所有内存都已经分配完了,就删除最近最少使用(LRU)的缓存,将其空间分配给新缓存

注意:第三条与内存分配部分的预分配结合来看。

6、两种序列化协议

  • 文本协议:

    • XML、JSON
    • key的长度为256字节
  • 二进制协议:相较于文本协议
    • jdk序列化机制、protobuf
    • 不需要文本协议的解析处理,速度更快
    • 具有更长的key,理论上最大可使用65536字节长度的key
    • 出现在1.3以后,推荐使用

注意:对于以上两种协议,自己选择吧。

  • 二进制协议+JDK的序列化机制,那么由于JDK自己的序列化机制低效,所以在速度上未必会比使用了fastjson的文本协议更快
  • 二进制协议+protobuf,速度很快,但是使用起来不太方便
  • 文本协议+fastjson

7、部分API

  • add:仅当存储空间中不存在相同key的数据时才保存
  • replace:替换。即仅当存储空间中存在相同的数据时才保存
  • set:add+replace。即无论何时都保存
  • delete(key, ‘阻塞时间(秒)‘)
  • 增1、减1操作,做计数器
  • get_multi(key1, key2):一次性非同步的同时(即并发的)获取多个键,比循环调用getKIA数十倍

注意点:

  • 对于memcached的监视:可以采用"nagios"
时间: 2024-07-29 11:14:29

第六章 memcached剖析的相关文章

20135306 第六章学习总结

第6章存储器层次结构 存储器系统是一个具有不同容量.成本和访问时间的存储设备的层次结构. cPU寄存器保存着最常用的数据. 靠近CPU的小的.快速的高速缓存存储器作为一部分存储在相对慢速的主存储器中数据和指令的缓冲区域. 主存暂时存放存储在容量较大的.慢速磁盘上的数据,而这些磁盘常常又作为存储在通过网络连接的其他机器的磁盘或磁带上的数据的缓冲区域. 6.1 存储技术 6.1.1随机访问存储器 随机访问存储器分为两类-静态和动态的. 静态RAM(SRAM)比动态RAM(DRAM)更快,但也贵很多.

HttpClient 4.3教程 第六章 HTTP缓存

HttpClient 4.3教程 第六章 HTTP缓存 Posted on 2013 年 10 月 28 日 6.1.基本概念 HttpClient的缓存机制提供一个与HTTP/1.1标准兼容的缓存层 – 相当于Java的浏览器缓存.HttpClient缓存机制的实现遵循责任链(Chain of Responsibility)设计原则,默认的HttpClient是没有缓存的,有缓存机制的HttpClient可以用来临时替代默认的HttpClient,如果开启了缓存,我们的请求结果就会从缓存中获取

第六章-“那又如何”:情绪低落为何会使人屈服于诱惑

第六章-"那又如何":情绪低落为何会使人屈服于诱惑 核心思想: 情绪低落会使人屈服于诱惑.摆脱罪恶感会让你变得更强大. 深入剖析: 缓解压力的承诺.当你面临压力.感到焦虑或情绪低落时,你会怎么解决? 什么吓到了你?注意那些从媒体.网络或其他渠道听到或看到的压力因素. 遭遇挫折.当意志力失效的时候,你会产生罪恶感并责备自己吗? 决定改善心情,你会用幻想未来的自己来改善现在的而不是采取实际行动来改善自己的行为吗? 意志力实验 有效的解压方法.下一回,当你面临巨大的压力时,尝试一种有效的解压

数据库系统实现 第六章 查询执行

第六章 查询执行 查询执行也就是操作数据库的算法 一次查询的过程: 查询-->查询编译(第七章)-->查询执行(第六章)-->数据 查询编译预览 查询编译可以分为三个步骤: a)分析:构造分析树,用来表达查询和它的结构 b)查询重写,分析树被转化为初始查询计划,通常是代数表达式,之后初始的查询计划会被优化为一个时间更小的计划 c)物理计划生成,将查询计划转化成物理的计划, 为了选择更好的查询计划,需要判断 1)查询哪一个代数的等价形式是最有效的 2)对选中形式的每一个操作,所使用的算法选

第六章:异常机制

第六章:异常机制 异常的定义 异常:在程序运行过程中出现的意外事件,导致程序中断执行. 异常处理 try...catch 语法:try{ //可能出现异常的代码}catch(异常类型 异常对象名){ //处理异常的代码:}执行过程:当try中的代码异常发生时抛出一个异常对象,该异常对象与catch中异常类型进行匹配,匹配成功进入catch块,否则不执行catch中代码(相当于异常未被处理).程序只有当异常处理成功后才能继续执行. try...catch...catch 语法:try{ //可能出

2017上半年软考 第六章 重要知识点

第六章 项目整体管理 []项目整体管理概述 [][]项目整体管理的含义.作用和过程 项目整体管理6个过程?p264 项目整体管理包括什么? 项目管理的核心是什么? 项目整体管理涉及哪几个方面?p265 [][]项目经理是整合者 项目经理作为整合者要做什么?p265 [][]整体管理的地位 []项目整体管理实现过程 [][]制定项目章程概述 项目章程的意义是什么? 项目章程包括什么? [][]制定项目章程 项目章程的作用? 项目章程的输入? 制定项目章程的工具和技术?p267 项目章程的输出?p2

ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片:多对多关系(上)

这章介绍了怎样创建一个新的实体来管理图片,怎样使用HTML窗体来上传图片文件和使用多对多关系来使它们与产品相关,并且怎样来保存图片到文件系统中.这章也介绍了更多复杂的错误处理增加客户端错误到模型中为了把它们显示回给用户.在这章中播种数据库使用的产品图片可能在在第六章的从Apress网页站点下载代码中. 注意:如果你想遵从这章的代码,你必须完成第五章的代码或者从www.apress.com下载第五章的源代码作为一个起点. 创建实体保存图片文件名 这个项目,我们正要使用文件系统在Web项目中存储图片

Linux与云计算——第二阶段Linux服务器架设 第六章:目录Directory服务器架设—FreeIPA

Linux与云计算--第二阶段Linux服务器架设 第六章:目录Directory服务器架设-FreeIPA 1 FreeIPA 配置FreeIPA服务器 Configure IPA Server to share users' account in your local network. [1] Install FreeIPA. [[email protected] ~]# yum -y install ipa-server ipa-server-dns bind bind-dyndb-lda

APUE读书笔记-第六章 系统数据文件和信息

昨天看完了,今天来看看第六章.感觉第六章的内容不是非常重要.简单看看吧 6.2 口令文件 口令文件其实就是/etc文件夹下的passwd文件,但处于安全性的考虑,我们无法直接读取它.就是通过直接限制权限的方式对其进行保护,passwd文件具体权限如下: -rw-r--r-- 1 root root 可以看到只有root用户具有读写权限,与root同组的用户与其他用户仅具有读权限. 不过为了解决以上问题,Linux中给出了一系列数据结构与函数帮助我们操纵口令文件,首先是关键数据结构,定义位于/in