zoukankan      html  css  js  c++  java
  • Memcached内存缓存技术

    Memcached是什么,有什么作用?

    Memcached是一个开源的、高性能的内存缓存软件,从名称上看Mem就是内存的意思,而Cache就是缓存的意思。
    Memcached通过在事先规划好的内存空间中临时缓存数据库中的各类数据,以减少业务直接对数据库的访问,从而减轻数据库的访问压力和网站集群的响应速度。

    Memcached服务在企业集群架构中应用场景

    1.作为数据库的前端缓存应用

    完整缓存(易):例如商品分类,以及商品信息,可实现放到内存里,然后再对外提供数据访问。这个被称之为预热。用户访问时可以只读取memcached缓存,不读取数据库了。

    热点缓存(难):需要前端程序配合。只缓存热点的数据,即缓存经常被访问的数据。先预热基础数据,然后再动态更新。程序先读取缓存,如果缓存里没有对应的数据,程序再去读取数据库,然后程序把读到的数据放入缓存。

    特殊说明:
    如果碰到电商秒杀等高并发的业务,一定要事先预热,或者其他思想实现,例如:秒杀只是获取资格,而不是瞬间秒杀到手商品。如果数据更新,要同时触发缓存更新,防止给用户过过期数据。

    2.作为集群的session会话共享存储

    优点:速度比files块,可以解决共用session问题
    缺点:不能持久化,只能单点部署,多点数据无法同步,即使用hash分配节点,也会有session丢失

     Memcached服务在不同企业业务应用场景中的工作流程

    1.当web程序需要访问后端数据库获取数据时会优先访问Memcached内存缓存,如果缓存中有数据就直接获取返回前端服务及用户,如果没有数据(未命中),再由程序请求后端的数据库服务器,获取到对应的数据后,除了返回给前端服务及用户数据外,还会把数据放到Memcached内存中进行缓存,等待下次被访问。Memcahced内存始终是数据库的挡箭牌,从而大大的减轻数据库的访问压力,提高整个网站架构的响应速度,提升了用户体验。

    2.当程序更新,修改或删除数据库中已有的数据时,会同时发送请求通知Memcached已经缓存过的同一个ID内容的旧数据失效,从而保证Memcahce中的数据和数据库中的数据保持一致。如果是在高并发场合,除了通知Memcached过期的缓存失效外,还会通过相关机制,使得在用户访问新数据前,通过程序预先把更新过的数据推送到memcached中缓存起来,这样可以减少数据库的访问压力,提升memcached中缓存的命中率。

    3.数据库插件可以在写入更新数据库后,自动抛给MC缓存起来,自身不Cache

    Memcached服务分布式集群如何实现?

    1.程序端实现

    程序加载所有mc的ip列表,通过对key做hash(一致性哈希),从而映射到某一台mc,相同的key永远映射到同一台的mc。 Hash就是将任意长度的输入转化成固定长度的输出。
    一致性哈希的目的:不但保证每个对象只请求一个对应的服务器,同时保证当某个节点宕机,缓存服务器的更新重新分配比例降到最低。
    2.负载均衡器实现:由负载均衡器来做hash
     
    特殊说明:memcached集群和web服务集群是不一样的,所有memcached数据总和才是数据库的数据。每台memcached只有一部分数据。

    Memcached服务特点及工作原理是什么?

    a.节点之间相互独立
    b.数据是以key/value对形式存在的
    c.C/S模式架构,C语言编写,总共代码2000多行
    d.异步I/O模型,使用libevent事件通知机制
    e.全部数据放入内存,无持久性设计,重启服务数据丢失  (缺点)
    f.当内存中缓存的数据容量达到启动时设定的内存值时,自动使用LRU算法删除过期的缓存数据
    g.可以对存储的数据设置过期时间,这样过期后数据自动被清除,服务本身不会监控过期,而是在访问的时候查看key的时间戳判断是否过期
    h.memcached内存分配机制是对特定的内存进行分块,再把多个块分为组

    Memcached内存管理机制原理

    malloc的全称是memory allocation,中文叫动态内存分配,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
    早期的memcached内存管理方式是通过malloc分配的内存,使用完后通过free来回收内存。这种方式容易产生内存碎片并降低操作系统对内存的管理效率。加重操作系统内存管理器的负担,最坏的情况下,会导致操作系统比memcached进程本身还慢,为了解决上述问题,Slab Allocator内存分配机制就产生了
    现在的memcached就是利用Slab Allocation机制来分配和管理内存。
    Slab Allocation机制原理是按照预先规定的大小,将分配给memcached的内存分割成特定长度的内存块chunk,再把尺寸相同的内存块分成组(chunks slab class),这些内存块不会释放,可以重复利用。

    Memcached服务器端中保存着slab class中空闲chunk个数的列表,根据该列表选择chunk,然后将数据缓存于其中。当有数据存入时,Memcached根据接收到的数据大小,分配一个能存下这个数据的最小内存块chunk。但是缺点在于由于分配的chunk大小是固定的,所以会有部分空间被浪费。

    避免浪费的办法是,预先计算出应用存入的数据大小或把同一业务类型的数据存入一个Memcached服务器中,确保存入的数据大小相对均匀。同时使用-f<factor> chunk size growth factor增长因子来划分chunk大小,进行调优。各组之间chunk的大小按照factor对应倍数递增,factor的默认值是1.25。

    同时slab allocator还有重复使用已分配的chunk的作用。也就是说,分配到的chunk不会释放,而是重复利用,用新数据替换旧数据。

    Slab主要术语:
    Page:分配给Slab的内存空间
    Chunk:内存块
    Slab Class:多个特定大小的chunk组成的组,一般也叫slabs

    Memcached的删除原理与删除机制

    Memcached主要的删除机制是LRU(最近最少用)算法,加上item过期失效。当您存数据到memcached中,可以指定该数据在缓存中可以呆多久。如果memcached内存不够用,过期的数据会优先被替换,接着轮到最老的未被使用的数据。在某些情况下(完整缓存),如果不想用LRU算法,可以通过-M参数启动Memcached,这样memcached内存耗尽也不会删除,宁愿报错也不删除。

    Memcached服务端与客户端的安装部署与使用测试

    #安装memcached前需要安装libevent
    yum install libevent-devel nc -y
    #源码安装memcahced
    cd /server/tools
    wget http://memcached.org/files/memcached-1.4.24.tar.gz
    tar xf memcached-1.4.24.tar.gz
    cd memcached-1.4.24
    ./configure --prefix=/application/memcached-1.4.24
    make
    make install
    ln -s /application/memcached-1.4.24/ /application/memcached
    
    #启动一个Mem实例
    /application/memcached/bin/memcached -m 16m -p 11211 -d -u root -c 8192 # 分配的内存 端口 后台 用户 最大并发连接数
    lsof -i :11211
    ps -ef | grep memcached | grep -v grep
    root       2984      1  0 23:10 ?        00:00:00 /application/memcached/bin/memcached -m 16m -p 11211 -d -u root -c 8192
    
    #可以启动多个Mem实例
    /application/memcached/bin/memcached -m 16m -p 11212 -d -u root -c 8192
    ps -ef | grep memcached | grep -v grep
    root       2984      1  0 23:10 ?        00:00:00 /application/memcached/bin/memcached -m 16m -p 11211 -d -u root -c 8192
    root       3036      1  0 23:16 ?        00:00:00 /application/memcached/bin/memcached -m 16m -p 11212 -d -u root -c 8192
     
    #加入开机启动
    echo "/application/memcached/bin/memcached -m 16m -p 11211 -d -u root -c 8192" >> /etc/rc.local
    echo "/application/memcached/bin/memcached -m 16m -p 11212 -d -u root -c 8192" >> /etc/rc.local
    
    #测试服务端是否正常
    [root@nagios tools]# printf "set key1 0 0 5
    peter
    " | nc 127.0.0.1 11211
    STORED
    [root@nagios tools]# printf "get key1
    " | nc 127.0.0.1 11211
    VALUE key1 0 5
    peter
    END
    [root@nagios tools]# printf "delete key1
    " | nc 127.0.0.1 11211
    DELETED
    
    #客户端php插件memcache安装
    cd /server/tools/
    wget http://pecl.php.net/get/memcache-2.2.7.tgz
    tar xf memcache-2.2.7.tgz
    cd memcache-2.2.7
    /application/php/bin/phpize
    ./configure --enable-memcache --with-php-config=/application/php/bin/php-config
    make
    make install
    Installing shared extensions:     /application/php-5.3.27/lib/php/extensions/no-debug-non-zts-20090626/
    ls -l /application/php-5.3.27/lib/php/extensions/no-debug-non-zts-20090626/
    total 244
    -rwxr-xr-x 1 root root 246696 Sep  1 22:51 memcache.so
    
    vim /application/php/lib/php.ini
    
    ; http://php.net/extension-dir
     extension_dir = "/application/php-5.3.27/lib/php/extensions/no-debug-non-zts-20090626/"
     extension=memcache.so
    
    /application/php/sbin/php-fpm -t
    pkill php-fpm
    /application/php/sbin/php-fpm
    ps -ef | grep php-fpm
    
    #http://10.0.0.23/test_info.php
    

     

    #连接测试
    vim op_mem.php
    <?php
            $memcache = new Memcache;
            $memcache->connect('172.16.1.23',11211) or die ("Could not connect Mc server");
            $memcache->set('key','oldboy book');
            $get=$memcache->get('key');
            echo $get;
    ?>
    
    /application/php/bin/php op_mem.php
    oldboy book
    

     如何实现集群中的session共享存储?

    vim /application/php/lib/php.ini
    
    1458 [Session]
    1459 ; Handler used to store/retrieve data.
    1460 ; http://php.net/session.save-handler
    1461 session.save_handler = memcache           #修改session存储方式
    1462
    1463 ; Argument passed to save_handler.  In the case of files, this is the path
    1464 ; where data files are stored. Note: Windows users have to change this
    1465 ; variable in order to use PHP's session functions.
    1466 ;
    1467 ; The path can be defined as:
    1468 ;
    1469 session.save_path = "tcp://172.16.1.23:11211"    #修改session存储路径
           
    pkill php-fpm
    /application/php/sbin/php-fpm
    
    #http://10.0.0.23/test_info.php
    

     

    session同步的多种方式

    a. lb层可以做会话保持,例如:
         lvs -p
         nginx ip_hash
         haproxy cookie insert
         PHP,JAVA都可以用
    b. 软件层,可以做session复制,例如
         tomcat resin couchbase
    c. session共享
          memcache或者其他nosql工具,PHP常用这个
    d. 高并发场景:例如门户网站用cookies或cookies配合session把用户级会话信息缓存在用户本地。高并发的场景cookies的效率比session要好很多

     MEMCACHED服务的状态信息的获取,例如:命中率

    1.通过memcache命令
    printf "stats
    " | nc 127.0.0.1 11211     #Memcached各种状态信息
    STAT pid 41346                              #PID
    STAT uptime 4759                            #服务已运行秒数
    STAT time 1505572559                        #服务当前UNIX时间戳
    STAT version 1.4.24                         #Memcached版本
    STAT libevent 1.4.13-stable                 #libevent版本
    STAT pointer_size 64                        #操作系统指针大小
    STAT rusage_user 0.121981                   #进程累计用户时间
    STAT rusage_system 0.112982                 #进程累计系统时间
    STAT curr_connections 10                    #当前连接数
    STAT total_connections 14                   #服务运行以来总连接数
    STAT connection_structures 11               #服务分配的连接结构数量
    STAT reserved_fds 20                        #内部使用的FD数
    STAT cmd_get 1                              #get请求次数
    STAT cmd_set 1                              #set请求次数
    STAT cmd_flush 0                            #flush请求次数
    STAT cmd_touch 0                            #touch请求次数
    STAT get_hits 1                             #get命中次数
    STAT get_misses 0                           #get未命中次数
    STAT delete_misses 0                        #delete未命中次数
    STAT delete_hits 1                          #delete命中次数
    STAT incr_misses 0                          #incr未命中次数
    STAT incr_hits 0                            #incr命中次数
    STAT decr_misses 0                          #decr未命中次数
    STAT decr_hits 0                            #decr命中次数
    STAT cas_misses 0                           #cas未命中次数
    STAT cas_hits 0                             #cas命中次数
    STAT cas_badval 0                           #cas使用擦拭次数
    STAT touch_hits 0                           #touch命中次数
    STAT touch_misses 0                         #touch未命中次数
    STAT auth_cmds 0                            #认证命令处理次数
    STAT auth_errors 0                          #认证命令失败次数
    STAT bytes_read 53                          #读取总字节数
    STAT bytes_written 45                       #写入总字节数
    STAT limit_maxbytes 16777216                #分配内存总大小(字节)
    STAT accepting_conns 1                      #接受新的连接
    STAT listen_disabled_num 0                  #失效的监听数
    STAT threads 4                              #当前线程数
    STAT conn_yields 0                          #连接操作主动放弃数目
    STAT hash_power_level 16                    #hash表等级
    STAT hash_bytes 524288                      #hash表大小
    STAT hash_is_expanding 0                    #hash表正在扩展
    STAT malloc_fails 0                         #分配内存失败的数目
    STAT bytes 0                                #已过期但未获取的对象数目
    STAT curr_items 0                           #当前的对象数目
    STAT total_items 1                          #当前存储占用的字节数
    STAT expired_unfetched 0                    #已过期但未获取的对象数目
    STAT evicted_unfetched 0                    #已驱逐但未获取的对象数目
    STAT evictions 0                            #LRU释放的对象数目
    STAT reclaimed 0                            
    STAT crawler_reclaimed 0                    
    STAT crawler_items_checked 0                    
    STAT lrutail_reflocked 0
    END
    
    [root@nagios ~]# printf "stats settings
    " | nc 127.0.0.1 11211     #Memcached设置信息
    [root@nagios ~]# printf "stats slabs
    " | nc 127.0.0.1 11211        #查看slabs相关信息
    [root@nagios ~]# printf "stats items
    " | nc 127.0.0.1 11211        #查看items相关信息
    [root@nagios ~]# printf "stats sizes
    " | nc 127.0.0.1 11211        #查看items的大小和个数
    [root@nagios ~]# printf "stats reset
    " | nc 127.0.0.1 11211        #清理统计数据
    
    #访问测试
    [root@nagios nginx]# printf "stats
    " | nc 127.0.0.1 11211 | grep get
    STAT cmd_get 1
    STAT get_hits 1
    STAT get_misses 0
    
    [root@nagios nginx]# printf "get key1
    " | nc 127.0.0.1 11211
    END
    
    [root@nagios nginx]# printf "stats
    " | nc 127.0.0.1 11211 | grep get
    STAT cmd_get 2
    STAT get_hits 1
    STAT get_misses 1
    

    2.通过Memcached管理工具Memadmin展示

    #Memadmin是基于PHP和JQuery的Memcached管理监控工具
    cd /server/tools
    wget http://www.junopen.com/memadmin/memadmin-1.0.12.tar.gz
    tar xf memadmin-1.0.12.tar.gz
    mv memadmin /application/nginx/html/www/
    
    #http://10.0.0.88/memadmin
    

     

    通过Nagios监控Memcached

    1.监控指标:

    端口

    命名率

    响应时间

    模拟用户存取

    2.Nagios插件开发

    #模拟用户进行存取,测试memcached的状态
    vim check_mc.sh
    [ $# -ne 2 ] && {
         echo "$0 ip port"
         exit
    }
    #!/bin/bash
    ServerIP=$1
    ServerPort=$2
    cmd="nc $ServerIP $ServerPort"
    printf "delete key
    " | $cmd > /dev/null 2>&1
    sleep 1
    printf "set key 0 0 5
    peter
    " | $cmd > /dev/null 2>&1
    if [ `printf "get key
    " | $cmd | grep peter | wc -l` -eq 1 ];then
        echo "mc is alive."
        exit 0
    else
        echo "mc is dead."
        exit 2
    fi
    
    [root@nagios ~]# sh check_mc.sh 127.0.0.1 11211
    mc is alive.
    
     
  • 相关阅读:
    python定义函数的三种形式
    python函数的返回值
    python函数的调用
    python函数的定义
    python文件操作
    Python2和3字符编码的区别
    python的字符编码
    python异常处理
    python深浅拷贝
    python色彩缤纷的python(改变字体颜色以及样式)
  • 原文地址:https://www.cnblogs.com/Peter2014/p/7535733.html
Copyright © 2011-2022 走看看