Nosql---memcache(上)
Nosql的含义
Nosql(Not Only Nosql)泛指非关系型数据库,它是由一次叫"反SQL运动"的社区讨论而诞生的.这运动的发起最早起源于社区网站Livejournal的开发团队,他们初衷是为了减少数据库连接数,减轻数据库的工作压力,但发展至今有着其他不同的应用邻域,因此Nosql处于一种所谓百家争鸣的时期.
Nosql的分类
Nosql产品大概六种,ttServer,redis,mongodb,memcache,Aliyun MQ,KVCache(Memcache).
Nosql共同的特点和优点:
Nosql通常以key-value形式储存的(如:memchache,redis,mongodb)
不支持sql语句
没有表结构
配置简单
灵活,高效的操作与数据模型
简单易学
能很好的作为mysql的中间层
能很好的支持php
Nosql的共同的缺点:
没有统一的标准
安全性极差
没有正式的官方支持
各种产品还不成熟
权威支持的产品价格很高(如:阿里云),其实这个成本很多公司给得起,至少比设置多个读写分离的服务器成本是要低的.
Nosql-memcache
memcache是Livejournal的开发团队二次开发的产品(加入了内置的分布式算法),高性能的分布式内存缓存服务器.一般的使用目的是,通过缓存数据库查询结果,减少数据库访问次数,以提高动态Web应用的速度,提高可扩展性.
memcache的优点:
1.纯内存的储存机制,因此它是所有Nosql产品中最简单也是速度最快的,但是同时功能也是最弱的
2.内置分布式算法,使得开发者不需要自己去实现
3.他能把单项数据的数据缓存过期时间设置为30天,也能使得单项数据常驻内存当中
4.完美支持php的调用
memcache的缺点:
1.由于memcache使用telnet协议进行传输,没有数据加密功能,所以安全性很差
2.memcache最大的内存存储空间(吞吐量)只有64M,如果64M一旦爆满,memcache会指定重启,并释放当前所有的内存,里面的数据就丢失掉.
3.由于memcache把数据储存在内存中.所以服务器进行维护或者重启,那么数据就会丢失.
4.数据零散,无法遍历,管理数据完整性非常一般
memcache的使用注意事项:
1.不要把安全性,敏感性,具有明文过高的数据放到memcache当中
2.使用数据时候要注意压缩,尽量使用一些小型的数据进行储存(产品分类,文章栏目,用户登录信息,计数器的结果,用户属性)
memcache的存储格式:key-value(键值对的存储方式)
memcache在国内职场中的使用场景:

PHP+Memcache+Mysql的架构图

当前方式的客户端(用户浏览器)发起请求,这时这种架构的请求方式,我们称之为非实时请求,那么每一次的请求必须通过中间的缓存层面进行,如果缓存中有数据,那么数据库就不会做出任何的响应,,如果没有缓存数据,数据库就只会响应一次,并把响应的结果放到内存中等待用户的下一次请求.
memcache的安装
安装包包括:1.memcache的rpm包,用于实现memcache服务器安装 2.telnet的rpm包安装,这个包用于客户端连接服务器 3.telnet-server的rpm包,用于telnet客户端的启动
安装说明:安装memcache,这三个包必须一起安装,而不能分开安装,否则它们的依赖关系需要自己解决
使用yum进行memcache的安装,安装命令:yum -y install memcache telnet telnet-server
使用putty 执行命令安装过程如下:
第一步:打开putty输入linux服务器地址:

第二步:输入用户名和密码进行登录:

第三步:登录完成后输入yum命令yum -y install memcache telnet telnet-server

注意:这里为什么使用putty而不使用Xshell呢,因为xshell操作memcache不能退格不能清屏,putty可以退格
启动memcache的服务器
在memcache服务器中,如果希望能正常的启动memcache,并且可以在客户端正常连接memcache服务器,name需要启动memcached和xinetd的服务器
memcached的说明:memcached是memcache服务器的守护进程,负责memcache服务器的启动,重启,关闭和状态的监控.其管理命令如下:
#启动memcache服务器:service memcache start
#重启memcache服务器:service memcahce restart
#停止memcache服务器:service memcache stop
#查看守护进程: service memcache status
#把memcache加入开机脚本:chkconfig memcahched on
注意:如果重启或者停止memcache服务器,那么memcache中存储的数据会马上丢失,无法恢复.
说明:xinetd是telnet服务器的守护进程,负责telnet客户端可以正常连接memcache服务器,默认下占据11211端口
#启动telnet服务器:service xinetd start
#重启telnet服务器:service xinetd restart
#停止telnet服务器:service xinetd stop
#查看守护进程的状态:service xinetd status
#把xinetd加入开机脚本: chkconfig xinetd on
注意:xinetd重启或者停止不会导致memcache的数据丢失,但客户端无法连接memcache服务器.所以如果想维护memcache服务器,那么可以停止telnet服务器
使用telnet连接memcache
首先,要保证telnet和memcache处于启动状态,并且默认端口为11211
第一步:如果没有启动xinetd和memcached需要启动,命令为,service memcache start和service xinetd start

