多次提到了存储服务,如mysql集群,而且存储服务多数是把本地所提供的存储空间只能给本地提供给用户空间访问的这么一种存储机制,
通过所谓的某一层应用软件再一次抽象出另外一种数据,组织结构,并且通常是能够通过套接字将自己的api输出给其他服务应用,都可以统称为存储服务
这种存储服务,不管是怎么组织管理的,不管用的什么模型,用的什么范式,大多数存储数据无非就是增删改查几种基本需求
CRUD
注意的是,这种数据服务无论是何种模型,最终数据还是得存储在文件系统之上表现为文件,mysql就把它抽象为了一个关系模型,可以按行按列,甚至用更为简洁的方式,如sql接口,api来访问里面数据
事实上memcached和redis也无非都是此类运用存储服务,所不同的是
不同的存储服务,如果底层的数据模型不同的话,他们所提供的ap,增删改查功能接口,也不会完全相同,比如memcached就属于键值存储,只是支持最简洁的数据格式,能存进去的数据类型,无非就是
(name:jerry),存的每一个数据项都是一个键值对,所以要想表达复杂的数据模型就可能做不到了,
在mysql中设计张表,任何一行信息都可以代表一个实体,可以表示一个比如人的很多信息,年龄之类的
但是在memcached当中就不行,只能描述一个实体的一个属性,多个属性有什么关系,也不管,所以用到纯粹的缓存功能时,memcached才有用,多一点要求基本上就没用了,(所以这是一种存储模型简单到令人发指的东西)
任何一种存储服务,要想与这个服务打交道,如果通过网络的套接字来输出服务,一般有自己的专门协议,比如mysql有mysql协议,memcached就有memcached的协议,redis有redis协议
要想与这个服务打交道,就得通过这个协议能与服务对话,
要说你服务的语言,要么能进入你的软件程序,要么能进入你的库,去开发程序,协议适配器,驱动,只有它才能与服务交互
redis有redis的适配,mysql有mysql适配,memcached简单到没有适配,甚至可以用telnet直接连接,现在大家想要统一一个协议交互
基本都统一到http协议上,现在很多存储服务都可以提供http接口,http协议能与对方直接交互,即便没有html,也可以用http上传下载文档,就是用http接口
可以用http协议给对象发送增删改操作,每个对象都有一个id表示,比如(h ttp://w w w.i linux.io/myapp/7654321/creat)就是通过这个url发送过去,删除就在后面改成delete
现在很多应用都支持这个风格, RESTFUL API,表针状态转移,大概在2000年左右,作者在博士期间发布了论文,现在很多开源应用都是http接口 支持RESETFUL风格的API,甚至于在应用程序开发领域,也间接的成为一种,主流的风格,后来讲的docker或者其他应用时,与后端的其他交互的时候都是http协议而且是基于RESTFUL风格来实现的
memcached:
memcached is a high-performance, distributed memory object caching system, 内存对象缓存系统
generic in nature, but intended for use in speeding up dynamic web applications by alleviating database load.
虽然设计的原初特性是通用的目的,但多数是实现web应用程序加速的
lamt,lnmt也好,jsp程序都需要从mysql中一个web存储服务的,但是mysql性能太差了,每秒钟只能50-200tps,平均值,这个时候对某些查询结果,为了再下次查询的时候不至于再执行半天,可以加一个缓存系统(memcached)
memcached是一个旁挂式缓存,而非代理,所以你的应用程序要想使用memcached自己来查缓存,缓存如果没命中,得自己去找存储系统,找完之后增加负责缓存下来(并非想varnish,varnish是代理式缓存)
旁挂式的,以为着在应用程序适配的时候,自己需要是mysql客户端,还有一个模块是mysql客户端,还要在memcached客户端上两者进行转换,查的时候,如果没命中,需要激活这个客户端去找mysql,从mysql查到数据后,还能激活这个客户端把缓存下来,所以你这个客户端需要拥有智能功能,这就是两种memcached经常的特性,它的特性一半在客户端一半在服务端
缓存服务器:
缓存:cache,无持久存储功能;
bypass缓存
k/v cache,仅支持存储流式化数据;
LiveJournal(非常著名的互联网站点)、
旗下的Danga Interactive研发(分布式文件系统,高性能的web反向代理服务器,),
特性:
k/v cache:仅可存储可序列化数据;存储项:k/v;(任何数据想要存储在磁盘上都要通过电信介质传输数据,无非就是0101,高低电频,如果一个数据有接口,传输的时候就能打碎,传过去以后,对方还能把它还原回来,但如果用java程序写的就有可能不能转换,)
(java是完全面向对象的,每个对象是在内存中生成的,这个对象要想存到磁盘上,每个对象都有自己的格式,存到磁盘上就相当于流逝化,从磁盘还要装入内存中,这就叫流逝化,有一种程序就帮你专门负责流逝化)
智能性一半依赖于客户端(调用memcached的API开发程序),一半依赖于服务端;
分布式缓存:互不通信的分布式集群;(客户端来分布,自己互不通信)
分布式系统请求路由方法:取模法,一致性哈希算法;
(可以组织多台memcached来用,但是有问题,第一台服务器缓存袭来数据,查只能到第一台去查,查到2,缓存就命中不了,浪费了,所以数据缓存到哪个节点,就只能到哪个节点去查,这样才能缓存可命中的,保证数据在4个节点上,各存了4分之一差不多)
数据缓存到一个节点,下次访问要想访问该节点有两种方法,
1.取模法(服务器数量发生变化,全局都会失效,静态数组来存储服务器节点)
2.一致性哈希算法
(客户端要知道你有几台服务器,要知道自己怎么调服务器,所以客户端自己要实现算法,要么是取模,要么是一致性哈希,一般使用一致性哈希算法,程序员需要自己写代码实现)
算法复杂度:O(1)
清理过期缓存项:
缓存耗尽:LRU
缓存项过期:惰性清理机制
既然是缓存,那就有过期时间,memcached对于每个缓存下来的数据都给了一个TTL值,这个TTL值直到耗尽为0就删除了,删除这个缓存项有一个非常有意思的方式,叫惰性清除法(假如到期了,但是空间没用完,不用激活LRU(最近最少使用缓存项),空间没有用完,这时候就不动它,这是把可见性标记为0 TTL=0)
已经被收录进base仓库中
安装配置:
由CentOS 7 base仓库直接提供:
监听的端口:
11211/tcp, 11211/udp(既可以通过tcp提供服务,又可以通过udp来提供服务)
缓存的都是极小的数据k/v,v最大不能超过1M,
因此如果用tcp来创建的话,效率非常低,每次都是短连接,三次握手,4次断开,
所以也支持udp(不推荐,还可以设置长连接)
主程序:/usr/bin/memcached 可以向命令行传递选项来配置的,为了使得将来能修改这些选项
配置文件:/etc/sysconfig/memcached (varnish有一个。params文件,早期在/ETC/CONFIG下,后来才移动到varnish目录下的)
Unit File:memcached.service
协议格式:memcached协议 (文件格式有两个,二进制和文本)
文本格式
二进制格式
命令:
统计类:stats(查看统计数据的,总共存了多少缓存项,各自有什么特点), stats items, stats slabs, stats sizes
存储类:set, add, replace, append 追加, prepend (insert,前面插入)
命令格式:<command name》 <key》 <flags》 <exptime》<bytes》
<cas unique
检索类:get(,查获取数据), delete(删), incr/decr
清空:flush_all(情况所以缓存)
这些命令了解即可,开发的话直接调用接口程序即可
示例:
telnet> add KEY <flags》<expiretime》 <bytes》 \r
telnet> VALUE
memcahced本身是用内存来存储数据的,内存是属于分页存储的,大约每4k一个页,当缓存一个缓存项的时候,最大时是一兆,4k不够用,需要多个页,最小可能就几个字节,比如最小存了一个缓存项,只有30个字节,存到4k的页里页就太浪费了,因此为了高效使用内存(varnish使用内存时,经常地增删增删,会出现空隙,碎片)为了避免碎片,memcached采用了一种机制,立即分配给你内存如1g,你用或不用都在那里
一个G内存拿过来以后,按照固定大小分割开来,分隔开指的是,比如要存的缓存项最少有30个字节的,就分一堆30个字节或40个字节的碎片,放好
如果要存一个31字节的,基于增长因子的格式,你的缓存项是多大,就固定分配这么多种,增长因子如果是1.5倍,意味着后面的是前面的1.5倍,开始30,后面就是45字节,45的字节又放一堆,再1.5倍放一堆,最大到1M,所以从你的最小项到最大项之间,要把整个提供的内存空间,划割成N种分类,每一个类又多少个,取决于你总的内存是多少
256M可以和256G可用肯定不一样
分类有多少类别取决于你的增长因子。自增1.2倍,其实到最大是1M
自增(1.2,1.4,1.8)所迈的步数是不一样的,到底多少为好
如果要存31字节的,像刚才就只能存放45字节中的了,14字节是浪费,你的步子太大会发现你浪费的很多、
步子太小也有问题,类别太多,的确省了很多空间,但是类别变多了
后面是前面的多少倍就是增长因子,growth factor,每一个大小作为一个类别。
每一个内存分配是靠 slab allocator 程序来实现,slab类别分配器,分配的每一个类别slab class
30字节的为一类,45字节的为另一类
slab allocator,当你指定memcached可使用1G内存当缓存时,把1G立即生成过来,按照growth factor切割成多类
每一个都计算好放在那里的,要存储的时候,找一个最近但大于等于缓存项的空间来存放,所以就避免了缓存碎片,至少降低了内存碎片
基于LRU算法做清理(最近最少使用)
直接去安装memcached
主程序很简单,就那么几个程序
-p监听在tcp端口,
-U 监听在UDP端口 使用0就是关闭的
-s可以监听socketfile,本地通讯时更加高效,基于共享内存来通讯
-l监听地址
-d运行在后台
-r最大核心文件大小
-u以什么方式运行
-M 一旦缓存耗尽,后面的缓存项久不让存了(把内存耗尽时,默认是用LRU算法去清理一些缓存,来腾出空间)
-C最大并发链接数,默认是1024
-f factor 增长因子,默认是1.25
** -t指明memcached自己的线程数,整个线程对于memcached来讲,单线程响应多个请求的,基于epoll机制的,这个数量一般要小于等于cpu核心数
-p来指定运行时参数的**
自定义5个变量
端口
用户
最大并发连接数
缓存大小 测试来讲,64够用了,生产中最起码2G
每个选项都有一个o来定义
启动时就是靠memcached来定义的
其实就是从sysconfig/memcached文件中,加载这么一些变量来传递给启动时命令行的选项值
memcached一般是存储层,不会直接面向客户端服务的,都是面向前端应用服务器,或者反代,所以一般并发链接数不会太大,在接入层,nginx,30000个请求,可能只有百分之20到达存储层,而且到大存储层,一般也是由前端负载均衡器发过来的,并发链接数并没有要那么大,所以1024并不是一个小数字,对于存储来讲
命令+键+flags标记位+exptime 过期事件+bytes要存数据的大小
显示了各种类型数据
会探测你的cpu核心数
接收几个get命令。或者命中都有显示
stats items查看缓存项的
stats slabs看内存分配器的
active slabs活动的分配项
total_malloced 一共分的项 存了多少数据
标记为1,过期时间60s,存储14个字符
后面补久用append,后面补就用preappend
后面补一个iunix,
加不上是因为数据已经过期了
再来一遍
标记为1,600s,13个字符
在前面补一个就是preappend,delete mykey 删除
再一次stats,可以看到很多次操作
**缓存项一般缓存计数器的数值,如果存下来以后,要缓存一些数值,比如微博的转发次数,不断地增增减减
add counter计数器 1 标记位 600s 1个字符 **
对数值型数据可以不停地自增自减
这就是memcached基本操作,想要使用memcached,接下里就要自己想办法在应用程序中使用了
对于运维来讲,只需要确保安装启动,监控就没问题了,余下就是程序员如何让使用
如何让tomcat的会话集群能将会话存储到memcached当中去
使用一个外部的存储来存储来存储会话的
其中有一项叫做memcached的session cached manager sms
tomcat 会话管理器,可以把会话存在memcached和redis中,
可以支持有黏性和非粘性
memcached是一个缓存,宕机了该如何,为了避免数据丢失,需要做冗余
memcached由于没有集群功能,我们只能在前端做双险,保存两份,默认一个为主,都存,只从一份读,一个挂了就从另外一份读,就变成主的了
这个过程,能把错误发生的请求转发至另外的节点上
msm
要想存储在存储系统中,需要做流逝化的,tomcat是java程序,java程序的所有应用运行都是先对象化的,而对象一旦流逝化,再还原就还原不过来了,所以需要一个序列化工具来帮助完成序列化,能序列化还能还原回来
序列化工具常用的有几个,kryo
解释了几种不同的情形大概怎么配置
如使用 sticky sessions + kryo
non-sticky sessions + kryo都可以自己定义
className=“de.javakaffee.web.msm.MemcachedBackupSessionManager"类名
memcachedNodes=“n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211(节点编号)”
sticky=false 不做sticky,表示轮询,(不是指前端会话粘性,而是指tomcat服务器访问memecached的时候,到底是访问一个(读的时候只从一个读)还是从所有的都可以读
如果使用的话,还可以避免把压力都压再一台memcached上
sessionBackupAsync=“false” 是否可以基于异步方式同步
lockingMode=“uriPattern:/path1|/path2” 哪些路径下可以激活锁模式
requestUriIgnorePattern=”.*.(ico|png|gif|jpg|css|js)$" 对于哪些资源可以忽略session(对于静态内容来讲,追踪session是没有意义的)
transcoderFactoryClass=“de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory” 用哪一个对应的类来完成转码 factory 工厂
如果要使用sticky session,表示读的时候只从一个读
<Context
…
<Manager className=“de.javakaffee.web.msm.MemcachedBackupSessionManager”
memcachedNodes=“n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211”
failoverNodes=“n1” 故障转移节点是n1 ,n2是主节点,存的时候n1和n2都会存,默认只有n2会读
requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass=“de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory”
/
</Context
准备两个memcached节点,来配置,可以再两个tomcat上安装memcached
在前端上打开核心转发
所有来自192.168。10.0这个网络的请求使用 -j 做SNAT 到 外网地址
memcached的作为存储服务,很多程序链接都需要有驱动,如果用的时候php,就需要安装一个php-memcached
如果是c语言,应该是lib-memcached
在第3个节点上也安装
安装以后,前端的snat规则就没有必要了,可以删除,因为之前N2,N3都是内网
启动服务
\不管哪种方式安装,都需要把对方选定的安装包的对应的类文件复制到tomcta类文件下就可以了
这个memcached-session-manager类
下载jar文件,打包后的类文件,下载以后防止别人篡改,可以下载jar》asc校验码
这个类还是和版本有关系的
如果是tc7就找 tc7,tc8就找tc8
所以我们至少需要这个两个包的相关内容,
还可以去下载一个序列化工具,帮你完成会话的序列化,找到对应版本下载jar文件
、http://repo1.maven.org/maven2/de/javakaffee/msm/msm-javolution-serializer/2.1.1/
注意的是,如果要用到的是javolution,额外还需要spymemcached-{version}.jar这个包
这个几个jar文件要安装在tomcat主机上自己的类文件存放路径下
把你的jar文件扔在,/usr/share/java/tomcat里就可以了这是yum安装
如果是使用官方下载的tar包安装的,那就再tar包的lib目录下
先把tomcat集群停掉
systemctl stop tomcat
配置文件一样 复制一份过去即可,还原到没有cluster
按照文档介绍进行配置,把kryp改成javolution即可
再你的context或者host中加个manager就可以了
path的属性 docbase 文档路径(相对路径test,等于webapps下的test路径) reloadable自动装载
+会话管理器定义
…
<Manager className=“de.javakaffee.web.msm.MemcachedBackupSessionManager”
memcachedNodes=“n1:host1.yourdomain.com:11211,n2:host2.yourdomain.com:11211” (n1,n3只是一个标识而已+地址
failoverNodes=“n1”
requestUriIgnorePattern=".*.(ico|png|gif|jpg|css|js)$"
transcoderFactoryClass=“de.javakaffee.web.msm.serializer.kryo.KryoTranscoderFactory” (用的如果是javolution就需要修改
/>
用javolution 文件这两个文件都需要下载下来
另外一个配置文件应该是一模一样的所以就先复制过去
去给我们的tomcat添加这么几个jar文件
复制到n2的jar包里
复制给n3主机
**复制完成就可以启动tomcat了
javolution序列化工具
多了一个tc8 的工具,避免影响就把这个删除
**
n3节点也一样删除
先监控日志,现在可以启动tomcat
对于n3节点也一样
没报错说明初始化完成了
下面可以尝试访问应用了,会话再m1中
会话没变但变成tomcata说明成功了
停一个memecached
会自动转移到第二个节点上去
sticky如果=false,就标识这两个memcached是轮询的
如果把m1再上线
会不会转移回来,还在使用m2,m2宕机就使用m1了
m1宕机了,数据丢失了,就需要从m2复制数据
这样session server就绑定了
对于tomcat主机而言,将来可能会安装一些其他的对应的客户端所使用的API的一些包的
php链接memcached的链接叫php-pecl-memcache和php-pecl-memcached,这两个其实都是客户端API,是由两个不同组织开发的目前来讲好像第一个更流行,收入base仓库的
c语言连接的叫libmemcached-devel,这个包其实带有客户端测试工具,可以用它拉链接到memcached服务器上去,做一些管理操作
安装以后有很多工具是mem开头
memstat
-servers指明你的memcached服务器是什么
其他的 没有认证直接连接上去即可
这是由libmemcached包提供的
这些功能有可能是为了写zabbix监控memecached的时候的接口