zoukankan      html  css  js  c++  java
  • Part01、memcache 缓存

    Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy


    目录

    一、 Memcached

    1. Memcached安装和基本使用
    2. Python操作Memcached
      2.1 set
      2.2 集群操作
      2.3 add
      2.4 replace
      2.5 set 和 set_multi
      2.6 delete 和 delete_multi
      2.7 get 和 get_multi
      2.8 append 和 prepend
      2.9 decr 和 incr  
      2.10 gets 和 cas



    一、 Memcached

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

    1.1 Memcached安装和基本使用

    • 安装Memcached:

      用wget 去http://memcached.org下载最新源码
      tar -zxvf memcached-x.x.x.tar.gz
      cd memcached-x.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

      PS:如果你是在本机的虚拟机内测试,请将IP改为0.0.0.0
    • 参数说明:

      -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..

    1.2 Python操作Memcached

    安装API

    1.2.1 set

    set是最基本的操作,传入两个参数,第一个是name,第二个是这个name对应的value。

    import memcache

    mc
    = memcache.Client(['10.211.55.4:12000'], debug=True)
    mc.set(
    "foo", "bar")
    ret
    = mc.get('foo')
    print(ret)

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


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

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

    代码如下:


    mc = memcache.Client([('1.1.1.1:12000', 1), ('1.1.1.2:12000', 2), ('1.1.1.3:12000', 1)], debug=True)
    mc.set('k1', 'v1')



    1.2.3 add

    添加一条键值对。如果已经存在该 key,则弹出异常。


    mc.add('k1', 'v1')
    mc.add('k1', 'v2') #报错,对已存在的key重复添加!!!


    1.2.4 replace

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


    mc.replace('kkkk','999')

    1.2.5 set 和 set_multi

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


    mc.set('key0', 'jack')
    mc.set_multi({'key1': 'val1', 'key2': 'val2'})

    1.2.6 delete 和 delete_multi

     delete: 删除指定的一个键值对
     delete_multi: 删除指定的多个键值对


    mc.delete('key0')
    mc.delete_multi(['key1', 'key2'])


    1.2.7 get 和 get_multi

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

     
    val = mc.get('key0')
    item_dict = mc.get_multi(["key1", "key2", "key3"])


    1.2.8 append 和 prepend

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


    # k1 = "v1"
    mc.append('k1', 'after')
    # k1 = "v1after"
    mc.prepend('k1', 'before')
    # k1 = "beforev1after"


    1.2.9 decr 和 incr  

     incr : 自增,将值增加 N ( N默认为1 )
     decr :自减,将值减少 N ( N默认为1 )


    mc.set('k1', '777')
    mc.incr('k1')
    # k1 = 778
    mc.incr('k1', 10)
    # k1 = 788
    mc.decr('k1')
    # k1 = 787
    mc.decr('k1', 10)
    # k1 = 777

    1.2.10 gets 和 cas

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

     举个例子:
     >>假设商城某件商品的剩余个数保存在memcache中,product_count = 900
       A用户刷新页面从memcache中读取到product_count = 900
       B用户刷新页面从memcache中读取到product_count = 900

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

       A用户修改后 product_count=899
       B用户修改后 product_count=899 
       如此一来缓存内的数据便不再正确,实际此时product_count应该等于898.
       如果使用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")



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







    GitHub:https://github.com/ju-do-it
    个人博客:https://zhangju.lookdoc.cn
    博客园:https://www.cnblogs.com/zhangju
    Copyright ©2020 Ju-do-it
    【转载文章务必保留出处和署名,谢谢!】
  • 相关阅读:
    dubbo入门(一)
    java中文件操作《一》
    Unity 游戏框架搭建 2019 (七) 自定义快捷键
    凉鞋:我所理解的框架 【Unity 游戏框架搭建】
    Unity 游戏框架搭建 2019 (六) MenuItem 复用
    Unity 游戏框架搭建 2019 (五) 打开所在文件夹
    Unity 游戏框架搭建 2019 (四) 导出 UnityPackage
    Unity 游戏框架搭建 2019 (三) 生成文件名到剪切板
    Unity 游戏框架搭建 2019 (二) 文本复制到剪切板
    Unity 游戏框架搭建 2019 (一) 简介与第一个示例文件名的生成
  • 原文地址:https://www.cnblogs.com/zhangju/p/5720208.html
Copyright © 2011-2022 走看看