memcached

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

安装

yum install libevent-devel*
yum install libevent-devel*
wget http://memcached.org/latest
tar zxvf memcached-1.4.29.tar.gz
./configure && make && make test && sudo make install

启动

memcached -d -m 10    -u root  -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

首先,需要安装memcache:pip3 install python-memcached

简单操作

import memcache

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

其中,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 = "v1"),那么要执行一下步骤:

  • 根据算法将 k1 转换成一个数字(unicode对应)
  • 将数字和主机列表长度求余数,得到一个值 N( 0 <= N < 列表长度 )
  • 在主机列表中根据 第2步得到的值为索引获取主机,例如:host_list[N]
  • 连接 将第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')

add

添加一条键值对,如果已经存在的 key,重复执行add操作异常,报错:MemCached: while expecting 'STORED', got unexpected response 'NOT_STORED'

import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.set('foo','bar')
mc.add('cc',23) #如果已经存在'cc'的key,会报错
print(mc.get('cc'))

replace

修改某个key的值,如果key不存在,则异常,报错:MemCached: while expecting 'STORED', got unexpected response 'NOT_STORED'

import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.replace('cc',23)
mc.replace('alex',33) #无'alex' key,会报错

set set_multi

  • set:设置一个键值对,如果key不存在,则创建,如果key存在,则修改
  • set_multi 设置多个键值对,如果key不存在,则创建,如果key存在,则修改,注意参数为字典
import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.set('alex',32)
mc.set_multi({'cc':'niubi','alex':2222})

delete delete_multi

  • delete:删除指定的一个键值对,如果没有指定的key,不会报错
  • delete_multi:删除指定的多个键值对,注意参数为列表
import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.delete('aaa')
mc.delete('alex')
print(mc.get('alex'))
mc.delete_multi(['cc','alex2'])
print(mc.get('alex2'),mc.get('cc'))

get get_multi

  • get:获取一个键值对
  • get_multi:获取多个键值对,参数为列表,返回值为字典类型
import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.set('cc','ccccc')
print(mc.get('cc'))
print(mc.get_multi(['cc','laex','2222']))

out:

ccccc
{'cc': 'ccccc'}

append prepend

  • append:修改指定key的值,在值的后面追加内容,无指定key会报异常
  • prepend:修改指定key的值,在值的前面插入内容
import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.append('cc','dd')
mc.append('ds','dsdsds') #不存在ds,会报异常
print(mc.get('ds'))
mc.prepend('cc','aa')
print(mc.get('cc'))

decr incr

  • incr:自增,将Memcached中的某一个值增加N,(N默认为1),如果值非数字,会报错
  • decr:自减,将Memcached中的某一个值减少N,(N默认为1),如果值非数字,会报错
import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.set('cc',23)
mc.incr('cc')
print(mc.get('cc'))
mc.decr('cc',3)
print(mc.get('cc'))

out:

24
21

gets cas

使用情景:

如商城商品剩余个数,假设改值保存在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

import memcache

mc=memcache.Client(['192.168.4.193:12000'],debug=True)
mc.set('count',999)
print(mc.gets('count'))
# 如果有人在gets之后和cas之前修改了product_count,那么,下面的设置将会执行失败,抛出异常,从而避免非正常数据的产生
mc.cas('count',981)
#cas也能创建一个不存在key的键值对
mc.cas('we',90)
print(mc.gets('we'))

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

memcache是否已经过时?

转自:开源中国社区

源地址,戳我戳我

这两年Redis火得可以,Redis也常常被当作Memcached的挑战者被提到桌面上来。关于Redis与Memcached的比较更是比比皆是。然而,Redis真的在功能、性能以及内存使用效率上都超越了Memcached吗?

下面内容来自Redis作者在stackoverflow上的一个回答,对应的问题是《Is memcached a dinosaur in comparison to Redis?》(相比Redis,Memcached真的过时了吗?)

