Python自动化开发学习-Memcached

讲师的博客:https://www.cnblogs.com/wupeiqi/p/5132791.html
如果是要在django里使用Memcache缓存,那么下面都不用看了,直接看django里是怎么用的就好了。
这篇里缓存的章节:http://blog.51cto.com/steed/2104127

Memcached

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

和redis比较

貌似Redis要比Memcached好。不过这两个都不错,也都有人在用。仔细比较的话也确实是各有优劣的,比如Redis只使用单核,而Memcached可以使用多核。
具体看这篇吧:https://www.oschina.net/news/26691/memcached-timeout

安装Memcached

Memcached官网:http://memcached.org/
关于安装,可以看这里:https://github.com/memcached/memcached/wiki/Install
可以直接用yum安装:

$ yum install libevent-devel

可能还要安装这个,但是上面的yum安装时并不在依赖关系里:

$ yum install libevent-devel

上面这个我还没有安装。

启动运行

$ memcached -d -m 10 -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid

启动选项:

  • -p <num> : TCP监听端口(default: 11211)
  • -U <num> : UDP监听端口(default: 11211, 0 is off)
  • -s <file> : UNIX套接字路径侦听
  • -a <mask> : UNIX套接字的访问掩码,八进制(默认值:0700)
  • -l <addr> : 侦听接口地址默认为所有地址,可以指定主机加端口可以使用逗号分隔多个地址
  • -d : 作为守护进程运行
  • -r : 最大文件描述符
  • -u <username> : 指定运行用户
  • -m <num> : 最大内存(默认为64 MB)
  • -M : 内存耗尽时返回错误而不删除项目
  • -c <num> : 最大同时连接数默认为1024
  • -k : 锁定所有分页内存
  • -v : 显示错误或警告事件
  • -vv : 详细错误
  • -vvv : 详细错误信息及内部状态转换
  • -h : 打印此帮助
  • -i : 打印内存缓存和许可证
  • -P <file> : 指定PID文件,只与-d选择一起使用
  • -f <factor> : 块大小生长因子,默认值为1.25
  • -n <bytes> : 为键值标志的最小空间,默认为48
  • -L : 使用大内存页,增加的内存页大小可以减少TLB命中数提高性能
  • -D <char> : 使用<char>作为密钥前缀和IDS之间的分隔符
  • -t <num> : 使用的线程数,默认为4
  • -R : 每个事件的最大请求数默认为20
  • -C : 禁用CAS的使用
  • -b <num> : 设置积压队列限制默认值1024
  • -B : 绑定协议——ASCII、二进制或AUTO(默认)之一
  • -I : 重写每个板页的大小。调整最大项目大小(默认值:1MB,MI:1K,MAX:128M)
  • -S : 打开SASL认证
  • -o : 逗号分隔的扩展或实验选项列表

上面如果用后台启动了之后无法关闭,可以先找到守护进程的PID,然后kill掉:

$ ps -aux
$ kill -9 PID

开放防火墙:

$ firewall-cmd --permanent --add-port=11211/tcp
$ firewall-cmd --reload

安装python-memcached模块

直接使用pip安装:

pip install python-memcached

第一次使用:

import memcache

mc = memcache.Client([‘192.168.3.108:11211‘], debug=True)
mc.set(‘k1‘, ‘v1‘)
ret = mc.get(‘k1‘)
print(ret)

这里有个参数,debug=True表示运行出现错误时,显示错误信息,上线后移除该参数。
运行上面的代码前先确认启动了服务端的Memcached,用如下的命令开启吧:

$ memcache -u root -vv

此时,在运行上面的代码,就可以进行设置值和取值的操作了。

天生支持集群

python-memcached模块原生支持集群操作。这里单讲上面的生成memcache.Client实例的这条命令。
实例化的时候传入的第一个参数,是一个列表。既然是列表,就可以传入多个,这样是实现了集群的操作:

mc = memcache.Client([‘192.168.3.108:11211‘, ‘192.168.3.109:11211‘, ‘192.168.3.110:11211‘])

另外,列表中的元素可以是一个元组,元组的第一个元素就是上面的IP地址和端口,第二个元素是数字表示权重:

mc = memcache.Client([(‘192.168.3.108:11211‘, 1), (‘192.168.3.109:11211‘, 3), (‘192.168.3.110:11211‘, 4)])

根据算法将用户要存的key转换成一个数字,将数字和主机列表的长度求值,如此就知道该连接哪一台主机了。加了权重值,就是增加这个主机在主机列表里出现的次数。

基本操作

这里操作的命令比较简单,所以简单了解一下有哪些命令可以操作就好了。

add
添加一条键值对,如果是已经存在的key,会返回False:

res = mc.add(‘k2‘, ‘v2‘)
print(res)  # 设置成功,返回True
res = mc.add(‘k2‘, ‘value2‘)
print(res)  # 设置失败,返回False

这里重复add同一个key,应该是会产生异常的,不过应该是被底层捕获的,不会导致程序崩溃。如果开启了debug,那么会把异常打印出来。

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

mc.replace(‘k1‘, ‘value1‘)

这里的异常和上面add的情况是一样的。set操作就相当于是 add + replace 。

set 和 set_multi
set : 设置一个键值对,如果key不存在,则创建,如果key存在,则修改
set_multi : 设置多个键值对,此时要传入一个字典

res = mc.set(‘k1‘, ‘v1‘)
print(res)  # 设置成功,会返回True
mc.set_multi({‘k11‘: ‘v11‘, ‘k12‘: ‘v12‘, ‘k13‘: ‘v13‘})

set的时候可以直接传数字,应该是会自动帮我们传成字符串保存的:

mc.set(‘n1‘, 100)
print(mc.get(‘n1‘))

get 和 get_multi
get : 获取一个键值对
get_multi : 获取多个键值对,传入一个列表,返回字典

items = mc.get_multi([‘k11‘, ‘k12‘, ‘k13‘])
print(items)

delete 和 delete_multi
delete : 删除指定的一个键值对,可以删除不存在的键值对
delete_multi : 删除指定的多个键值对,如果key不存在,会异常

mc.delete(‘k1‘)
mc.delete_multi([‘k11‘, ‘k12‘, ‘k13‘])

append 和 prepend
append : 修改指定key的值,在该字符串后面追加内容
prepend : 修改指定key的值,在该字符串前面插入内容
在Memcached里只有一个数据格式,就是字符串,所以这里是对字符串的操作:

mc.set(‘s1‘, ‘TEST‘)
print(mc.get(‘s1‘))
mc.append(‘s1‘, ‘ after‘)
print(mc.get(‘s1‘))
mc.prepend(‘s1‘, ‘before ‘)
print(mc.get(‘s1‘))

decr 和 incr
incr : 自增,将某个值增加N,默认加1
decr : 自减,将某个值减少N,默认减1
这里能操作的只能是能是数字形式的字符串,否则程序会抛出异常。这个异常应该是客户端计算是产生的,直接会导致程序崩溃:

mc.set(‘n1‘, ‘123‘)
print(mc.get(‘n1‘))
mc.incr(‘n1‘)
print(mc.get(‘n1‘))
mc.incr(‘n1‘, 100)
print(mc.get(‘n1‘))

设置超时时间
上面的设置值的操作:set、 set_multi、add、replace,都是可以设置超时时间的。通过time参数,单位是秒:

mc.set(‘k1‘, ‘v1‘, time=2)
time.sleep(1)
print(mc.get(‘k1‘))  # 返回设置的值,v1
time.sleep(1)
print(mc.get(‘k1‘))  # 超时,返回None

gets 和 cas
这里提供的方法,是为了解决同时修改某个数据的时候,导致数据一致性问题。
比如A取出了某个值假设是1000,B也取出了这个值1000。A和B都要把数据减1然后回写回去。此时A和B都会尝试把999写回去。这样最终这个数字就不对了。应该是A和B都把数字减少了1,此时最终的数值应该是998。
用这里的gets和cas操作,就可以发生上面的问题。要让这两个命令有效果,需要在创建客户端实例的时候再加一个参数cache_cas=True:

mc = memcache.Client([‘192.168.3.108:11211‘], debug=True, cache_cas=True)

下面是演示这种冲突情况的代码:

# s2a.py
import memcache

mc = memcache.Client([‘192.168.3.108:11211‘], debug=True, cache_cas=True)  # 注意参数
mc.set(‘count‘, 1000)  # 设置一个默认值

n = mc.gets(‘count‘)
input("%s>>>" % n)  # 获取到值之后,先暂停
res = mc.cas(‘count‘, n-1)  # 把计算后的新的值写回
print(res, mc.get(‘count‘))

# s2b.py
import memcache

mc = memcache.Client([‘192.168.3.108:11211‘], debug=True, cache_cas=True)

n = mc.gets(‘count‘)
input("%s>>>" % n)
res = mc.cas(‘count‘, n-1)
print(res, mc.get(‘count‘))

先运行s2a.py,然后再运行s2b.py。此时2个程序都会在获取到值之后暂停。随便让一个程序继续,写回最新的数据。当第二个程序写回的时候就会发生错误,返回False。此时你就知道这里的操作失败了。知道失败了,就再重新执行一个gets和cas的操作应该就可以了。失败返回如下:

1000>>>
MemCached: while expecting ‘STORED‘, got unexpected response ‘EXISTS‘
False 999