第二步:使用telnet客户端进行memcache服务器的连接
命令格式:telnet [mamcache的服务器] [端口]

注意:如果刚打开telnet客户端敲入回车键,那么会出现ERROR,这时并不是代表连接失败,而是因为memcache服务器在等待您输入正确的指令,而回车并不是一个正确的指令,所以它会报出ERROR的错误.
memcache的get,add,set,delete命令
1.get命令:
这个命令用于获取memcache内存中的数据,命令格式:get[键名(key)]
比如:如果希望获取一个为name的键名,可以使用命令:get name
命令效果如下图所示:

如果存在键名则能获取数据,如下图所示:

get name: 代表获取key位name的值
VALUE name 1 3:代表key为name的键值的说明,其中1代表标识符,3代表字节的大小
2.add命令:
这个命令就是向memcache的内存中的某一个值添加数据,然而它在显示开发中很少用,一般我们会用set直接取代它的操作,所以这个命令只需要了解.
命令格式:add 键名 标识符 过期时间 字节大小
说明:
标识符:一般只会填入1,也可以天999,随便乱填但是不可填负数和0,也不可以是中文和特殊字符,只能是正整数.
过期时间:0代表永远不过期,其余请求就是以秒为单位,如设为:30,代表30秒后过期.最大秒数可以设置为:30*86400=30天
字节大小:就是打算添加的数据有多大,如:设为3,代表输入3个字节.
使用add命令一个键名为name的数据,键值为php
命令的运行效果如下图所示:

add name 1 0 3:代表输入一个名为name的键名,3个字节的大小,永不过期
php:代表name键名中的键值为php
STORED:代表成功写入name键名中
3.set命令:
这个命令在开发过程中使用率有100%,他作用很特别,如果一个键名已经存在,那么set命令会修改此键名的值,如果此键名不存在就会创建此键名,所以set既可以修改又可以添加,因此add的意义就不大了,因为add只能添加.
命令格式:set 键名 标识符 过期时间 字节大小
说明:
标识符:一般只会填入1
过期时间:0代表永不过期,其他数字代表对应秒数
字节大小:就是打算添加的数据有多大,例如3,代表3个字节
命令运行效果如下图:
1.用set修改一个已经存在的键名,如:name

set name 1 0 4:修改一个已经存在键名的四个字节永不过期的
java:修改name中的值
STORED:代表写入成功
2.用set添加一个不存在的键名,如:project

set project 1 0 6:添加不存在键名的project,其字节大小位6,永不过期
lovely:添加project中的值
STORED:代表写入成功
4.delete命令
这个命令就是删除memcache在内存中的值,如果把名删除了.对应的值也没了,所占据的空间大小也释放了
命令格式:delete 键名 (可以存在也可以不存在)

5.过期时间
memcache的过期时间一般用于add命令和set命令当中,过期时间以秒为单位,0代表永不过期,永不过期的数据会永远占据的内存空间,直接删除键名或者memcache重启时才会被释放,因此设置一个永不过期的键名要深吸熟虑,使用过期时间的设置,可以有效节省内存空间.一般设置过期时间,虽然理论上也可以使用add命令,然而由于set命令具备add命令的功能,且set命令本身具备修改的功能,因此我们在设置过期时间时,使用set命令的几率是最高的.
其命令格式:set 键名 标识符 过期时间 字节大小
其实这个命令的关键点就是过期时间的参数不能设置为0和小数点,必须为正整数.比如说:把一个为project2的键名的过期时间设置为20秒,可以使用以下方式:set project2 1 20 3,效果如下图所示:

6.set和add的注意事项
在memcache当中,默认的最大储存内存空间为64M,memcache对单个键名的存储的空间最大为1M,所以设置键名的时候,要合理分配字节大小,然后memcache分配字节大小是非常严格的,比如说,你分配一个3字节的键名,如果使用时超过了3个字节或者有时候不足3个字节那么memcache 就会报错.
1.设置一个为project3,字节大小为3,永不过期的键名,其值为java(超过3个字节),这时由于java是4个字节,超过3个字节,所以会报错,效果如下:

