zoukankan      html  css  js  c++  java
  • python---Memcached

    Memcached

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

    Memcached安装和基本使用

    服务端Memcached安装:

    1 用wget 去http://memcached.org下载最新源码
    2 tar -zxvf memcached-x.x.x.tar.gz
    3 cd memcached-x.x.x
    4 ./configure && make && make test && sudo make install
    5 PS:依赖libevent,需要提前安装
    6 yum install libevent-devel
    7 #apt-get install libevent-dev

    启动Memcached:

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

    Memcached命令:

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

    Python操作Memcached

    安装API:

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

    简单的操作示例:

     1 #!/usr/bin/env python3
     2 #coding:utf8
     3 import memcache
     4 #链接
     5 mc = memcache.Client(['139.129.5.191:12000'], debug=True)
     6 #插入
     7 mc.set("name", "python")
     8 #读取
     9 ret = mc.get('name')
    10 print (ret)
    11  
    12 # 输出结果
    13 python
    14  
    15 # debug=True表示运行出现错误时,可以显示错误信息,正式环境可以不加

    天生支持集群:

      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 = "value1"),那么要执行以下步骤:

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

    代码如下:

    1 #!/usr/bin/env python3
    2 #coding:utf8
    3 import memcache
    4 mc = memcache.Client([('1.1.1.1:12000', 1), ('1.1.1.2:12000', 2),('1.1.1.3:12000',3)])
    5 mc.set('k1','value1')
    6 ret = mc.get('k1')
    7 print (ret)

    基本memcached操作:

    • add        添加一条键值对,如果已经存在的key,重复执行add操作会出现异常。
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 mc = memcache.Client(['0.0.0.0:12000'])
     5 mc.add('k1', 'v1')
     6 mc.add('k1', 'v2') # 报错,对已经存在的key重复添加,失败!!!
     7 例如:
     8 ret1 = mc.add('name','tom')
     9 print(refalse)
    10 ret2 = mc.add('name','jack')
    11 print(retrue)
    12 结果:
    13 False #当已经存在key 那么返回false
    14 True  #如果不存在key     那么返回treue  
    • replace    replace修改某个key的值,如果key不存在,则异常
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 mc = memcache.Client(['0.0.0.0:12000'])
     5 mc.set('name','tom')
     6 re = mc.get('name')
     7 print(re)
     8 rereplace = mc.replace('name','jack')
     9 re = mc.get('name')
    10 print(rereplace,re)
    11 结果:
    12 tom  #第一次赋值
    13 True jack #如果存在key那么修改成功为yaoyao 返回True
    14 rereplace = mc.replace('name1','hahaha')
    15 re = mc.get('name1')
    16 print(rereplace,re)
    17 结果:
    18 False None #如果不存在key,修改失败,返回空值
    • set 和 set_multi

    set : 设置一个键值对,如果Key不存在,则创建,如果key存在,则修改。

    set_multi : 设置多个键值对,如果key不存在,则创建,如果key存在,则修改。

     1 import memcache
     2 mc = memcache.Client(['0.0.0.0:12000'])
     3 mc.set('name','tom')
     4 re = mc.get('name')
     5 print('set用法',re) #设置一个键值对
     6 dic = {'name':'to,','age':'19','job':'IT'}
     7 mc.set_multi(dic)  #设置多个键值对
     8 #或者mc.set_multi({'name':'tom','age':'19','job':'IT'})
     9 mcname = mc.get('name')
    10 mcage = mc.get('age')
    11 mcjob = mc.get('job')
    12 print('set_multi用法:',mcname,mcage,mcjob)
    • delete 和 delete_multi

    delete : 在Memcached中删除指定的一个键值对。

    delete_multi : 在Memcached中删除指定多个键值对。

    import memcache
    mc = memcache.Client(['0.0.0.0:12000'])
    mc.set('name','tom')
    re = mc.get('name')
    print('存在',re)
    mc.delete('name')
    re = mc.get('name')
    print('删除',re)  #删除一个键值对
    • get 和 get_multi

    get : 获取一个键值对。

    get_multi : 获取多个键值对。

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 mc = memcache.Client(['0.0.0.0:12000'])
     5 mc.set('name','tom')
     6 re = mc.get('name')
     7 print('get',re)     #获取一个键值对
     8 dic = {'name':'to,','age':'19','job':'IT'}
     9 mc.set_multi(dic)
    10 regetmu=mc.get_multi(['name','age','job'])
    11 print('get_multi',re) #获取多个键值对的值
    • append 和 prepend

    append : 修改指定key的值,在该值后面追加内容。

    prepend : 修改指定key的值,在该值前面插入内容。

     1 import memcache
     2 mc = memcache.Client(['0.0.0.0:12000'])
     3 mc.set('num','第一|')
     4 re = mc.get('num')
     5 print(re)
     6 mc.append('num','追加第二个') #在第一后面追加
     7 re = mc.get('num')
     8 print(re)
     9 mc.prepend('num','我是零个')  #在第一前面追加
    10 re = mc.get('num')
    11 print(re)
    12 结果:
    13 第一|
    14 第一|追加第二个
    15 我是零个第一|追加第二个
    • decr 和 incr

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

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

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 mc = memcache.Client(['0.0.0.0:12000'])
     5 mc.set('num','1')
     6 re = mc.get('num')
     7 print('我是没加过的值',re)
     8 mc.incr('num','9')
     9 re = mc.get('num')
    10 print('我是加上新增后的值',re)
    11 mc.decr('num','5')
    12 re = mc.get('num')
    13 print('我是减去的值',re)
    14 # 结果:
    15 我是没加过的值 1
    16 我是加上新增后的值 10
    17 是减去的值 5
    • gets 和 cas

    使用缓存系统共享数据资源就必然绕不开数据争夺和脏数据(数据混乱)的问题。

    假设商城某件商品的剩余个数保存在memcache中,product_count = 900

    A用户刷新页面从memecache中读取到product_count = 900

    B用户刷新页面从memecache中读取到product_count = 900

    A,B用户均购买商品,并修改product_count的值

    A修改后,product_count = 899

    B修改后,product_count = 899

    然而正确数字应该是898,数据就混乱了。

    如果想要避免这种情况的发生,则可以使用  gets 和 cas

     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 import memcache
     4 mc = memcache.Client(['0.0.0.0:12000'],cache_cas=True)
     5 mc.set('count','10')
     6 reget = mc.get('count')
     7 print('件数',reget)
     8 regets = mc.gets('count')
     9 print(regets)
    10 # 如果有人在gets之后和cas之前修改了product_count,那么,
    11 下面的设置将会执行失败,剖出异常,从而避免非正常数据的产生
    12 recas = mc.cas('count','11')
    13 print(recas)
    14 regets = mc.gets('count')
    15 print('修改',regets)

    本质上每次执行gets时,会从memcache中获取一个自增的数字,通过cas去修改gets的值时,会携带之前获取的自增和memcache中的自增值进行比较,如果相等,则可以提交,如果不相等,那么表示在gets和cas执行之间,又有其他人执行了gets,则不允许修改。

  • 相关阅读:
    461. Hamming Distance
    342. Power of Four
    326. Power of Three
    368. Largest Divisible Subset java solutions
    95. Unique Binary Search Trees II java solutions
    303. Range Sum Query
    160. Intersection of Two Linked Lists java solutions
    88. Merge Sorted Array java solutions
    67. Add Binary java solutions
    14. Longest Common Prefix java solutions
  • 原文地址:https://www.cnblogs.com/xiao1/p/5858967.html
Copyright © 2011-2022 走看看