zoukankan      html  css  js  c++  java
  • python 操作memcached

    Memcached

    Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。

    memcached作为高速运行的分布式缓存服务器,具有以下的特点。
      · 协议简单
      · 基于libevent的事件处理
      · 内置内存存储方式
      · memcached不互相通信的分布式

    存储方式

    为了提高性能,memcached中保存的数据都存储在memcached内置的内存存储空间中。由于数据仅存在于内存中,因此重启memcached、重启操作系统会导致全部数据消失。另外,内容容量达到指定值之后,就基于LRU(Least Recently Used,最近最少使用)算法自动删除不使用的缓存。memcached本身是为缓存而设计的服务器,因此并没有过多考虑数据的永久性问题。

    保存键值对发生变动的情况:

    • 为缓存分配的内存耗尽。这种情况下,memcached使用LRU(最近最少使用)算法从此缓存中删除条目。最近未曾使用的条目会从此缓存中先删除,最旧的最先访问。
    • 条目被确定删除, 如程序中删除。
    • 条目过期失效
    主要功能:
      服务器参数监控:STATS、SETTINGS、ITEMS、SLABS、SIZES实时刷新
      服务器性能监控:GET、DELETE、INCR、DECR、CAS等常用操作命中率实时监控
      支持数据遍历,方便对存储内容进行监视
      支持条件查询,筛选出满足条件的KEY或VALUE
      数组、JSON等序列化字符反序列显示
      兼容memcache协议的其他服务,如Tokyo Tyrant (遍历功能除外)
      支持服务器连接池,多服务器管理切换方便简洁

    Memcached安装和基本使用

    Memcached 连接

    编辑
    我们可以通过 telnet 命令并指定主机ip和端口来连接 Memcached 服务。[3] 

    语法

    1
    telnet HOST PORT
    命令中的HOST和PORT为运行 Memcached 服务的 IP 和 端口。

    实例

    以下实例演示了如何连接到 Memcached 服务并执行简单的 set 和 get 命令。
    本实例的 Memcached 服务运行的主机为 127.0.0.1(本机) 、端口为 11211。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    telnet 127.0.0.1 11211
     
    Trying 127.0.0.1...
     
    Connected to 127.0.0.1.
     
    Escape character is '^]'.
     
    set foo 0 0 3                                                   保存命令
     
    bar                                                             数据
     
    STORED                                                          结果
     
    get foo                                                         取得命令
     
    VALUE foo 0 3                                                   数据
     
    bar                                                             数据
     
    END                                                             结束行
     
    quit  

    Memcached安装:

    #1. 安装服务
    # apt-get install memcached -y
    
    #2. 修改配置文件
    # sed -i 's@(^-l).*@1 172.17.0.1@g' /etc/memcached.conf 
    # PS: 默认memcached监听在127.0.0.1, 如果本机使用的话,此步骤可以略去,建议将memcached监听在私有网段网卡上,并配合相应的安全访问控制,稍后续.
    
    
    #重启服务:
    # /etc/init.d/memcached restart
    
    # 查看启动状态:
    # ps -ef|grep memcached
    
    # 查看端口监听:
    # ss -tnlp|grep 11211
    
    # 官网地址:https://memcached.org/  
    
    # 解压缩:
    tar xf memcached-1.4.15.tar.gz && cd memcached-1.4.15
    
    # 编译
    ./configure --prefix=/usr/local/memcached --with-libevent=/usr/local/libevent
    
    make && make install
    ubuntu 安装
    #!/bin/bash
    #
    # Init file for memcached
    # chkconfig: - 86 14
    # description: Distributed memory caching daemon
    # processname: memcached
    # config: /etc/sysconfig/memcached
    
    . /etc/rc.d/init.d/functions
    
    ## Default variables
    PORT="11211"
    USER="nobody"
    MAXCONN="1024"
    CACHESIZE="64"
    OPTIONS=""
    
    RETVAL=0
    prog="/usr/local/memcached/bin/memcached"
    desc="Distributed memory caching"
    lockfile="/var/lock/subsys/memcached"
    
    start() {
            echo -n $"Starting $desc (memcached): "
            daemon $prog -d -p $PORT -u $USER -c $MAXCONN -m $CACHESIZE -o "$OPTIONS"
            RETVAL=$?
            echo
            [ $RETVAL -eq 0 ] && touch $lockfile
            return $RETVAL
    }
    
    stop() {
            echo -n $"Shutting down $desc (memcached): "
            killproc $prog
            RETVAL=$?
            echo
            [ $RETVAL -eq 0 ] && rm -f $lockfile
            return $RETVAL
    }
    
    restart() {
            stop
            start
    }
    
    reload() {
            echo -n $"Reloading $desc ($prog): "
            killproc $prog -HUP
            RETVAL=$?
            echo
            return $RETVAL
    }
    
    case "$1" in
      start)
            start
            ;;
      stop)
            stop
            ;;
      restart)
            restart
            ;;
      condrestart)
            [ -e $lockfile ] && restart
            RETVAL=$?
            ;;       
      reload)
            reload
            ;;
      status)
            status $prog
            RETVAL=$?
            ;;
       *)
            echo $"Usage: $0 {start|stop|restart|condrestart|status}"
            RETVAL=1
    esac
    
    exit $RETVAL
    memcached 系统启动脚本
    wget http://memcached.org/latest
    tar -zxvf memcached-1.x.x.tar.gz
    cd memcached-1.x.x
    ./configure && make && make test && sudo make install
     
    PS:依赖libevent
           yum install libevent-devel
           apt-get install libevent-dev
    

    启动Memcached

    memcached -d -m 10    -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid
     
    参数说明:
        -d 是启动一个守护进程
        -m 是分配给Memcache使用的内存数量,单位是MB
        -u 是运行Memcache的用户
        -l 是监听的服务器IP地址
        -p 是设置Memcache监听的端口,最好是1024以上的端口
        -c 选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定
        -P 是设置保存Memcache的pid文件
    

    Memcached命令

    存储命令: set/add/replace/append/prepend/cas
    获取命令: get/gets
    其他命令: delete/stats..

    Python操作Memcached

    安装API

    1
    2
    python操作Memcached使用Python-memcached模块
    下载安装:https://pypi.python.org/pypi/python-memcached

    1、python操作memcached

    # /usr/bin/env python
    # -*- coding:utf8 -*-
    # auth rain
    import memcache mc
    = memcache.Client(['127.0.0.1:12000'], debug=True) mc.set('key','values') resutl = mc.get('key') print(resutl) ------------------------------------ values

     Ps:debug = True 表示运行出现错误时,现实错误信息,上线后移除该参数。

    2、默认支持集群

    python-memcached模块原生支持集群操作,其原理是在内存维护一个主机列表,且集群中主机的权重值和主机在列表中重复出现的次数成正比

      主机    权重
        1.1.1.1   1
        1.1.1.2   2
        1.1.1.3   1
     
    那么在内存中主机列表为:
        host_list = ["1.1.1.1", "1.1.1.2", "1.1.1.2", "1.1.1.3", ]

    如果用户根据如果要在内存中创建一个键值对(如:k1 = "v1"),那么要执行一下步骤:

    • 根据算法将 k1 转换成一个数字
    • 将数字和主机列表长度求余数,得到一个值 N( 0 <= N < 列表长度 )
    • 在主机列表中根据 第2步得到的值为索引获取主机,例如:host_list[N]
    • 连接 将第3步中获取的主机,将 k1 = "v1" 放置在该服务器的内存中

    代码如下:

    mc = memcache.Client([('172.16.30.162:11211',2),('172.16.30.163:11211',1),('172.16.30.164:11211',1)],debug=1)
    mc.set('key','values')   # 设置一个key, 值为values
    
    result = mc.get('key')  # 获取key值
    print(result)
    
    ---------------------------------------
    values

    3、add
    添加一条键值对,如果已经存在的 key,重复执行add操作异常

    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('key','values')
    resutl = mc.get('key')
    print(resutl)
    
    mc.add('k3','v3')
    a = mc.get('k3')
    print(a)
    
    mc.add('k3','v3')
    # MemCached: while expecting 'STORED', got unexpected response 'NOT_STORED'

    4、replace
    replace 修改某个key的值,如果key不存在,则异常

    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('key','values')
    resutl = mc.get('key')
    print(resutl)               # values
    
    mc.replace('key','values123')
    result1 = mc.get('key')
    print(result1)              # values123
    
    mc.replace('123','abcd')
    # MemCached: while expecting 'STORED', got unexpected response 'NOT_STORED'

    5、set 和 set_multi

    set  设置一个键值对,如果key不存在,则创建,如果key已经存在,则更新key值

    set_multi  设置多个键值对,如果key不存在,则创建,如果key已经存在,则更新key值

    # /usr/bin/env python
    # -*- coding:utf8 -*-
    # auth rain
    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('k1','v1')
    result2 = mc.get('k1')
    print(result2)
    # v1
    
    mc.set_multi({'key':'values', 'key1':'values123'})
    resutl = mc.get_multi(['key', 'key1'])
    print(resutl)
    
    # {'key': 'values', 'key1': 'values123'} 

    6、delete 和 delete_multi

    delete             在Memcached中删除指定的一个键值对
    delete_multi    在Memcached中删除指定的多个键值对

    # /usr/bin/env python
    # -*- coding:utf8 -*-
    # auth rain
    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('k1','v1')
    result2 = mc.get('k1')
    print(result2)
    # v1
    
    mc.set_multi({'key':'values', 'key1':'values123'})
    resutl = mc.get_multi(['key', 'key1'])
    print(resutl)
    # {'key': 'values', 'key1': 'values123'}
    
    mc.delete('k1')
    result3 = mc.get('k1')
    print(result3)
    # None
    
    mc.delete_multi(['key','key1'])
    result4 = mc.get_multi(['key','key1'])
    print(result4)
    # {}
    
    mc.delete_multi(['key','key1'])
    result5 = mc.get_multi(['key','key1'])
    print(result5)
    
    # MemCached: while expecting 'DELETED', got unexpected response 'NOT_FOUND'
    # MemCached: while expecting 'DELETED', got unexpected response 'NOT_FOUND'

    7、get 和 get_multi

    get            获取一个键值对
    get_multi   获取多一个键值对

    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('k1','v1')
    result2 = mc.get('k1')
    print(result2)
    # v1
    
    mc.set_multi({'key':'values', 'key1':'values123'})
    resutl = mc.get_multi(['key', 'key1'])
    print(resutl)
    # {'key': 'values', 'key1': 'values123'}

    8、append 和 prepend

    append    修改指定key的值,在该值 后面 追加内容
    prepend   修改指定key的值,在该值 前面 插入内容

    # /usr/bin/env python
    # -*- coding:utf8 -*-
    # auth rain
    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('k1','v1')
    result2 = mc.get('k1')
    print(result2)
    # v1
    
    mc.append('k1','after')
    result = mc.get('k1')
    print(result)
    # v1after
    
    mc.prepend('k1', 'before')
    result1 = mc.get('k1')
    print(result1)
    # beforev1after

    9、decr 和 incr  

    incr  自增,将Memcached中的某一个值增加 N ( N默认为1 )
    decr 自减,将Memcached中的某一个值减少 N ( N默认为1 )

    # /usr/bin/env python
    # -*- coding:utf8 -*-
    # auth rain
    import memcache
    
    mc = memcache.Client(['127.0.0.1:12000'], debug=True)
    mc.set('k1',100)        # 先设置原始值为100
    result2 = mc.get('k1')  
    print(result2)
    # 100
    
    mc.incr('k1')           #自增1, 结果为101
    result = mc.get('k1')
    print(result)
    # 101
    
    mc.decr('k1',2)         # 自减2,默认为1,可以不写
    result1 = mc.get('k1')
    print(result1)
    # 99

    10、gets 和 cas

    gets  获取带有CAS令牌存储的value(数据值) , 如果key 不存在,则返回空

    语法:
    gets key
    多个key使用空格分开:
    gets key1 key2 key3 ..

    cas      (compare-And-Swap) 用于执行一个"检查并设置" 的操作。它仅在当前客户端最后一次取值后,该key对应的值没有被其他客户端修改的情况下,才能够将值写入。检查是通过cas_token参数进行的,这个参数是memcached指定给已经存在的元素的一个唯一的64位的值。

    语法: 
    cas key flags exptime bytes unique_cas_token [noreply]
    value
    • key:键值 key-value 结构中的 key,用于查找缓存值。
    • flags:可以包括键值对的整型参数,客户机使用它存储关于键值对的额外信息 。
    • exptime:在缓存中保存键值对的时间长度(以秒为单位,0 表示永远)
    • bytes:在缓存中存储的字节数
    • unique_cas_token通过 gets 命令获取的一个唯一的64位值。
    • noreply(可选): 该参数告知服务器不需要返回数据
    • value:存储的值(始终位于第二行)(可直接理解为key-value结构中的value)

    如商城商品剩余个数,假设改值保存在memcache中,product_count = 900
    A用户刷新页面从memcache中读取到product_count = 900
    B用户刷新页面从memcache中读取到product_count = 900

    如果A、B用户均购买商品

    A用户修改商品剩余个数 product_count=899
    B用户修改商品剩余个数 product_count=899

    如此一来缓存内的数据便不在正确,两个用户购买商品后,商品剩余还是 899
    如果使用python的set和get来操作以上过程,那么程序就会如上述所示情况!

    如果想要避免此情况的发生,只要使用 gets 和 cas 即可,如:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import memcache
    mc = memcache.Client(['10.211.55.4:12000'], debug=True, cache_cas=True)
     
    v = mc.gets('product_count')
    # ...
    # 如果有人在gets之后和cas之前修改了product_count,那么,下面的设置将会执行失败,剖出异常,从而避免非正常数据的产生
    mc.cas('product_count', "899")

    Ps:本质上每次执行gets时,会从memcache中获取一个自增的数字,通过cas去修改gets的值时,会携带之前获取的自增值和 memcache中的自增值进行比较,如果相等,则可以提交,如果不想等,那表示在gets和cas执行之间,又有其他人执行了gets(获取了缓冲的指 定值), 如此一来有可能出现非正常数据,则不允许修改。

    memcached统计命令:

    stats

    用于返回统计信息,如PID、版本号、连接数等:

    root@test2-ubunut:~/.aliyuncli# telnet localhost 11211
    Trying ::1...
    Trying 127.0.0.1...
    Connected to localhost.
    Escape character is '^]'.
    stats
    STAT pid 9720
    STAT uptime 346412
    STAT time 1469082312
    STAT version 1.4.14 (Ubuntu)
    STAT libevent 2.0.21-stable
    STAT pointer_size 64
    STAT rusage_user 9.024617
    STAT rusage_system 5.018162
    STAT curr_connections 7
    STAT total_connections 41
    STAT connection_structures 8
    STAT reserved_fds 20
    STAT cmd_get 51
    STAT cmd_set 34
    STAT cmd_flush 0
    STAT cmd_touch 0
    STAT get_hits 39
    STAT get_misses 12
    STAT delete_misses 2
    STAT delete_hits 3
    STAT incr_misses 0
    STAT incr_hits 6
    STAT decr_misses 0
    STAT decr_hits 5
    STAT cas_misses 0
    STAT cas_hits 0
    STAT cas_badval 0
    STAT touch_hits 0
    STAT touch_misses 0
    STAT auth_cmds 0
    STAT auth_errors 0
    STAT bytes_read 1431
    STAT bytes_written 2535
    STAT limit_maxbytes 67108864
    STAT accepting_conns 1
    STAT listen_disabled_num 0
    STAT threads 4
    STAT conn_yields 0
    STAT hash_power_level 16
    STAT hash_bytes 524288
    STAT hash_is_expanding 0
    STAT expired_unfetched 0
    STAT evicted_unfetched 0
    STAT bytes 304
    STAT curr_items 4
    STAT total_items 38
    STAT evictions 0
    STAT reclaimed 0
    END
    View Code

    stats items

    用于显示各个slab中item的数目和存储时长(最后一次访问距离到现在的秒数).

    语法:

    stats items
    stats items
    STAT items:1:number 4
    STAT items:1:age 4105
    STAT items:1:evicted 0
    STAT items:1:evicted_nonzero 0
    STAT items:1:evicted_time 0
    STAT items:1:outofmemory 0
    STAT items:1:tailrepairs 0
    STAT items:1:reclaimed 0
    STAT items:1:expired_unfetched 0
    STAT items:1:evicted_unfetched 0
    END
    View Code

    stats slabs

    显示各个slab的信息,包括chunk的大小、数目、使用情况等。

    语法:

    stats slab
    stats slabs
    STAT 1:chunk_size 96
    STAT 1:chunks_per_page 10922
    STAT 1:total_pages 1
    STAT 1:total_chunks 10922
    STAT 1:used_chunks 5
    STAT 1:free_chunks 10917
    STAT 1:free_chunks_end 0
    STAT 1:mem_requested 384
    STAT 1:get_hits 39
    STAT 1:cmd_set 34
    STAT 1:delete_hits 3
    STAT 1:incr_hits 6
    STAT 1:decr_hits 5
    STAT 1:cas_hits 0
    STAT 1:cas_badval 0
    STAT 1:touch_hits 0
    STAT active_slabs 1
    STAT total_malloced 1048512
    END
    View Code

    stats sizes 

    显示所有item和的大小和个数

    返回两列,第一列是item大小,第二列是item的个数

    stats sizes
    STAT 96 4
    END

    flush_all  

    该命令用于清空缓存中的所有 key/value, 提供了一个可选参数 time, 用于在指定的时间后执行清理缓存操作。

    语法:

    flush_all [time] [noreply]
    flush_all
    OK
  • 相关阅读:
    MSDN Magazine搞错了
    Visual Studio 2005中设置调试符号(Debug Symbols)
    BCB 6的问题
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现人与身份证的一对一关系映射
    吴裕雄天生自然Spring BootSpring Data JPA
    吴裕雄天生自然Spring BootSpring Boot对JSP的支持
    吴裕雄天生自然Spring BootSpring Boot的异常统一处理
    吴裕雄天生自然Spring Boot使用Spring Data JPA实现Author与Article的一对多关系映射
    吴裕雄天生自然Spring Boot解决 Error creating bean with name 'entityManagerFactory' defined in class path resource
    吴裕雄天生自然Spring Boot@ExceptionHandler注解和@ControllerAdvice注解
  • 原文地址:https://www.cnblogs.com/yxy-linux/p/5689107.html
Copyright © 2011-2022 走看看