2.设置一个project4,字节大小为3,永不过期的键名.其值为ab(小于3个字节),这时由于ab的值是2个字节,小于3个字节的储存空间,实际上memcache就会报错,然而必须输入回车才能看到错误的提示,如下图:

但有时存储一个键名为lover其字节大小为8个字节,那么如下情况你感觉你输入的是4个字节,但其实是8个字节,这情况成为有时成功的情况:

所以我们尽量在设置memcahche的值之前,要先考虑好值占据空间的大小已免使用的时候出错或者大小占据过分的空间
思考:如果我希望把memcache当中所有的数据清除,释放掉内存,我们应该怎么做?
1.把linux服务器关机或者重启,然而这样会使服务器重启了,不可取.
2.把memcache直接 service memcache restart|stop ,然而这样的话我们现实中做的几率只有10%,因为重启memcache的服务会导致php或者telnet客户端失去连接,如果当前有用户在客户端正在操作memcache那么他们就会获取错误信息,用户体验极差,所以这样做其实很暴力很不人性化.
3.在memcache当中还有一个命令flush_all,意思是清除当前所有的内存缓存信息,执行flush_all的结果如下:
在没有执行flush_all之前可以获取lover和name2的值如下:

然后执行flush_all之后,结果如下所示:

再获取lover和name2,结果获取不了:

拓展:在memcache当中简述LRU的运行原理和策略原理
在memcache当中其实memcache除了分布式的算法之外,memcache还存在一种策略算法,叫做懒惰策略算法,这种算法需要配合一个叫stats的命令来理解.
首先,我们需要知道什么叫做懒惰策略?
举个生活中的小例子,如果妈妈买了5个苹果回家放在水果盘中,那么如果我们吃掉一个苹果就相当于在水果盘删除一个苹果,这时吃掉苹果是一种主动的删除方式.然而如果苹果不吃时间长了就会变质,在现实生活当中我们应该主动把烂掉的苹果扔掉,然而妈妈的孩子很懒惰,他之后要去吃苹果的时候,发现了它要吃的苹果烂了,这时孩子才会扔掉这个苹果,这时扔掉的一个苹果也是属于水果盘删除了一个苹果,然而如果有两个苹果或者两个以上的苹果过期变质,这个孩子依然只会扔掉他准备吃的那一个,而剩下的那些他依然不会去理会,这种就叫做懒惰策略删除,这个策略如果在生活中是不可取的,然而放到memcache当中是很具有效率的.
在memcache当中如果我们用set设置了一个key在20秒后过期,那么memcache其实过期之后并不能查找当前的这个key里面的值,然而这时你认为key 过期之后,memcache到底有没有删除这个key呢?这个答案是否定的,只要你不去get这个key那么这个key其实只是它的值消失了,但key依然会占据这个内存空间,这样的好处是如果你下次再设置一个相同的key,那么memcache不需要再开辟一个空间.这种就是memcache当中的懒惰策略删除,它这种删除是怎么实现的呢?memcache使用了一种算法叫LRU算法进行实现的,但是我们怎么来证明这个策略是存在的呢?这时就要配合一个叫stats命令来学习,stats命令是查看当前memcache的所有状态,执行命令结果如下所示:

现在创建一个key为itcast,值为szpgper的键值时,然后这个键值会在15秒后过期,代码如下:

这时查看stats会发觉curr_items中记录为1:

等待15秒后再查看stats会发觉curr_itrms中还是1:

相当于那个孩子没有把烂掉的苹果扔掉,因为他还没有去吃这个苹果也就是没有使用到get方法,因此LRU算法是不会删除curr_items的,这时如果我们去主动使用get方法,那么获取不到数据是很正常,然而这时stats会产生什么变化呢?

这时LRU就发现你主动的get了一次然而你要get的key已经过期所以这时LRU算法就会懒惰把你要get的key删除掉,然而你有多个key同时过期, 那么LRU也只会删除你get的那个key,因此我们回到curr_items的结果为0:

因此这种就是LRU懒惰策略算法的原理,在memcache当中过期不等与删除,过期之后只有主动去get那么才会被懒惰策略的LRU删除,这个目的是memcache下次设置重复的键值时开启一片新的空间,然而你主动使用delete或者重启memcache,那么curr_items就会不收LRU的控制,因为delete和重启属于主动行为,注意:flush_all不属于主动删除,因此flush_all之后,curr_items是受到LRU算法的控制的:

curr_items的结果:

浙公网安备 33010602011771号