memcached快速上手教程
2022年5月24日大约 3 分钟约 886 字
python-memcached
[TOC]
基本操作
import memcache
mc = memcache.Client(['139.129.5.191:12000'], debug=True)
#-----------------------插入---------------------------
# 覆盖设置(不管键是否存在都覆盖插入并返回True)
mc.set("name", "python")
# 覆盖设置多个键值对
dic = {'name':'to,','age':'19','job':'IT'}
mc.set_multi(dic)
# 添加(如果键已存在,则不添加并返回FALSE,成功则返回True)
mc.add('k1', 'v1')
#----------------------修改----------------------------
# 修改(如果键已存在,则修改并返回True,不存在则不操作并返回False)
mc.replace("k1", "v1")
# 在值后面追加
mc.append('num','追加第二个')
# 在值前面追加
mc.prepend('num','我是零个')
# 自增
mc.incr('num','9')
# 自减
mc.decr('num','5')
#--------------------读取----------------------------
#读取
ret = mc.get('name')
print (ret)
#--------------------删除---------------------------
mc.delete('name')
并发修改
解决并发修改问题的最好办法是减轻时效性的影响,使用memcached CAS(check and set)方式。
CAS基本原理非常简单,一言以蔽之,就是“版本号”,在数据库领域也叫乐观锁。每个存储的数据对象,都有一个版本号。
例子
如果不采用CAS,则有如下的情景:
第一步,A取出数据对象X;
第二步,B取出数据对象X;
第三步,B修改数据对象X,并将其放入缓存;
第四步,A修改数据对象X,并将其放入缓存。
我们可以发现,第四步中会产生数据写入冲突,也就是写入了A持有的过期数据 。
如果采用CAS协议,则是如下的情景。
第一步,A取出数据对象X,并获取到CAS-ID1;
第二步,B取出数据对象X,并获取到CAS-ID2;这里CAS-ID2等于CAS-ID1;
第三步,B修改数据对象X,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“一致”,就将修改后的带有CAS-ID2的X写入到缓存。
第四步,A修改数据对象Y,在写入缓存前,检查CAS-ID与缓存空间中该数据的CAS-ID是否一致。结果是“不一致”,则拒绝写入,返回存储失败。
而使用memcached的CAS方式,可以以几乎0成本的方式解决时效性问题,尽管存在一点小缺陷,但这种缺陷可以通过简单的重试即可解决。
解决
gets和cas命令:
Memcached 1.2.5以及更高版本,提供了gets和cas命令。
incr/decr命令:
Memcached保存的key/value都有一个唯一标识casUnique,在进行incr/decr操作时,首先获取casUnique,执行incr,检验返回值是否casUnique+1,如果是,则更新,否则,失败不更新!
add命令:
Memcache中的Add操作也是原子的,Add操作要不成功要不失败,失败了就是其他线程或者应用已经添加了此key/value.
到现在,我们总结一下Memecache支持的多线程同步的方法
**1. Add命令 **
**2. incr/decr命令 **
3. gets/cas操作
import memcache
mc = memcache.Client(['0.0.0.0:12000'],cache_cas=True)
# 与get功能一样,仅仅是多获取了一个数据的版本号casUnique
regets = mc.gets('count')
# 与set功能一致,只是会用gets获取的该数据版本号对于缓存中版本号是否一致,如果一致则修改,如果不一致,说明我获取的数据是旧数据,修改无效。
recas = mc.cas('count','11')
# 也就是说如果在gets和cas之间数据被其他程序修改,则这次修改不成功。
# 需要重新使用gets获取新的版本号再次用cas修改数据。