You should not care too much about performances. Redis is faster per core with small values, but memcached is able to use multiple cores with a single executable and TCP port without help from the client. Also memcached is faster with big values in the order of 100k. Redis recently improved a lot about big values (unstable branch) but still memcached is faster in this use case. The point here is: nor one or the other will likely going to be your bottleneck for the query-per-second they can deliver.
没有必要过多的关心性能,因为二者的性能都已经足够高了。由于Redis只使用单核,而Memcached可以使用多核,所以在比较上,平均每一 个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近 也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。说了这么多,结论是,无论你使用哪一个,每秒处理请求的次数都不会成为瓶 颈。(比如瓶颈可能会在网卡)
You should care about memory usage. For simple key-value pairs memcached is more memory efficient. If you use Redis hashes, Redis is more memory efficient. Depends on the use case.
如果要说内存使用效率,使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。当然,这和你的应用场景和数据特性有关。
You should care about persistence and replication, two features only available in Redis. Even if your goal is to build a cache it helps that after an upgrade or a reboot your data are still there.
如果你对数据持久化和数据同步有所要求,那么推荐你选择Redis,因为这两个特性Memcached都不具备。即使你只是希望在升级或者重启系统后缓存数据不会丢失,选择Redis也是明智的。
You should care about the kind of operations you need. In Redis there are a lot of complex operations, even just considering the caching use case, you often can do a lot more in a single operation, without requiring data to be processed client side (a lot of I/O is sometimes needed). This operations are often as fast as plain GET and SET. So if you don’t need just GEt/SET but more complex things Redis can help a lot (think at timeline caching).
当然,最后还得说到你的具体应用需求。Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在 Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通 常和一般的GET/SET一样高效。所以,如果你需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。

Python操作memecache的更多相关文章

  1. Python之路:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  2. 【转】Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  3. python操作RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  4. python操作nosql数据库之memcache

    一.memcache的安装 1.memcache简介 Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象减少读取数据库的次数,从而 ...

  5. Python操作Redis(一)

    redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串).list(链表).set(集合).zset(sorted set ...

  6. Python(九) Python 操作 MySQL 之 pysql 与 SQLAchemy

    本文针对 Python 操作 MySQL 主要使用的两种方式讲解: 原生模块 pymsql ORM框架 SQLAchemy 本章内容: pymsql 执行 sql 增\删\改\查 语句 pymsql ...

  7. Python 【第六章】:Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

    Memcached Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态.数据库驱动网站的速度 ...

  8. 练习:python 操作Mysql 实现登录验证 用户权限管理

    python 操作Mysql 实现登录验证 用户权限管理

  9. Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy pymsql pymsql是Python中操作MySQL的模块,其使用方法和MySQLdb ...

随机推荐

  1. django 搜索引擎 Elasticsearch 安装使用

    1.使用docker安装elasticsearch a.获取镜像 # 拉取镜像到本地仓库 # docker image pull delron/elasticsearch-ik:2.4.6-1.0 由 ...

  2. PAT Advanced 1073 Scientific Notation (20 分)

    Scientific notation is the way that scientists easily handle very large numbers or very small number ...

  3. JavaScript展开操作符(Spread operator)介绍

    本文介绍JavaScript的展开操作符(Spread operator)....本文适合ES6初学者. 你可以通过展开操作符(Spread operator)...扩展一个数组对象和字符串.展开运算 ...

  4. PWA

    附一个示例e6书写 todolist的示例,切换list的状态: //todolist示例 const toggleTodo = (id)=>{ setTodos(todos => tod ...

  5. python+requests----登录接口reponse中token传递给其他接口使用的一个简单小示例介绍

    #!/usr/bin/env python # coding=UTF-8 import requests def login(): url = "https://xxxx.xxx.xxx/v ...

  6. Java锁--非公平锁

    转载请注明出处:http://www.cnblogs.com/skywang12345/p/3496651.html 参考代码 下面给出Java1.7.0_40版本中,ReentrantLock和AQ ...

  7. 聊聊我理解的ANSI C、ISO C、GNU C、POSIX C

    几句话了解C标准之间的关系 C语言标准 早期的计算机汇编语言是与机器平台紧密耦合的,为了屏蔽这种耦合,增加代码的可移植性,C语言随机出现. 二十世纪八十年代,为了避免各开发厂商用的C语言语法产生差异, ...

  8. list,tuple,set,dict基础

    list # @Auther : chen # @Time : 2018/4/26 19:55 # @File : list_ex.py # @SoftWare : PyCharm # list1 = ...

  9. 智能指针share_ptr记录

    shared_ptr 是一个共享所有权的智能指针,允许多个指针指向同一个对象.shared_ptr 对象除了包括一个对象的指针,还包括一个引用计数器.当每给对象分配一个share_ptr的时候,引用计 ...

  10. Appium自动化测试教程-自学网-monkey参数

    monkey 参数 参数分类 · 常规类参数 · 事件类参数 · 约束类参数 · 调试类参数 常规类参数 常规类参数包括帮助参数和日志信息参数.帮助参数用于输出Monkey命令使用指导:日志信息参数将 ...