python使用memcached

来源:互联网 发布:少儿编程课程要会什么 编辑:程序博客网 时间:2024/06/08 07:12

python使用memcached

转载:http://oursimplehouse.blog.sohu.com/63588732.html


网上对memcached的讨论好火呀!总结一下


安装 memcached:

1、下载memcached-1.2.2.tar.gz

2、tar xvzf memcached-1.2.2.tar.gz

3、./configure;make;make install


安装python API组件:

1、下载python-memcached-1.39.tar.gz

2、tar xvzf python-memcached-1.39.tar.gz

3、python setup.py install


启动memcached

memcached -d -m 64 -l 10.1.41.113 -p 11211

启动的这个memcached为一个后台守护进程模式(-d), 然后缓存的空间为64M(-m), 监听(-l)服务器10.1.41.113的11212号端口(-p)

root下要加-u 指定user参数

memcached -u bj1822 -d -m 64 -l 10.1.41.113 -p 11211


#杀掉缓存

ps aux|grep memcached

killall memcached


#启动缓存                           

/usr/local/memcached/bin/memcached -d -m 1024 -c 2048 -p 7788 -t 8 -u nobody

/usr/local/memcached/bin/memcached -d -m 1024 -c 2048 -p 7789 -t 8 -u nobody


memcached -h

memcached 1.2.2

-p <num>      TCP port number to listen on (default: 11211)

-U <num>      UDP port number to listen on (default: 0, off)

-s <file>     unix socket path to listen on (disables network support)

-l <ip_addr> interface to listen on, default is INDRR_ANY

-d            run as a daemon

-r            maximize core file limit

-u <username> assume identity of <username> (only when run as root)

-m <num>      max memory to use for items in megabytes, default is 64 MB

-M            return error on memory exhausted (rather than removing items)

-c <num>      max simultaneous connections, default is 1024

-k            lock down all paged memory

-v            verbose (print errors/warnings while in event loop)

-vv           very verbose (also print client commands/reponses)

-h            print this help and exit

-i            print memcached and libevent license

-b            run a managed instanced (mnemonic: buckets)

-P <file>     save PID in <file>, only used with -d option

-f <factor>   chunk size growth factor, default 1.25

-n <bytes>    minimum space allocated for key+value+flags, default 48

memcached的基本设置:


-p 监听的端口
-l 连接的IP地址, 默认是本机
-d start 启动memcached服务
-d restart 重起memcached服务
-d stop|shutdown 关闭正在运行的memcached服务
-d install 安装memcached服务
-d uninstall 卸载memcached服务
-u 以的身份运行 (仅在以root运行的时候有效)
-m 最大内存使用,单位MB。默认64MB
-M 内存耗尽时返回错误,而不是删除项
-c 最大同时连接数,默认是1024
-f 块大小增长因子,默认是1.25
-n 最小分配空间,key+value+flags默认是48
-h 显示帮助
mixi的设置,单台:

[/code]
每台memcached服务器仅启动一个memcached进程。分配给memcached的内存为3GB,启动参数如下:


/usr/bin/memcached -p 11211 -u nobody -m 3000 -c 30720
由于使用了x86_64的操作系统,因此能分配2GB以上的内存。32位操作系统中,每个进程最多只能使用2GB内存。也曾经考虑过启动多个分配2GB以下内存的进程,但这样一台服务器上的TCP连接数就会成倍增加,管理上也变得复杂,所以mixi就统一使用了64位操作系统。

另外,虽然服务器的内存为4GB,却仅分配了3GB,是因为内存分配量超过这个值,就有可能导致内存交换(swap)。连载的第2次中前坂讲解过了memcached的内存存储“slab allocator”,当时说过,memcached启动时指定的内存分配量是memcached用于保存数据的量,没有包括“slab allocator”本身占用的内存、以及为了保存数据而设置的管理空间。因此,memcached进程的实际内存分配量要比指定的容量要大,这一点应当注意。

mixi保存在memcached中的数据大部分都比较小。这样,进程的大小要比指定的容量大很多。因此,我们反复改变内存分配量进行验证,确认了3GB的大小不会引发swap,这就是现在应用的数值。



memcached -d -m 1024 -u root -l 172.25.38.70 -p 12000 -c 4096 -P /tmp/memcached.pid   12000
-p 12000 端口
-m 1024  内存设置 1024
-c 4096  同时连接数

编写python程序:

import memcache, time

mc = memcache.Client(['10.1.41.113:11211'], debug=0)

连接到10.1.41.113的11211端口,也就是memcachd启动的端口。


mc.set("some_key", "Some value")

设置key和value,第三个参数默认为0,也就是数据永不超时。

如果这样设置:

mc.set("some_key", "Some value",1)

表示一秒后超时

过两秒打印value的话

time.sleep ( 2)

value = mc.get("some_key")

print value

结果就是None了。


删除

mc.set("another_key", 3)

mc.delete("another_key")                                                                                                           

自增和自减

mc.set("key", "1")                                                                                

mc.incr("key")                                                                                

mc.decr("key")          


关于LRU