这里应该是一个乐观锁的实现。总之就是cas之后检查返回值判断是否成功。如果不成功,表示之前执行的时候有冲突,那么再执行一次。
另外其实数字的加减,是不需要这样做的。对于数字,使用decr 和 incr就不会发生上面的那种冲突的情况。不过如果是字符串操作,比如在前后添加内容,就无法避免了。另外或许处理数字还有其他更复杂的情况,只是还没遇到。

原文地址:http://blog.51cto.com/steed/2342146

时间: 2024-12-28 21:21:39

Python自动化开发学习-Memcached的相关文章

Python自动化开发学习12-MariaDB

关系型数据库 主流的关系型数据库大概有下面这些: Oracle : 甲骨文公司的企业级的数据库 SQL Server : 微软的 MySQL : 免费的数据库,现在也属于Oracle的旗下产品 MariaDB : 开源的数据库,MySQL的一个分支 PostgreSQL : 也是开源的 SQLite : 一款轻量级的数据库 DB2 : IBM的 RDBMS 术语 RDBMS(Relational Database Management System)即关系数据库管理系统,在开始之前,先了解下RD

Python自动化开发学习19-Django

接下来,我们把Django分为视图(View).路由系统(URL).ORM(Model).模板(Templates )这4块进行学习. 视图 提交数据 上节课已经用过 request.POST.get() 获取提交的数据了,现在来看看有多选框的情况,多选的话应该要提交多个数据.先写一个有单选.多选.下拉列表的html: <body> <form action="/choice/" method="post"> <p> 性别: &l

Python自动化开发学习22-Django上

session 上节已经讲了使用Cookie来做用户认证,但是Cookie的问题缺点:敏感信息不适合放在cookie里,敏感信息只能放在服务器端优势:把部分用户数据分散的存放在每个客户端,减轻服务端的压力Cookie是保存在用户浏览器端的键值对,Session是保存在服务器端的键值对.Session依赖Cookie,Cookie保存随机字符串,凭借这个随机字符串获取到服务器端Session里的内容.用Session来优化用户登录:用户登录后,生成一个随机字符串,通过Cookie发送给客户端保存.

python自动化开发学习-9 socket网络编程

一. 简介 python提供了两个级别访问的网络服务: 低级别的网络服务支持节本的socket,它提供了标准的BSD sockets API,可以访问底层操作系统socket接口的全部方法. 高级别的网络服务模块socketserver,它提供了服务器中心类,可以简化网络服务器的开发. socket介绍 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. socket起源于Unix

Python自动化开发学习4-3

JSON 和 pickle 序列化:把数据对象变成字符串的形式,这样可以保存在文件中.反之就是反序列化 python自带的str()可以完成序列化,然后eval()可以反序列化,但是我们先把他们忘记.不知道适用范围是多大. 我们用json的规范来做序列化和反序列化. import json dica = {'name':'Alice',         'age':18,         'from':'ShangHai'         } stra = json.dumps(dica)  #

Python自动化开发学习5

模块 在模块中,我们可以定义变量.函数,还有类(这个还没学到).总之应该就是所有的代码.先建一个文件,取名为module,py,内容如下: # 一下是module.py的内容 string = "This is module,py" def say_hi():     print("Hi") def test():     return "test in module.py" 在上面的模块中我们定义了1个变量和2个函数,现在我们要在另外一个文件中

Python自动化开发学习14

Web的三个层次 网页设计思路是把网页分成三个层次,即:结构层(HTML).表示层(CSS).行为层(Javascript).形象的比喻,先是HTML捏了一个人,然后CSS则是给人穿上衣服,最后通过JS让人动起来. Web服务的本质 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端.用户向服务器发送一个请求.然后服务器响应,将数据和格式发回给客户端,然后断开这个连接.客户端收到返回的数据后,通过浏览器将数据按照一定的格式呈现出来.整个过程就是

Python自动化开发学习15-JavaScript和DOM

初识JavaScript JavaScript(后面都简写为js)是一门独立的语言.浏览器本身就具有js解释器. js的存在形式 和css类似,js代码要放在<script>标签中.同样和css类似,还可以写在一个js文件中,比如文件名就叫 commons.js ,然后在head中引入 <script src="commons.js"></script> ,src的值就是js的文件路径.<script type="text/javas

Python自动化开发学习16-前端内容综合进阶

css补充 这里再补充几个css的知识点,下面会用到 最小宽度-min-width 设置元素的最小宽度.举例说明,比如设置一个百分比的宽度,那么元素的宽度的像素值是会随着页面大小而变化的.如果设置一个最小的像素宽度,那么当变化到最小值之后,不会继续变小.在下面的例子中,会出现滚动条,保证元素的宽度: <body> <div style="height: 80px;width: 100%;background-color: blue;min-width: 800px;"