• 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
  • 相关阅读:
    将两个数组对比后合并为同一个数组
    invalid reference format: repository name must be lowercase
    Error: too many open files之ulimt
    vim打开文件末尾带有^M
    双层for循环体里,分别跳出外层循环和内层循环
    echarts 多饼图集合多标题
    近1个月订单占比城市TOP6
    javascript 显示日期
    国密SM2,SM4 For Delphi xe 10.3.3
    Datasnap POST 方案
  • 原文地址:https://www.cnblogs.com/yxy-linux/p/5689107.html
Copyright © 2020-2023  润新知