memcached_memcachedb - CSDN
精华内容
参与话题
  • 一次性精通Memcached

    2019-12-16 10:30:28
    基础篇涵盖:什么是Memcached、缓存原理、使用方式,Memcached安装、多节点部署,完整缓存、热点缓存、session共享,Memcached操作指令详解,java客户端开发、Spring集成等等。 原理篇涵盖:分布式存储、...
  • Redis与Memcached的区别

    万次阅读 多人点赞 2015-09-29 10:42:30
    Redis与Memcached的区别 ... 实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的

    转载地址:http://gnucto.blog.51cto.com/3391516/998509


    Redis与Memcached的区别


    传统MySQL+ Memcached架构遇到的问题

      实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:

      1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。

      2.Memcached与MySQL数据库数据一致性问题。

      3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。

      4.跨机房cache同步问题。

      众多NoSQL百花齐放,如何选择

      最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题

      1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。

      2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。

      3.这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计,节点之间通过gossip方式传递集群信息,数据保证最终一致性,后者是一个中心化的方案设计,通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log,然后定期compat归并到磁盘上,将随机写优化为顺序写,提高写入性能。

      4.Schema free,auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的,直接存储json格式数据,并且支持auto-sharding等功能,比如mongodb。

      面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。

      Redis适用场景,如何正确的使用

      前面已经分析过,Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?

     

    如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:

    1  Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。

    2  Redis支持数据的备份,即master-slave模式的数据备份。

    3  Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。

    抛开这些,可以深入到Redis内部构造去观察更加本质的区别,理解Redis的设计。

    在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的 key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计 算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以 保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存 中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个 操作,直到子线程完成swap操作后才可以进行修改。

    使用Redis特有内存模型前后的情况对比:
    VM off: 300k keys, 4096 bytes values: 1.3G used
    VM on:  300k keys, 4096 bytes values: 73M used
    VM off: 1 million keys, 256 bytes values: 430.12M used
    VM on:  1 million keys, 256 bytes values: 160.09M used
    VM on:  1 million keys, values as large as you want, still: 160.09M used

    当 从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行 批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程 池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。

    如果希望在海量数据的环境中使用好Redis,我相信理解Redis的内存设计和阻塞的情况是不可缺少的。

     

    补充的知识点:

    memcached和redis的比较

    1 网络IO模型

      Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO, 网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如,Memcached最常用的stats 命令,实际Memcached所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。

    (Memcached网络IO模型)

      Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll、kqueue和select,对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。

      2.内存管理方面

      Memcached使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除,原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/

      Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,导致swap也不会剔除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。

      3.数据一致性问题

      Memcached提供了cas命令,可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。

      4.存储方式及其它方面

      Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能

      Redis除key/value之外,还支持list,set,sorted set,hash等众多数据结构,提供了KEYS

      进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其dump文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。

      5.关于不同语言的客户端支持

      在不同语言的客户端方面,Memcached和Redis都有丰富的第三方客户端可供选择,不过因为Memcached发展的时间更久一些,目前看在客户端支持方面,Memcached的很多客户端更加成熟稳定,而Redis由于其协议本身就比Memcached复杂,加上作者不断增加新的功能等,对应第三方客户端跟进速度可能会赶不上,有时可能需要自己在第三方客户端基础上做些修改才能更好的使用。

      根据以上比较不难看出,当我们不希望数据被踢出,或者需要除key/value之外的更多数据类型时,或者需要落地功能时,使用Redis比使用Memcached更合适。

      关于Redis的一些周边功能

      Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,对于此类功能需要了解其实现原理,清楚地了解到它的局限性后,才能正确的使用,比如pubsub功能,这个实际是没有任何持久化支持的,消费方连接闪断或重连之间过来的消息是会全部丢失的,又比如聚合计算和scripting等功能受Redis单线程模型所限,是不可能达到很高的吞吐量的,需要谨慎使用。

      总的来说Redis作者是一位非常勤奋的开发者,可以经常看到作者在尝试着各种不同的新鲜想法和思路,针对这些方面的功能就要求我们需要深入了解后再使用。

      总结:

      1.Redis使用最佳方式是全部数据in-memory。

      2.Redis更多场景是作为Memcached的替代者来使用。

      3.当需要除key/value之外的更多数据类型支持时,使用Redis更合适。

      4.当存储的数据不能被剔除时,使用Redis更合适。




                                                                                                                          谈谈Memcached与Redis(一)

     

     1. Memcached简介

    Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器。其本质上就是一个内存key-value数据库,但是不支持数据的持久化,服务器关闭之后数据全部丢失。Memcached使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上,只要安装了libevent即可使用。在Windows下,它也有一个可用的非官方版本(http://code.jellycan.com/memcached/)。Memcached的客户端软件实现非常多,包括C/C++, PHP, Java, Python, Ruby, Perl, Erlang, Lua等。当前Memcached使用广泛,除了LiveJournal以外还有Wikipedia、Flickr、Twitter、Youtube和WordPress等。
    在Window系统下,Memcached的安装非常方便,只需从以上给出的地址下载可执行软件然后运行memcached.exe –d install即可完成安装。在Linux等系统下,我们首先需要安装libevent,然后从获取源码,make && make install即可。默认情况下,Memcached的服务器启动程序会安装到/usr/local/bin目录下。在启动Memcached时,我们可以为其配置不同的启动参数。
    1.1 Memcache配置
    Memcached服务器在启动时需要对关键的参数进行配置,下面我们就看一看Memcached在启动时需要设定哪些关键参数以及这些参数的作用。
    1)-p <num> Memcached的TCP监听端口,缺省配置为11211;
    2)-U <num> Memcached的UDP监听端口,缺省配置为11211,为0时表示关闭UDP监听;
    3)-s <file> Memcached监听的UNIX套接字路径;
    4)-a <mask> 访问UNIX套接字的八进制掩码,缺省配置为0700;
    5)-l <addr> 监听的服务器IP地址,默认为所有网卡;
    6)-d 为Memcached服务器启动守护进程;
    7)-r 最大core文件大小;
    8)-u <username> 运行Memcached的用户,如果当前为root的话需要使用此参数指定用户;
    9)-m <num> 分配给Memcached使用的内存数量,单位是MB;
    10)-M 指示Memcached在内存用光的时候返回错误而不是使用LRU算法移除数据记录;
    11)-c <num> 最大并发连数,缺省配置为1024;
    12)-v –vv –vvv 设定服务器端打印的消息的详细程度,其中-v仅打印错误和警告信息,-vv在-v的基础上还会打印客户端的命令和相应,-vvv在-vv的基础上还会打印内存状态转换信息;
    13)-f <factor> 用于设置chunk大小的递增因子;
    14)-n <bytes> 最小的chunk大小,缺省配置为48个字节;
    15)-t <num> Memcached服务器使用的线程数,缺省配置为4个;
    16)-L 尝试使用大内存页;
    17)-R 每个事件的最大请求数,缺省配置为20个;
    18)-C 禁用CAS,CAS模式会带来8个字节的冗余;
    2. Redis简介
    Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。Redis使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上无需任何外部依赖就可以使用。Redis支持的客户端语言也非常丰富,常用的计算机语言如C、C#、C++、Object-C、PHP、Python、Java、Perl、Lua、Erlang等均有可用的客户端来访问Redis服务器。当前Redis的应用已经非常广泛,国内像新浪、淘宝,国外像Flickr、Github等均在使用Redis的缓存服务。
    Redis的安装非常方便,只需从http://redis.io/download获取源码,然后make && make install即可。默认情况下,Redis的服务器启动程序和客户端程序会安装到/usr/local/bin目录下。在启动Redis服务器时,我们需要为其指定一个配置文件,缺省情况下配置文件在Redis的源码目录下,文件名为redis.conf。
    2.1 Redis配置文件
    为了对Redis的系统实现有一个直接的认识,我们首先来看一下Redis的配置文件中定义了哪些主要参数以及这些参数的作用。
    1)daemonize no 默认情况下,redis不是在后台运行的。如果需要在后台运行,把该项的值更改为yes;
    2)pidfile /var/run/redis.pid当Redis在后台运行的时候,Redis默认会把pid文件放在/var/run/redis.pid,你可以配置到其他地址。当运行多个redis服务时,需要指定不同的pid文件和端口;
    3)port 6379指定redis运行的端口,默认是6379;
    4)bind 127.0.0.1 指定redis只接收来自于该IP地址的请求,如果不进行设置,那么将处理所有请求。在生产环境中最好设置该项;
    5)loglevel debug 指定日志记录级别,其中Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose。debug表示记录很多信息,用于开发和测试。verbose表示记录有用的信息,但不像debug会记录那么多。notice表示普通的verbose,常用于生产环境。warning 表示只有非常重要或者严重的信息会记录到日志;
    6)logfile /var/log/redis/redis.log 配置log文件地址,默认值为stdout。若后台模式会输出到/dev/null;
    7)databases 16 可用数据库数,默认值为16,默认数据库为0,数据库范围在0-(database-1)之间;
    8)save 900 1保存数据到磁盘,格式为save <seconds> <changes>,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件rdb。相当于条件触发抓取快照,这个可以多个条件配合。save 900 1就表示900秒内至少有1个key被改变就保存数据到磁盘;
    9)rdbcompression yes 存储至本地数据库时(持久化到rdb文件)是否压缩数据,默认为yes;
    10)dbfilename dump.rdb本地持久化数据库文件名,默认值为dump.rdb;
    11)dir ./ 工作目录,数据库镜像备份的文件放置的路径。这里的路径跟文件名要分开配置是因为redis在进行备份时,先会将当前数据库的状态写入到一个临时文件中,等备份完成时,再把该临时文件替换为上面所指定的文件。而这里的临时文件和上面所配置的备份文件都会放在这个指定的路径当中,AOF文件也会存放在这个目录下面。注意这里必须指定一个目录而不是文件;
    12)slaveof <masterip> <masterport> 主从复制,设置该数据库为其他数据库的从数据库。设置当本机为slave服务时,设置master服务的IP地址及端口。在Redis启动时,它会自动从master进行数据同步;
    13)masterauth <master-password> 当master服务设置了密码保护时(用requirepass制定的密码)slave服务连接master的密码;
    14)slave-serve-stale-data yes 当从库同主机失去连接或者复制正在进行,从机库有两种运行方式:如果slave-serve-stale-data设置为yes(默认设置),从库会继续相应客户端的请求。如果slave-serve-stale-data是指为no,除去INFO和SLAVOF命令之外的任何请求都会返回一个错误"SYNC with master in progress";
    15)repl-ping-slave-period 10从库会按照一个时间间隔向主库发送PING,可以通过repl-ping-slave-period设置这个时间间隔,默认是10秒;
    16)repl-timeout 60 设置主库批量数据传输时间或者ping回复时间间隔,默认值是60秒,一定要确保repl-timeout大于repl-ping-slave-period;
    17)requirepass foobared 设置客户端连接后进行任何其他指定前需要使用的密码。因为redis速度相当快,所以在一台比较好的服务器下,一个外部的用户可以在一秒钟进行150K次的密码尝试,这意味着你需要指定非常强大的密码来防止暴力破解;
    18)rename-command CONFIG "" 命令重命名,在一个共享环境下可以重命名相对危险的命令,比如把CONFIG重名为一个不容易猜测的字符:# rename-command CONFIG b840fc02d524045429941cc15f59e41cb7be6c52。如果想删除一个命令,直接把它重命名为一个空字符""即可:rename-command CONFIG "";
    19)maxclients 128设置同一时间最大客户端连接数,默认无限制。Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数。如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息;
    20)maxmemory <bytes> 指定Redis最大内存限制。Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,Redis同时也会移除空的list对象。当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。注意:Redis新的vm机制,会把Key存放内存,Value会存放在swap区;
    21)maxmemory-policy volatile-lru 当内存达到最大值的时候Redis会选择删除哪些数据呢?有五种方式可供选择:volatile-lru代表利用LRU算法移除设置过过期时间的key (LRU:最近使用 Least Recently Used ),allkeys-lru代表利用LRU算法移除任何key,volatile-random代表移除设置过过期时间的随机key,allkeys_random代表移除一个随机的key,volatile-ttl代表移除即将过期的key(minor TTL),noeviction代表不移除任何key,只是返回一个写错误。
    注意:对于上面的策略,如果没有合适的key可以移除,写的时候Redis会返回一个错误;
    22)appendonly no 默认情况下,redis会在后台异步的把数据库镜像备份到磁盘,但是该备份是非常耗时的,而且备份也不能很频繁。如果发生诸如拉闸限电、拔插头等状况,那么将造成比较大范围的数据丢失,所以redis提供了另外一种更加高效的数据库备份及灾难恢复方式。开启append only模式之后,redis会把所接收到的每一次写操作请求都追加到appendonly.aof文件中。当redis重新启动时,会从该文件恢复出之前的状态,但是这样会造成appendonly.aof文件过大,所以redis还支持了BGREWRITEAOF指令对appendonly.aof 进行重新整理,你可以同时开启asynchronous dumps 和 AOF;
    23)appendfilename appendonly.aof  AOF文件名称,默认为"appendonly.aof";
    24)appendfsync everysec  Redis支持三种同步AOF文件的策略: no代表不进行同步,系统去操作,always代表每次有写操作都进行同步,everysec代表对写操作进行累积,每秒同步一次,默认是"everysec",按照速度和安全折中这是最好的。
    25)slowlog-log-slower-than 10000 记录超过特定执行时间的命令。执行时间不包括I/O计算,比如连接客户端,返回结果等,只是命令执行时间。可以通过两个参数设置slow log:一个是告诉Redis执行超过多少时间被记录的参数slowlog-log-slower-than(微妙),另一个是slow log 的长度。当一个新命令被记录的时候最早的命令将被从队列中移除,下面的时间以微妙微单位,因此1000000代表一分钟。注意制定一个负数将关闭慢日志,而设置为0将强制每个命令都会记录;
    26)hash-max-zipmap-entries 512 && hash-max-zipmap-value 64 当hash中包含超过指定元素个数并且最大的元素没有超过临界时,hash将以一种特殊的编码方式(大大减少内存使用)来存储,这里可以设置这两个临界值。Redis Hash对应Value内部实际就是一个HashMap,实际这里会有2种不同实现。这个Hash的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,对应的value redisObject的encoding为zipmap。当成员数量增大时会自动转成真正的HashMap,此时encoding为ht;
    27)list-max-ziplist-entries 512 list数据类型多少节点以下会采用去指针的紧凑存储格式;
    28)list-max-ziplist-value 64数据类型节点值大小小于多少字节会采用紧凑存储格式;
    29)set-max-intset-entries 512 set数据类型内部数据如果全部是数值型,且包含多少节点以下会采用紧凑格式存储;
    30)zset-max-ziplist-entries 128 zsort数据类型多少节点以下会采用去指针的紧凑存储格式;
    31)zset-max-ziplist-value 64 zsort数据类型节点值大小小于多少字节会采用紧凑存储格式。
    32)activerehashing yes Redis将在每100毫秒时使用1毫秒的CPU时间来对redis的hash表进行重新hash,可以降低内存的使用。当你的使用场景中,有非常严格的实时性需要,不能够接受Redis时不时的对请求有2毫秒的延迟的话,把这项配置为no。如果没有这么严格的实时性要求,可以设置为yes,以便能够尽可能快的释放内存;


    2.2 Redis的常用数据类型

    与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。在具体描述这几种数据类型之前,我们先通过一张图来了解下Redis内部内存管理中是如何描述这些不同数据类型的。
    图1 Redis对象
    Redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如图1所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。通过Figure1我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给Redis不同数据类型提供一个统一的管理接口,实际作者也提供了多种方法帮助我们尽量节省内存使用。下面我们先来逐一的分析下这五种数据类型的使用和内部实现方式。
    1)String
    常用命令:set/get/decr/incr/mget等;
    应用场景:String是最常用的一种数据类型,普通的key/value存储都可以归为此类;
    实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
    2)Hash
    常用命令:hget/hset/hgetall等
    应用场景:我们要存储一个用户信息对象数据,其中包括用户ID、用户姓名、年龄和生日,通过用户ID我们希望获取该用户的姓名或者年龄或者生日;
    实现方式:Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。如图2所示,Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据。当前HashMap的实现有两种方式:当HashMap的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,这时对应的value的redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
    图2 Redis的Hash数据类型
    3)List
    常用命令:lpush/rpush/lpop/rpop/lrange等;
    应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现;
    实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。
    4)Set
    常用命令:sadd/spop/smembers/sunion等;
    应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;
    实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。
    5)Sorted Set
    常用命令:zadd/zrange/zrem/zcard等;
    应用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
    实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
    2.3 Redis的持久化
    Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。我们会在下文分别介绍这两种不同的持久化策略。
    2.3.1 Redis的AOF日志
    Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。
    我们可以通过Redis的save指令来配置RDB快照生成的时机,比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。
    Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。
    但是,我们可以很明显的看到,RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制:AOF日志。
    2.3.2 Redis的AOF日志
    AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。当然,并不是发送发Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件。那么每一条修改数据的命令都生成一条日志,那么AOF文件是不是会很大?答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。
    AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的5个流程。那么写AOF的操作安全性又有多高呢。实际上这是可以设置的,在Redis中对AOF调用write(2)写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面appendfsync的三个设置项,安全强度逐渐变强。
    1)appendfsync no
    当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
    2)appendfsync everysec
    当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
    3)appednfsync always
    当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。


    3. Memcached和Redis关键技术对比

    作为内存数据缓冲系统,Memcached和Redis均具有很高的性能,但是两者在关键实现技术上具有很大差异,这种差异决定了两者具有不同的特点和不同的适用条件。下面我们会对两者的关键技术进行一些对比,以此来揭示两者的差异。
    3.1 Memcached和Redis的内存管理机制对比
    对于像Redis和Memcached这种基于内存的数据库系统来说,内存管理的效率高低是影响系统性能的关键因素。传统C语言中的malloc/free函数是最常用的分配和释放内存的方法,但是这种方法存在着很大的缺陷:首先,对于开发人员来说不匹配的malloc和free容易造成内存泄露;其次,频繁调用会造成大量内存碎片无法回收重新利用,降低内存利用率;最后,作为系统调用,其系统开销远远大于一般函数调用。所以,为了提高内存的管理效率,高效的内存管理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理机制,但是实现方法存在很大的差异,下面将会对两者的内存管理机制分别进行介绍。
    3.1.1 Memcached的内存管理机制
    Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。Slab Allocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在Slab Allocation系统里,而Memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响
    Slab Allocation的原理相当简单。 如图3所示,它首先从操作系统申请一大块内存,并将其分割成各种尺寸的块Chunk,并把尺寸相同的块分成组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每个Slab Class的大小,可以在Memcached启动的时候通过制定Growth Factor来控制。假定Figure 1中Growth Factor的取值为1.25,所以如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推。
    图3 Memcached内存管理架构
    当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图 4所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。

    图4 Memcached的存储空间浪费
    3.1.2 Redis的内存管理机制
    Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存块的头部。如图 5所示,real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的算出real_ptr的值,然后将real_ptr传给free释放内存。
    图5 Redis块分配
    Redis通过定义一个数组来记录所有的内存分配情况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每一个元素代表当前程序所分配的内存块的个数,且内存块的大小为该元素的下标。在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。所以,总的来看,Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。


    3.2 Redis和Memcached的集群实现机制对比

    Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。
    3.2.1 Memcached的分布式存储
    Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。图6 给出了Memcached的分布式存储实现架构。当客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后数据会直接发送到该节点上存储。但客户端查询数据时,同样要计算出查询数据所在的节点,然后直接向该节点发送查询请求以获取数据。
    图6 Memcached客户端分布式存储实现
    3.2.2 Redis的分布式存储
    相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。尽管Redis当前已经发布的稳定版本还没有添加分布式存储功能,但Redis开发版中已经具备了Redis Cluster的基本功能。预计在2.6版本之后,Redis就会发布完全支持分布式的稳定版本,时间不晚于2012年底。下面我们会根据开发版中的实现,简单介绍一下Redis Cluster的核心思想。
    Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,具有线性可伸缩的功能。图7给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个key的数值域分成4096个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。
     
    图7 Redis分布式架构
    为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。如图4所示,在Redis Cluster中,每个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会导致数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。
    图8 Redis Cluster中的Master节点和Slave节点
    3.3 Redis和Memcached整体对比
    Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较,总体来看还是比较客观的,现总结如下:
    1)性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。
    2)内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。
    3)Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。


    展开全文
  • MemCached详解

    千次阅读 2012-04-17 21:01:40
    首先,我们来了解一下MemCached与MemCache之间的区别: Memcache是什么? Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统。用于加速动态web应用程序,减轻数据库负载。 它可以应对任意多个连接...

    首先,我们来了解一下MemCached与MemCache之间的区别:

    Memcache是什么?

    Memcache是一个自由和开放源代码、高性能、分配的内存对象缓存系统。用于加速动态web应用程序,减轻数据库负载。

    它可以应对任意多个连接,使用非阻塞的网络IO。由于它的工作机制是在内存中开辟一块空间,然后建立一个HashTable,Memcached自管理这 些HashTable。

    Memcached又是什么?

    Memcached是Memcache系统的主程序文件,以守护程序方式运行于一个或多个服务器中,随时接受客 户端的连接操作,使用共享内存存取数据。

    那PHP中的Memcache是什么?php中的所讲的memcache是用于连接Memecached的php支持扩展之一(可用phpinfo查看),类似mbstring,eAccelerator。

    简单的说

    Memcache是总的缓存系统项目名称,容易和PHP中的Memcache混淆。

    我们常提到Memcache其实是PHP中的Memcache,即PHP的Memcached扩展支持。

    我们常提到Memcached是服务端主程序文件,服务端安装程序。

    为了让你的程序飞起来,必须安装memcached服务端程序和PHP的Memcached扩展,所以如果您要使用Memcache来缓存系统,memcache和memcached两样我们都需要安装。

    接下来,我们来了解一下Memcached有关的知识点:

    Memcached是danga.com(运营LiveJournal的技术团队)开发的一套分布式内存对象缓存系统,用于在动态系统中减少数据库 负载,提升性能。

    它所具有的特点有:

    协议简单 基于libevent的事件处理 内置内存存储方式 memcached不互相通信的分布式

    Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。

    Memcached有两个核心组件组成:服务端(ms)和客户端(mc),在一个memcached的查询中,mc先通过计算key的hash值来 确定kv对所处在的ms位置。当ms确定后,客户端就会发送一个查询请求给对应的ms,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以 memcached交互带给网络的影响是最小化的。

    内存分配

    默认情况下,ms是用一个内置的叫“块分配器”的组件来分配内存的。舍弃c++标准的malloc/free的内存分配,而采用块分配器的主要目的 是为了避免内存碎片,否则操作系统要花费更多时间来查找这些逻辑上连续的内存块(实际上是断开的)。用了块分配器,ms会轮流的对内存进行大块的分配,并 不断重用。当然由于块的大小各不相同,当数据大小和块大小不太相符的情况下,还是有可能导致内存的浪费。

    同时,ms对key和data都有相应的限制,key的长度不能超过250字节,data也不能超过块大小的限制 --- 1MB。
    因为mc所使用的hash算法,并不会考虑到每个ms的内存大小。理论上mc会分配概率上等量的kv对给每个ms,这样如果每个ms的内存都不太一样,那 可能会导致内存使用率的降低。所以一种替代的解决方案是,根据每个ms的内存大小,找出他们的最大公约数,然后在每个ms上开n个容量=最大公约数的 instance,这样就等于拥有了多个容量大小一样的子ms,从而提供整体的内存使用率。

    缓存策略

    当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。

    同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。

    缓存数据库查询

    现在memcached最流行的一种使用方式是缓存数据库查询,下面举一个简单例子说明:

    App需要得到userid=xxx的用户信息,对应的查询语句类似:

    “SELECT * FROM users WHERE userid = xxx”

    App先去问cache,有没有“user:userid”(key定义可预先定义约束好)的数据,如果有,返回数据;如果没有,App会从数据库中读取数据,并调用cache的add函数,把数据加入cache中。

    当取的数据需要更新,app会调用cache的update函数,来保持数据库与cache的数据同步。

    从上面的例子我们也可以发现,一旦数据库的数据发现变化,我们一定要及时更新cache中的数据,来保证app读到的是同步的正确数据。当然我们可 以通过定时器方式记录下cache中数据的失效时间,时间一过就会激发事件对cache进行更新,但这之间总会有时间上的延迟,导致app可能从 cache读到脏数据,这也被称为狗洞问题。(以后我会专门描述研究这个问题)

    数据冗余与故障预防

    从设计角度上,memcached是没有数据冗余环节的,它本身就是一个大规模的高性能cache层,加入数据冗余所能带来的只有设计的复杂性和提高系统的开支。

    当一个ms上丢失了数据之后,app还是可以从数据库中取得数据。不过更谨慎的做法是在某些ms不能正常工作时,提供额外的ms来支持cache,这样就不会因为app从cache中取不到数据而一下子给数据库带来过大的负载。

    同时为了减少某台ms故障所带来的影响,可以使用“热备份”方案,就是用一台新的ms来取代有问题的ms,当然新的ms还是要用原来ms的IP地址,大不了数据重新装载一遍。

    另外一种方式,就是提高你ms的节点数,然后mc会实时侦查每个节点的状态,如果发现某个节点长时间没有响应,就会从mc的可用server列表里 删除,并对server节点进行重新hash定位。当然这样也会造成的问题是,原本key存储在B上,变成存储在C上了。所以此方案本身也有其弱点,最好 能和“热备份”方案结合使用,就可以使故障造成的影响最小化。

    Memcached客户端(mc)

    Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等,具体可参见memcached api page [2]。
    大家可以根据自己项目的需要,选择合适的客户端来集成。

    缓存式的WEB应用程序架构

    有了缓存的支持,我们可以在传统的app层和db层之间加入cache层,每个app服务器都可以绑定一个mc,每次数据的读取都可以从ms中取得,如果 没有,再从db层读取。而当数据要进行更新时,除了要发送update的sql给db层,同时也要将更新的数据发给mc,让mc去更新ms中的数据。

    性能测试

    Memcached 写速度
    平均速度: 16222 次/秒
    最大速度 18799 次/秒

    Memcached 读速度
    平均速度: 20971 次/秒
    最大速度 22497 次/秒

    Memcachedb 写速度
    平均速度: 8958 次/秒
    最大速度 10480 次/秒

    Memcachedb 读速度
    平均速度: 6871 次/秒
    最大速度 12542 次/秒
    Memcached客户端(mc)的使用方法

    创建memcached.xml文件:

    <?xml version="1.0" encoding="UTF-8"?>
    <memcached>
       
        <client name="mclient0" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool0">
            <errorHandler>com.moit.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
        </client>
       
        <client name="mclient1" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool1">
            <errorHandler>com.moit.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
        </client>
       
        <client name="mclient2" compressEnable="true" defaultEncoding="UTF-8" socketpool="pool2">
            <errorHandler>com.moit.xplatform.asf.cache.memcached.MemcachedErrorHandler</errorHandler>
        </client>
       
        <socketpool name="pool0" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
    	<!--MS的服务器地址-->
            <servers>192.168.3.251:11211,192.168.3.251:11211</servers>
        </socketpool>
       
        <socketpool name="pool1" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.3.251:11211,192.168.3.251:11211</servers>
        </socketpool>
       
        <socketpool name="pool2" failover="true" initConn="5" minConn="5" maxConn="250" maintSleep="0"
            nagle="false" socketTO="3000" aliveCheck="true">
            <servers>192.168.3.251:11211,192.168.3.251:11211</servers>
        </socketpool>
        <cluster name="cluster1">
            <memCachedClients>mclient1,mclient2</memCachedClients>
        </cluster>
    </memcached>
    //用containsKey方法判断cache服务器按指定的key值是否存在。
    System.out.println("是否包含了key的数据="+cache.containsKey("key"));
    if(cache.containsKey("key"))
    {
        System.out.println("包含了key的数据");
        System.out.println("从cache服务器获得key值");
    }
    else
    {
        System.out.println("没有包含了key的数据");
        System.out.println("cache服务器,没有数据,则去取数据库数据!");
    }

    例子如下:

    static ICacheManager<IMemcachedCache> manager;

    public String memcache()
    {
        manager = CacheUtil.getCacheManager(IMemcachedCache.class,
        MemcachedCacheManager.class.getName());
        manager.start();
        try{
           //"mclient0"为配置文件中client标签中的名字
           IMemcachedCache cache = manager.getCache("mclient0");
           //根据key得到缓存数据
            String a =(String)cache.get("key");
           //用containsKey方法判断cache服务器按指定的key值是否存在。
            System.out.println("是否包含了key的数据="+cache.containsKey("key"));
           if(cache.containsKey("key"))
           {
            System.out.println("包含了key的数据");
            System.out.println("从cache服务器获得key值");
           }
           else
           {
            System.out.println("没有包含了key的数据");
            System.out.println("cache服务器,没有数据,则去取数据库数据!");
           }
           //根据key删除服务器上的对应的缓存数据
            cache.remove("key");
           //根据key保存数据到服务器上
            cache.put("key", "你好!");
           //设置带有过期时间的例子
            //过30分钟
            Calendar calendar = Calendar.getInstance();//当前日期
            calendar.setTime(new Date());
            calendar.add(Calendar.MINUTE, 30);//
            cache.remove("keytime");
            cache.put("keytime", "30分钟后过期",calendar.getTime());
            System.out.println("30分钟后过期=keytime="+cache.get("keytime"));
            System.out.println("cache服务器getTime="+calendar.getTime());  
      
       }finally{ manager.stop();}
         //jsp 使用请参考test.jsp文件
         return "testmempage";
    }

    安装memcache

    # cd /usr/local/src
    # wget http://pecl.php.net/get/memcache-2.2.5.tgz
    # gzip -d memcache-2.2.5.tgz
    # tar xvf memcache-2.2.5.tar
    # cd memcache-2.2.5

    以下几句,是以php所在目录为/usr/local/php为例,如果您的php有变化,请自行替换几句中/usr/local/php的部分

    # /usr/local/php/bin/phpize
    # ./configure --enable-memcache --with-php-config=/usr/local/php/bin/php-config --with-zlib-dir
    # make && make install

    将memcache加入php扩展

    # vi /etc/php.ini(/etc/php.ini地址为我的php.ini位置,如果你不知道你的php.ini在哪里,可以用# find / -name php.ini进行查找,或者传个探针phpinfo,找到Configuration File (php.ini) Path)中php.ini的位置.

    末尾加入

    按键盘上的 i 开始编辑

    CTRL+F翻页拉到最下面在[Zend]之前加入

    extension_dir = "/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/"
    extension=memcache.so

    按Esc键,再输入

    :wq

    保存退出

    重启你的web服务器,比如apache

    /etc/init.d/httpd restart

    下面刷新下PHP探针,看下是不是有这个了,有的话就是装好了

    memcache
    Version 2.2.5memcache
    Version 2.2.5

    下面安装memcached

    装memcached首先需要安装安装libevent

    如果是centos可以yum安装

    # yum install libevent-devel

    如果不支持yum的系统,可以这样装libevent

    # cd /usr/local/src
    # wget http://www.monkey.org/~provos/libevent-1.4.12-stable.tar.gz
    # tar vxf libevent-1.4.12-stable.tar.gz
    # cd libevent-1.4.12
    # ./configure --prefix=/usr/local/libevent
    # make && make install

    接续安装memcached

    # cd /usr/local/src
    # wget http://cloud.github.com/downloads/saberma/saberma.github.com/memcached-1.4.4.tar.gz
    # tar vxf memcached-1.4.4.tar.gz
    # cd memcached-1.4.4
    # ./configure --prefix=/usr/local/memcached
    # make && make install

    安装完后启动memcached并分配32m内存(32为使用内存数,可按自身情况修改)

    /usr/local/memcached/bin/memcached -d -m 32 -l 127.0.0.1 -p 11211 -u root

    将memcached加入启动项

    # vi /etc/rc.d/rc.local

    按键盘上的 i 开始编辑

    在最后加入

    /usr/local/memcached/bin/memcached -d -m 32 -l 127.0.0.1 -p 11211 -u root

    按Esc键,再输入

    :wq

    保存退出

    如果需要,可以reboot一下,不过不用reboot应该已经生效~

    加速效果测试

    用没有什么负载的Discuz X1做个测试,未启用时

    GMT+8, 2010-9-12 09:08, Processed in 0.038893 second(s), 2 queries.

    缓存启用后的效果,不过总体感觉VPS上效果不如用eAccelerato缓存加入效果那么明显

    GMT+8, 2010-9-12 09:08, Processed in 0.008383 second(s), 2 queries, Memcache On.

    大功告成,打完收工!~~

    参考资源:

    http://www.chinaz.com/web/2010/0916/133310.shtml

    http://www.cnblogs.com/mandela/archive/2011/08/08/2131339.html
    http://sebug.net/paper/databases/nosql/Nosql.html

    http://blog.sina.com.cn/s/blog_6cabf4070100pccn.html
    展开全文
  • Memcached 基础知识

    千次阅读 2014-10-22 17:42:01
    1. 基本信息  memcached是高性能的分布式内存缓存服务器,

    1. 基本信息 

    memcached是一个高性能的内存缓存对象系统,其实质为一个键值对的hashmap.其事件处理和网络通信均是基于libevent.

    基本特征:

    协议简单:使用基于文本行的协议

    基于内存存储:数据存储在内存中

    事件处理:基于libevent开发

    不互相通信的分布式:多台memcached服务器之间不互相通信,由客户端实现分布式算法



                                                   图1 memcached的分布式(转来的图)


    1.1 内存管理机制

    memcached采用名为slab allocator的内存管理机制,其基本原理是将预先规定的大小,将内存划分为特定长度的块。目的是要解决简单的malloc/free方式所造成的内存碎片。

    Slab是memcached分配的基本单位,每个Slab对应多张Page(默认大小是1M),每张Page会被划分为多个chunk(每个chunk中都保存了一个item结构体、一对key和value)。

    早期的版本中,每个Page一旦被分配给一个Slab,其后变一直如遇该Slab,但在较新的版本中,一个Page已经可以被重新分配给不同的Slab。

    当客户端发来一条数据时,memcached根据数据的大小选择最为合适的Slab,将其存储在对应的Slab中。但是这也会带来新的问题,即内存的利用率会下降,例如,当一个100byte的数据到来,我们不得不为其分配一个128bytes的chunk,其多余的28字节就被浪费掉了。

    为了尽量低的减少内存的浪费,memcached预先设定了40类Slab,通过在启动时加入-vv命令可以查看(两个v)

    usr/local/memcached/bin/memcached -d -m 256 -l 127.0.0.1 -p 11212 -c 1024 -u root -vv


    memcached默认的使用1.25作为增长因子,在使用memcached的过程中我们通过调整-f (成长因子、 -n(default size)等参数优化内存使用,计算公式如下(抄来的):

    chunk size(class i) :  (default_size+item_size)*f^(i-1)+ CHUNK_ALIGN_BYTES

    当没有可用Page时,memcached开始对Slab执行LRU算法删除冷数据,这里必须明确一点即LRU执行的对象是 Slab不是全局。


    2. 安装、配置及启动

    首先,安装libevent:

    wget http://monkey.org/~provos/libevent-1.4.13-stable.tar.gz
    
    tar xzvf  libevent-1.4.13-stable.tar.gz
    
    cd libevent-1.4.13-stable
    
    ./configure && make && make install
    

    然后,安装memcached

    wget http://memcached.org/latest
    tar zxvf memcached-1.4.21.tar.gz && cd memcached-1.4.21
    ./configure && make && make install

     默认情况下程序会安装到 /usr/local/bin/memcached,接下来我们就可以启动memcached了,首先让我们来看一下启动参数,这里我们仅介绍一下常用的参数,更详细的参数列表可以通过man memcached查看:

    -l              设置监听的ip地址,默认为 INADDR_ANY

    -d             以守护进程模式运行memcached

    -u             指定用户

    -m            设置memcached可以使用的内存大小,单位为 M

    -c              设置最大链接数,默认为1024

    -R             设置一个客户端的最大连续请求数,默认为20

    -p              设置TCP监听端口

    -U              设置UDP监听端口

    -P              设置memcached的Pid文件

     /usr/local/bin/memcached -d -m 256 -l 127.0.0.1 -p 11211 -c 1024 -u root

    3. telnet方式

    连接memcached:


    3.1 存储命令

    <command name> <key> <flags> <expire> <bytes>
    
    <value>
    <command name> set/add/replace
    <key> 索引值 
    <flags> 标志信息
    <expire> 过期时间,0表示永不过期
    <bytes> value的字节数
    <value> 存储的数据块

    set 命令:即可以添加新数据还可以更新已存在数据


    add命令:仅在数据不存在时添加数据 

       

    replace命令:仅在数据存在时更新数据



    3.2 清除命令

    <command name> <key>

    delete命令: 删除已存在的数据



    flush_all命令:清空数据。实际上它是时此命令之前插入的数据,在读取时无效化,同时在新数据到来后清除老数据


    3.3 读取命令

    <command name> <key>
    get命令:读取指定key的值



    gets命令:读取指定key的值,末尾比get命令多一个值,限制value否改变,该值变化说明value发生了变化.



    cas命令:仅当最后一个参数与gets取得结果的最后一个参数匹配时才更新(应该算是添加数据命令,但放在这里比较好解释)



    3.4 更新数据命令

    append命令:在现有数据之后添加字符



    prepend命令:在现有数据之前添加字符



    incr/decr命令:对数值型value进行增减,支持64位无符号数,最后那个参数表示变更的范围



    3.5 查询状态命令

    stats命令:


    stats item命令:查看条目状态


    stats slabs命令:查看内存情况


    还有stats sizes,stats reset等等使用也比较常见.


    4. libmemcached 

    4.1 基本数据结构

    memcached_st 结构:用于保存memcached连接对象

            memcached_return_t结构: 用于保存memcached命令执行状态

            memcached_server_st 结构:用于存储memcached服务器列表


    4.2 创建和销毁一个memcached连接对象

    	memcached_st* memcached_create(memcached_st* ptr)      创建一个memcached_st对象,参数一般为NULL;
            memcached_st* memcached_clone(memcached_st* dest,memcached_st* src)    克隆一个memcached对象;
            void memcached_free(memcached_st* ptr)   释放memcached对象,断开连接时使用;


    4.3  操作memcached_st中存储的server信息

    memcached_return_t memcached_server_add(memcached_st *mem,const char *hostname, int port); //在服务器列表尾部添加一台server
    memcached_server_st* memcached_server_list_append(memcached_server_st* ptr,const char* hostname,int port,memcached_return_t * return) ; // 在memcached_server_st中添加一台server
    memcached_return_t memcached_server_push(memcached_st *mem,memcached_server_st* ptr); //在服务器列表尾部添加一个server数组,与memcached_server_list_append结合使用
    uint32_t memcached_server_count(memcached_st* mem); //计算当前server的个数
    void memcached_servers_reset(memcached_st* mem); //清空server列表
    void memcached_server_list_free(memcached_server_st* ptr); //释放memcached_server_st结构

    4.4 操作memcached数据

    增减数据值:

    memcached_return_t memcached_increment(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value)//将指定key的value值加1
    memcached_return_t memcached_decrement(memcached_st *ptr, const char *key, size_t key_length, uint32_t offset, uint64_t *value)//将指定key的value值减1

    删除数据

    memcached_return_t memcached_delete(memcached_st *ptr, const char *key, size_t key_length, time_t expiration)

    检查key值是否存在

    memcached_return_t memcached_exist(memcached_st *ptr, char *key, size_t *key_length)


    清空数据

    memcached_return_t memcached_flush(memcached_st *ptr, time_t expiration)

    获取数据

    char * memcached_get(memcached_st *ptr, const char *key, size_t key_length, size_t *value_length, uint32_t *flags, memcached_return_t *error)//获取单个数据
    memcached_return_t memcached_mget(memcached_st *ptr, const char * const *keys, const size_t *key_length, size_t number_of_keys)//获取多个数据,需要注意的是,当使用多个server时mget无法通过一次条用返回不同存储在不同server上的数据
    char* memcached_fetch(memcached_st *ptr,char* keys, size_t *key_length,size_t* value_length,uint32_t* flags,memcached_return_t *error)//从上面函数的结果中提取数据

    写入数据

    memcached_return_t memcached_set(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//向memcached写入一条数据,存在即覆盖
    memcached_return_t memcached_add(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//不存在即插入,存在返回错误
    memcached_return_t memcached_replace(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//存在即覆盖,不存在返回错误
    memcached_set在非阻塞模式下只有当网络错误发生时才会返回错误


    扩展字符串

    memcached_return_t memcached_prepend(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//在原来的字符串之前添加内容
    memcached_return_t memcached_append(memcached_st *ptr, const char *key, size_t key_length, const char *value, size_t value_length, time_t expiration, uint32_t flags)//在原来的字符串末尾添加内容

    上面这些接口仅用于TCP调用,libmemcached中对UDP和UNIX SOCKET也有相应的支持。

    基本上,libmemcached提供了所有与命令行对应的功能接口,可以查询http://docs.libmemcached.org/

    这里我们通过实例代码简要的说明一下存储和获取数据的接口

    #include <libmemcached/memcached.h>
    
    int main(int argc, char* argv[]){
        memcached_st *mem;
        memcached_return_t re;
        memcached_server_st *svr;
        
        //连接memcached 
        mem = memcached_create(NULL);
        svr = memcached_server_list_append(NULL,"127.0.0.1",11211,&rc);
        rc = memcached_server_push(mem,srv);
        memcached_server_list_free(srv);
        //存储数据
        char* value = "zhoushuaiyin";
        rc = memcached_set(mem,"zhou",4,value,strlen(value),0,0);
        if(MEMCACHED_SUCCESS == rc){
             //anything
        }
    
        //分别使用mgets+fetch和mget方式获取数据
        char *return_value = NULL;
        size_t return_value_length;
        char* keys[]={"zhou"};
        size_t keys_length[]={4};
        uint32 flags;
        rc = memcached_mget(mem,keys,keys_length,1);
        return_value = memcached_fetch(mem,return_key,&return_key_length,&return_value_length,&flags,&rc);
         if(MEMCACHED_SUCCESS == rc){
               printf("key:%s, value:%s",return_key,return_value);
         }
    
          char* val = memcached_get(mem,"zhou",4, &return_value_length,&flags,&rc);if(MEMCACHED_SUCCESS == rc){
               printf("key:%s, value:%s",return_key,return_value);
         }
    
         //删除数据
         rc = memcached_delete(mem,"zhou", 4 , (time_t)0);
    
         memcached_free(mem);
         retrun 0;
    
    
    }

    再给出一段memcached一致性hash的代码,包括使用memcached_get_by_key函数(by_key结尾的函数都具有相同的意义),不是很规范,但应该可以说明问题:

    #include<libmemcached/memcached.h>
    
    int main(int argc, char* argv[]){
        memcached_st *mem;
        memcached_return_t rc;
        memcached_server_st* servers;
    
        mem = memcached_create(NULL);
        memcached_behavior_set(mem,MEMCACHED_BEHAVIOR_DISTRIBUTION,MEMCACHED_DISTRIBUTION_CONSISTENT);
        servers = memcached_server_list_append(NULL,"localhost",11211,&rc);
        servers = memcached_server_list_append(servers,"localhost",11210,&rc);
    
    
        rc = memcached_server_push(mem,servers);
        memcached_server_free(servers);
    
        printf("the server count is %d",memcached_server_count(mem));
        const char* const keys[] = {"key1","key2","key3","key4"};
        char* values[] = {"value1","value2","value3","value4"};
    
        for(int i = 0 ; i < 4; i++){
            memcached_set(mem,keys[i],strlen(keys[i]),values[i],strlen(values[i]),0,0);
    
        }
    
        size_t value_length[4];
        uint32_t flag;
        for(int i = 0; i < 4; i++){
            values[i] = memcached_get(mem,keys[i],strlen(keys[i]),&value_length[i],&flag,&rc);
            printf("the value is %s\n",values[i]);
        }
    
        char* value = "zhou";
        size_t flag2;
    
        value = memcached_get_by_key(mem,keys[1],strlen(keys[1]),keys[1],strlen(keys[1]),&flag2,&flag,&rc);
        printf("the value is %s\n",value);
        memcached_free(mem);
        return 0;
    
    }


    5. PHP与memcached通信

    参阅:http://php.net/manual/zh/class.memcached.php

    展开全文
  • Memcached 工作原理介绍

    万次阅读 2013-07-15 16:27:50
    面临的问题  对于高并发高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题。特别当你的程序架构还是建立在单数据库模式,而一个数据池连接数峰值已经达到500的时候,那你的程序运行离崩溃的边缘也...
    
    

    一. Memcached简介

    Memcached 是一个高性能的分布式内存对象缓存系统,现在很多的大型web应用程序包括Facebook, LiveJournal,mixi, Digg等等都在使用memcached来支持他们每天数亿级的页面访问。通过把cache层与他们的web架构集成,他们的应用程序在提高了性能的同时,还大大降低了数据库的负载。

    二. Memcached的产生背景

    对于大数据、高并发、高访问的Web应用程序来说,数据库存取瓶颈一直是个令人头疼的问题。当一个数据池连接数峰值已经达到500的时候,那运行的程序离崩溃的边缘也不远了。很多小网站的开发人员一开始都将注意力放在了产品需求设计上,缺忽视了程序整体性能,可扩展性等方面的考虑,结果眼看着访问量一天天往上走,可突然发现有一天网站因为访问量过大而崩溃了,后果是非常严重的。

    大家都知道,当有一个request过来后,web服务器交给app服务器,app处理并从db中存取相关数据,但db存取的花费是相当高昂的。特别是每次都取相同的数据,等于是让数据库每次都在做高耗费的无用功,数据库如果会说话,肯定会发牢骚,你都问了这么多遍了,难道还记不住吗?是啊,如果app拿到第一次数据并存到内存里,下次读取时直接从内存里读取,而不用麻烦数据库,这样不就给数据库减负了?而且从内存取数据必然要比从数据库媒介取快很多倍,反而提升了应用程序的性能。

    因此,我们可以在web/app层与db层之间加一层cache层,主要目的:

    1. 减少数据库读取负担;

    2. 提高数据读取速度。而且,cache存取的媒介是内存,而一台服务器的内存容量一般都是有限制的,不像硬盘容量可以做到TB级别。所以,可以考虑采用分布式的cache层,这样更易于破除内存容量的限制,同时又增加了灵活性。

    三. Memcached的安装

    1. 下载Memercached For Windows,如果你的系统是Linux,可以下载Memercached  For Linux版本。

         2.  安装步骤

       (1)解压到指定目录,如:C:\Memcached\memcached-win32-1.4.4-14。

       (2)用cmd打开命令窗口,转到解压的目录,输入 “memcached.exe -d install”。

       (3)打开控制面板,打开服务,可以看到memcached已经在上面可,如果没有启动,则手动启动一下。

              

    四.Memcached的工作原理

    Memcached处理的原子是每一个(key,value)对(以下简称kv对),key会通过一个hash算法转化成hash-key,便于查找、对比以及做到尽可能的散列。同时,memcached用的是一个二级散列,通过一张大hash表来维护。

    Memcached有两个核心组件组成:服务器端(server)和客户端(client),在一个memcached的查询中,client先通过计算key的hash值来确定kv对所处在的server位置。当server确定后,客户端就会发送一个查询请求给对应的server,让它来查找确切的数据。因为这之间没有交互以及多播协议,所以memcached交互带给网络的影响是最小化的。

    举例说明:考虑以下这个场景,有三个client分别是c1,c2,c3,还有三个ms分别是s1,s2,s3:

    设置kv对
    c1想设置key=”com”,value=”iQiyi”
    c1拿到server列表,并对key做hash转化,根据hash值确定kv对所存的server位置
    s2被选中了
    c1连接上s2,s2收到请求,把(key=”com”,value=”iQiyi”)存了起来

    获取kv对
    c3想得到key=”com”的value
    c3用相同的hash算法算出hash值,并确定key=”aa”的值存在s2上
    c3连接上s2,并从s2那边得到value=”iQiyi”
    其他任何从c1,c2,c3的想得到key=”com”的值的请求都会发向s2

    五.Memcached的内存管理机制

    memcached会预先分配内存,首先,这里有3个概念:
    1.  slab
    2.  page
    3 . chunk
    解释一下,一般来说一个memcahced进程会预先将自己划分为若干个slab,每个slab下又有若干个page,每个page下又有多个chunk,如果我们把这3个咚咚看作是object得话,这是两个一对多得关系。再一般来说,slab得数量是有限得,几个,十几个,或者几十个,这个跟进程配置得内存有关。而每个slab下得page默认情况是1m,也就是说如果一个slab占用100m得内存得话,那么默认情况下这个slab所拥有得page得个数就是100,而chunk就是我们得数据存放得最终地方。下图是slab下的page图片

     

    Chunk

     

    用于缓存记录的内存空间。 

     

    Slab Class

    特定大小的chunk的组。 

     

    Memcached的内存分配以page为单位,默认情况下一个page1M ,可以通过-I参数在启动时指定。如果需要申请内存 时,memcached会划分出一个新的page并分配给需要的slab区域。Memcached并不是将所有大小的数据都放在一起的,而是预先将数据空间划分为一系列slabs,每个slab只负责一定范围内的数据存储,其大小可以通过启动参数设置增长因子,默认为1.25,即下一个slab的大小是上一个的1.25倍。如 下图,每个slab只存储大于其上一个slabsize并小于或者等于自己最大size的数据。如下图所示,需要存储一个100Bytes的对象时,会选用112BytesSlab Classes,如下图所示:

     

    六.Memcached的缓存策略

    当ms的hash表满了之后,新的插入数据会替代老的数据,更新的策略是LRU(最近最少使用),以及每个kv对的有效时限。Kv对存储有效时限是在mc端由app设置并作为参数传给ms的。

    同时ms采用是偷懒替代法,ms不会开额外的进程来实时监测过时的kv对并删除,而是当且仅当,新来一个插入的数据,而此时又没有多余的空间放了,才会进行清除动作。

    七.Memcached的客户端

    Memcached客户端有各种语言的版本供大家使用,包括java,c,php,.net等等。其中面向Java的三种Memcached客户端包括memcached client for java、spymemcached和xmemcached  。

    八.Memcached与Mysql整合

    Memcache和MySQL 交互流程图如下

        

    下面详细了解Memcache各类数据操作原理:

    1,查询数据(select),首先通过指定的Key查询 (get)Memcache中间缓存层数据,如果存在相对应数据,则直接获取出数据结果,查询过程完全不需要查询数据库。如果不存在,则查询MySQL数 据库,并以key对应value的形式将查询结果存储在Memcache缓存数据中,然后将结果返回给查询语句。

    2,更新 数据(update),首先更新数据,然后删除相关的memcache数据(delete)。

    3,增加 数据(add),首先删除相关缓存数据,然后增加数据。

    4,删除数据(delete), 删除数据,并删除Memcache数据。

    展开全文
  • memcached

    2020-03-30 13:35:39
    memcached是一个高性能的分布式的内存对象缓存系统,分担数据库压力。 memcached在内存里维护一个巨大的hash表, 哪些情况下适合使用memcached:存储验证码、登录session等不是至关重要的数据。 2、python 操作...
  • 为什么要使用Memcached

    2018-08-24 11:16:06
    大家好,今天给大家分享一下:为什么要使用memcachedmemcached有什么作用?   1.背景介绍 在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法。其通过记录某部分计算结果来尝试避免...
  • memcached真实项目中的应用

    万次阅读 2014-06-20 20:15:24
    上一篇介绍了memcached的一些基本概念和范例
  • Memcached —— 下载、 配置、使用

    千次阅读 2017-08-28 09:03:47
    主要了解Memcached 与其其中一个java客户端XMemcached。 一、基础了解 Memcahed 是一套分布式高速缓存系统。简言之,它是用于缓存数据的服务。在并发访问web服务器时,为减少直接访问数据库的次数,降低数据库...
  • Memcached 看一遍就懂了

    2017-09-28 21:19:22
    Memcached学习本文总结了学习Memcached的一些关键点: Memcached简介 Memcached特点 Memcached安装步骤 Memcached客户端 Memcached与Redis比较 Memcached与Memcache的区别 Memcached内存模型 目录Memcached学习 目录...
  • MemCached

    千次阅读 2019-04-27 10:18:00
    MemCached原理 许多Web应用都将数据保存到RDBMS中,应用服务器从中读取数据并在浏览器中显示 随着数据量的增大,访问的集中,就会出现RDBMS的负担加重,数据库响应恶化,网站显示延迟等重大影响 数据库存储...
  • Memcached之——Windows下安装Memcached

    万次阅读 多人点赞 2017-03-11 15:19:59
    一、下载并安装memcached服务器端软件 1、下载服务端memcached软件 32bit:下载 memcached-win32-1.4.4-14.zip(直接下)里面包含6个文件,将解压后的文件夹随便放在什么位置(例如:D:\memcached)。 memcached-...
  • Memcached

    2019-03-06 10:01:39
    Memcached简介 Memcached是一款开源的、高性能的、分布式的内存对象缓存系统 Memcached能干什么 最主要的功能就是:在内存中缓存数据,以减轻数据库负载。 它通过在内存中缓存数据和对象来减少读取数据库的次数,...
  • Memcached介绍

    万次阅读 2015-11-01 10:13:47
    Memcached介绍本文介绍memcached基本的使用和理解: Memcached是什么 Memcached的作用 怎样理解Memcached Memcached的使用场景 项目中使用Memcached 项目中使用Memcached注意事项 Memcached是什么: Memcached是一套...
  • sh memcached 进程启动及监控

    万次阅读 2013-06-23 12:22:41
    memcached 进程启动及监控 1.memcached_inc.sh 设置路径,端口等讯息。 #!/bin/sh #config include HOST=$(hostname) SITE="mysite" PORT=11211 MEMCACHED_PID_FILE="/tmp/memcached.pid" MEMCACHED_DAEMON_...
  • memcached】安装、启动、查看状态

    万次阅读 2014-06-08 16:02:02
    Ubuntu下安装
  • memcached的启动和停止

    千次阅读 2016-11-17 11:46:26
    memcached的启动和停止[root@hotapply ~]# ps -ef|grep memcached root 9662 1 0 10:13 ? 00:00:00 /usr/bin/memcached -d -m 1024 -u root -l 127.0.0.1 -p 11211 -c 1024 -P /tmp/memcached.pid root
  • Memcached 查看列出所有key方法

    万次阅读 2016-09-27 15:27:27
    Memcached 查看列出所有key方法
  • Windows 下 PHP memcached扩展安装

    千次阅读 2016-11-02 16:02:54
    Windows 下 PHP memcached扩展安装 图文教程
  • 1、实战Memcached缓存系统(1)Memcached基础及示例程序 内容:建筑Memcached背景知识和入门示例程序。 2、实战Memcached缓存系统(2)Memcached Java API基础之MemcachedClient 内容:以Memcached的Java Spy...
1 2 3 4 5 ... 20
收藏数 121,591
精华内容 48,636
关键字:

memcached