LRU是缓冲超过存储上限时删掉队尾也就是最长时间没人访问的元素,参数是-M。但设置了-M和过期时效会存在将未失效的元素删去的风险。所以网上有人改了下代码,增加对过期时效的判断:


返回超时时间的代码:

if (exptime > REALTIME_MAXDELTA) 

     return (rel_time_t) (exptime - stats.started);   

else { 

     return (rel_time_t) (exptime + current_time); 

}

memcached的失效时间格式有两种,当大于60*60*24*30也就是30天的秒数时就是过期距1970年1月1日零时的秒数,否则是有效的秒数。


删除cache的代码:

for (search = tails[id]; tries>0 && search; tries--, search=search->prev) { 

if (search->refcount==0) { 

   item_unlink(search); 

    break; 

}

增加条件:

search->exptime && search->exptime <= current_time 

这样就可以保证删除的都是过期了的元素了。


3.小例子演示

将memcached.pyc拷贝到工作目录

#!/usr/bin/env python import memcache mc = memcache.Client(['127.0.0.1:12000'],debug=0)mc.set("foo","bar")value = mc.get("foo")print value

输出得到bar

4.Python-memcached API总结

整个memcache.py只有1241行,相当精简

主要方法如下:

@set(key,val,time=0,min_compress_len=0)

无条件键值对的设置,其中的time用于设置超时,单位是秒,而min_compress_len则用于设置zlib压缩(注:zlib是提供数据压缩用的函式库)

@set_multi(mapping,time=0,key_prefix='',min_compress_len=0)

设置多个键值对,key_prefix是key的前缀,完整的键名是key_prefix+key, 使用方法如下

  >>> mc.set_multi({'k1' : 1, 'k2' : 2}, key_prefix='pfx_') == []

  >>> mc.get_multi(['k1', 'k2', 'nonexist'], key_prefix='pfx_') == {'k1' : 1, 'k2' : 2}

@add(key,val,time=0,min_compress_len=0)

添加一个键值对,内部调用_set()方法

@replace(key,val,time=0,min_compress_len=0)

替换value,内部调用_set()方法

@get(key)

根据key去获取value,出错返回None

@get_multi(keys,key_prefix='')

获取多个key的值,返回的是字典。keys为key的列表

@delete(key,time=0)

删除某个key。time的单位为秒,用于确保在特定时间内的set和update操作会失败。如果返回非0则代表成功

@incr(key,delta=1)

自增变量加上delta,默认加1,使用如下

>>> mc.set("counter", "20")  

>>> mc.incr("counter")

21

@decr(key,delta=1)

自减变量减去delta,默认减1

5._set方法

很多方法内部都调用了_set方法,其源码如下:

   def _set(self, cmd, key, val, time, min_compress_len = 0):          self.check_key(key)          server, key = self._get_server(key)          if not server:              return 0            self._statlog(cmd)            store_info = self._val_to_store_info(val, min_compress_len)          if not store_info: return(0)            if cmd == 'cas':              if key not in self.cas_ids:                  return self._set('set', key, val, time, min_compress_len)              fullcmd = "%s %s %d %d %d %d\r\n%s" % (                      cmd, key, store_info[0], time, store_info[1],                      self.cas_ids[key], store_info[2])          else:              fullcmd = "%s %s %d %d %d\r\n%s" % (                      cmd, key, store_info[0], time, store_info[1], store_info[2])            try:              server.send_cmd(fullcmd)              return(server.expect("STORED") == "STORED")          except socket.error, msg:              if isinstance(msg, tuple): msg = msg[1]              server.mark_dead(msg)          return 0

注: memcached 的客户端使用TCP链接与服务器通讯, 一个运行中的memcached服务器监视一些端口, 客户端连接这些端口,发送命令到服务器,读取回应,最后关闭连接。(具体命令请参考《Memcached 协议中文版》)

 

6.python-memcached线程安全

本部分转自http://weavesky.com/2009/01/22/is-python-memcached-threadsafe/

python-memcached是不是线程安全的

答案是肯定的,前提你在使用Python 2.4+和python-memcached 1.36+
为什么我们需要线程安全的memcached client,因为我们的实际应用一般是多线程的模型,例如cherrypy、twisted,如果python-memcached不是线程安全的话,引起的问题不仅仅是并发修改共享变量这么简单,是外部socket链接的数据流的混乱
python-memcached怎么实现线程安全的呢?查看源代码看到

try:    # Only exists in Python 2.4+    from threading import localexcept ImportError:    # TODO:  add the pure-python local implementation    class local(object):        pass class Client(local):

 

很取巧的让Client类继承threading.local,也就是Client里面的每一个属性都是跟当前线程绑定的。实现虽然不太优雅,但是很实在但是别以为这样就可以随便在线程里面用python-memcached了,因为这种thread local的做法,你的应用必须要使用thread pool的模式,而不能不停创建销毁thread,因为每一个新线程的创建,对于就会使用一个全新的Client,也就是一个全新的socket链接,如果不停打开创建销毁thread的话,就会导致不停的创建销毁socket链接,导致性能大量下降。幸好,无论是cherrypy还是twisted,都是使用了thread pool的模式


0 0
原创粉丝点击