- 浏览: 2663750 次
- 来自: 杭州
文章分类
- 全部博客 (1188)
- webwork (4)
- 网摘 (18)
- java (103)
- hibernate (1)
- Linux (85)
- 职业发展 (1)
- activeMQ (2)
- netty (14)
- svn (1)
- webx3 (12)
- mysql (81)
- css (1)
- HTML (6)
- apache (3)
- 测试 (2)
- javascript (1)
- 储存 (1)
- jvm (5)
- code (13)
- 多线程 (12)
- Spring (18)
- webxs (2)
- python (119)
- duitang (0)
- mongo (3)
- nosql (4)
- tomcat (4)
- memcached (20)
- 算法 (28)
- django (28)
- shell (1)
- 工作总结 (5)
- solr (42)
- beansdb (6)
- nginx (3)
- 性能 (30)
- 数据推荐 (1)
- maven (8)
- tonado (1)
- uwsgi (5)
- hessian (4)
- ibatis (3)
- Security (2)
- HTPP (1)
- gevent (6)
- 读书笔记 (1)
- Maxent (2)
- mogo (0)
- thread (3)
- 架构 (5)
- NIO (5)
- 正则 (1)
- lucene (5)
- feed (4)
- redis (17)
- TCP (6)
- test (0)
- python,code (1)
- PIL (3)
- guava (2)
- jython (4)
- httpclient (2)
- cache (3)
- signal (1)
- dubbo (7)
- HTTP (4)
- json (3)
- java socket (1)
- io (2)
- socket (22)
- hash (2)
- Cassandra (1)
- 分布式文件系统 (5)
- Dynamo (2)
- gc (8)
- scp (1)
- rsync (1)
- mecached (0)
- mongoDB (29)
- Thrift (1)
- scribe (2)
- 服务化 (3)
- 问题 (83)
- mat (1)
- classloader (2)
- javaBean (1)
- 文档集合 (27)
- 消息队列 (3)
- nginx,文档集合 (1)
- dboss (12)
- libevent (1)
- 读书 (0)
- 数学 (3)
- 流程 (0)
- HBase (34)
- 自动化测试 (1)
- ubuntu (2)
- 并发 (1)
- sping (1)
- 图形 (1)
- freemarker (1)
- jdbc (3)
- dbcp (0)
- sharding (1)
- 性能测试 (1)
- 设计模式 (2)
- unicode (1)
- OceanBase (3)
- jmagick (1)
- gunicorn (1)
- url (1)
- form (1)
- 安全 (2)
- nlp (8)
- libmemcached (1)
- 规则引擎 (1)
- awk (2)
- 服务器 (1)
- snmpd (1)
- btrace (1)
- 代码 (1)
- cygwin (1)
- mahout (3)
- 电子书 (1)
- 机器学习 (5)
- 数据挖掘 (1)
- nltk (6)
- pool (1)
- log4j (2)
- 总结 (11)
- c++ (1)
- java源代码 (1)
- ocr (1)
- 基础算法 (3)
- SA (1)
- 笔记 (1)
- ml (4)
- zokeeper (0)
- jms (1)
- zookeeper (5)
- zkclient (1)
- hadoop (13)
- mq (2)
- git (9)
- 问题,io (1)
- storm (11)
- zk (1)
- 性能优化 (2)
- example (1)
- tmux (1)
- 环境 (2)
- kyro (1)
- 日志系统 (3)
- hdfs (2)
- python_socket (2)
- date (2)
- elasticsearch (1)
- jetty (1)
- 树 (1)
- 汽车 (1)
- mdrill (1)
- 车 (1)
- 日志 (1)
- web (1)
- 编译原理 (1)
- 信息检索 (1)
- 性能,linux (1)
- spam (1)
- 序列化 (1)
- fabric (2)
- guice (1)
- disruptor (1)
- executor (1)
- logback (2)
- 开源 (1)
- 设计 (1)
- 监控 (3)
- english (1)
- 问题记录 (1)
- Bitmap (1)
- 云计算 (1)
- 问题排查 (1)
- highchat (1)
- mac (3)
- docker (1)
- jdk (1)
- 表达式 (1)
- 网络 (1)
- 时间管理 (1)
- 时间序列 (1)
- OLAP (1)
- Big Table (0)
- sql (1)
- kafka (1)
- md5 (1)
- springboot (1)
- spring security (1)
- Spring Boot (3)
- mybatis (1)
- java8 (1)
- 分布式事务 (1)
- 限流 (1)
- Shadowsocks (0)
- 2018 (1)
- 服务治理 (1)
- 设计原则 (1)
- log (0)
- perftools (1)
最新评论
-
siphlina:
课程——基于Python数据分析与机器学习案例实战教程分享网盘 ...
Python机器学习库 -
san_yun:
leibnitz 写道hi,我想知道,无论在92还是94版本, ...
hbase的行锁与多版本并发控制(MVCC) -
leibnitz:
hi,我想知道,无论在92还是94版本,更新时(如Puts)都 ...
hbase的行锁与多版本并发控制(MVCC) -
107x:
不错,谢谢!
Latent Semantic Analysis(LSA/ LSI)算法简介 -
107x:
不错,谢谢!
Python机器学习库
答案是肯定的,前提你在使用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 local except 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的模式。
但是不幸的是gevent不是thread pool的模式,这导致不停的创建销毁socket链接。
=============================
File: "/data1/duitang/dist/app/test/7199/duitang/common/templatetags/myTags.py", line 525, in statichtml
return StaticHTML_Tag(static_name)
File: "/data1/duitang/dist/app/test/7199/duitang/common/templatetags/myTags.py", line 507, in __init__
sh = StaticHTML.objects.get(name=name)
File: "/data1/duitang/dist/app/test/7199/duitang/statichtml/manager.py", line 18, in get
model = key and cache.get(key)
File: "/data1/duitang/dist/app/test/7199/duitang/perf/memcached.py", line 25, in get
rp = super(MemcachedCache, self).get(key, deault, version)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/django/core/cache/backends/memcached.py", line 58, in get
val = self._cache.get(key)
File: "build/bdist.linux-x86_64/egg/gevent/local.py", line 180, in __getattribute__
_init_locals(self)
File: "build/bdist.linux-x86_64/egg/gevent/local.py", line 167, in _init_locals
cls.__init__(self, *args, **kw)
File: "/data1/duitang/dist/app/test/7199/duitang/memcache.py", line 168, in __init__
print cf1.stacktraces()
File: "/data1/duitang/dist/app/test/7199/duitang/cf1.py", line 8, in stacktraces
for filename, lineno, name, line in traceback.extract_stack(stack):
========================================================
# ThreadID: 47316030715200
File: "build/bdist.linux-x86_64/egg/gevent/greenlet.py", line 390, in run
result = self._run(*self.args, **self.kwargs)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/gunicorn-0.14.6-py2.7.egg/gunicorn/workers/async.py", line 44, in handle
self.handle_request(req, client, addr)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/gunicorn-0.14.6-py2.7.egg/gunicorn/workers/ggevent.py", line 88, in handle_request
super(GeventWorker, self).handle_request(*args)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/gunicorn-0.14.6-py2.7.egg/gunicorn/workers/async.py", line 78, in handle_request
respiter = self.wsgi(environ, resp.start_response)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 273, in __call__
response = self.get_response(request)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
response = callback(request, *callback_args, **callback_kwargs)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/django/utils/decorators.py", line 93, in _wrapped_view
response = view_func(request, *args, **kwargs)
File: "/data1/duitang/dist/app/test/7199/duitang/people/views_people.py", line 45, in peopleIndex
people = AuthUser.objects.get(id=UserProfile.get_real_id(user_id))
File: "/data1/duitang/dist/app/test/7199/duitang/common/user.py", line 19, in get
model = key and cache.get(key)
File: "/data1/duitang/dist/app/test/7199/duitang/perf/memcached.py", line 25, in get
rp = super(MemcachedCache, self).get(key, deault, version)
File: "/duitang/dist/sys/python/lib/python2.7/site-packages/django/core/cache/backends/memcached.py", line 58, in get
val = self._cache.get(key)
File: "build/bdist.linux-x86_64/egg/gevent/local.py", line 180, in __getattribute__
_init_locals(self)
File: "build/bdist.linux-x86_64/egg/gevent/local.py", line 167, in _init_locals
cls.__init__(self, *args, **kw)
File: "/data1/duitang/dist/app/test/7199/duitang/memcache.py", line 168, in __init__
print cf1.stacktraces()
File: "/data1/duitang/dist/app/test/7199/duitang/cf1.py", line 8, in stacktraces
for filename, lineno, name, line in traceback.extract_stack(stack):
可以发现threading local最后委托给gevent/local.py实现,导致重复初始化Client。
而uwsgi只有初始化时才调用,后续刷新页面不再触发Client.init()
google了一下,老外的解决方案: https://groups.google.com/forum/?fromgroups=#!topic/gevent/ULKUPvbaQ7I
python memcache客户端比较
对于memcached,redis,hessian,mongo等各种客户端都要考虑一个问题,如何高效安全地和server进行通信?有几种策略:
1. 每次调用都建立和关闭连接
优点:实现简单,不存在线程安全问题。django的BaseMemcachedCache实现就是每次执行完都会close掉连接。
缺点:出现大量TIME_WAIT,花费在建立网络连接上的开销比较大,在有些情况下会导致性能瓶颈。
2.单一socket长线程
优点:不会出现大量TIME_WAIT,不会频繁开关socket,减轻服务器的压力。
缺点:远程调用一般是请求/问答式,为了保证线程安全必须加同步锁,如果远程服务器响应慢的话会导致大量线程竞争同一个socket资源,socket成为瓶颈。
3.单一socket长线程+连接池
为了解决方案1和方案2的问题,我们采用方案3:保持长连接不变,但采用连接池来保存长连接,这样系统内有一批socket供程序调用,避免大量线程竞争同一个socket。
那么python memcached client采用那种形式呢?
首先python memcached client有好几个,在memcached的官方网站提供了client列表(http://code.google.com/p/memcached/wiki/Clients):
a.libmemcached: 最受欢迎的memcached的C语言版本的客户端的,高性能,线程安全。很多语言都有对这个版本的wrapper。
b.pylibmc:是对libmemcached的wrapper。 http://sendapatch.se/projects/pylibmc/
c.python-memcached: 是100%纯python的版本,也是我们现在正在使用的版本。 http://www.tummy.com/Community/software/python-memcached/
d.Python libmemcached: 豆瓣提供的,对libmemcached的wrapper版本。http://code.google.com/p/python-libmemcached/
e.django cahce: django对memcached的支持,其实django只是提供了一个统一的cache接口,并没有具体实现,相关实现类在django.core.cache.backends.memcached.BaseMemcachedCache ,具体参考:https://docs.djangoproject.com/en/dev/topics/cache/ 不过django的问题很多。
python-memcached
python-memcached不会在每次get/set操作完成之后主动关闭连接,他是一种长连接,但他如果保证线程安全呢?一般我们是这样使用它:
import memcache
mc = memcache.Client(['127.0.0.1:11211'], debug=0)
答案在于他很取巧的让Client类继承threading.local,也就是Client里面的每一个属性都是跟当前线程绑定。这样每个线程都只会看到本地的Client,变相的实现了连接池。
这个池的大小取决于系统有多少个线程。为了验证这个说法,我们写一个程序来测试。
[code]
import memcache
import threading
mc = memcache.Client(['127.0.0.1:11211'], debug=1)
class TestThread(threading.Thread):
def __init__(self,redis_cache):
threading.Thread.__init__(self)
self.redis_cache = redis_cache
def run(self):
while True:
obj = self.redis_cache.get("uid:1002")
if not obj:
self.redis_cache.set("uid:1002","test",1)
print obj
for i in xrange(8):
t = TestThread(mc)
t.start()
[/code]
执行这段程序,然后通过netstat -an查看,刚好有一个8个ESTABLISHED,每个进程一个socket。
python的locale和java的ThreadLocl是一个意思,把值设置到线程中,每个线程只能看到自己线程保存的值,这里面的实现是这样的,由于Client继承于local,当访问Cient的任何一个方法或者属性都会进入到__getattribute__(),其内部实现是获取到当前线程并绑定 相关代码如下:
def _patch(self): key = object.__getattribute__(self, '_local__key') d = current_thread().__dict__.get(key) if d is None: d = {} current_thread().__dict__[key] = d object.__setattr__(self, '__dict__', d) # we have a new instance dict, so call out __init__ if we have # one cls = type(self) if cls.__init__ is not object.__init__: args, kw = object.__getattribute__(self, '_local__args') cls.__init__(self, *args, **kw) else: object.__setattr__(self, '__dict__', d)
cls是当前对象的class,object是基类class,我打印了清单:
new : <class 'duitang.memcache.Client'> | <type 'object'>
--------------------
cached: <class 'gevent.local.local'> | <slot wrapper '__init__' of 'object' objects> | <slot wrapper '__init__' of 'object' objects>
yunpeng@yunpeng-duitang:~/test2$ netstat -an | grep 11211
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN
tcp 31 0 127.0.0.1:46835 127.0.0.1:11211 ESTABLISHED
tcp 0 0 127.0.0.1:46832 127.0.0.1:11211 ESTABLISHED
tcp 0 0 127.0.0.1:46831 127.0.0.1:11211 ESTABLISHED
tcp 0 0 127.0.0.1:46829 127.0.0.1:11211 ESTABLISHED
tcp 0 14 127.0.0.1:46833 127.0.0.1:11211 ESTABLISHED
tcp 31 0 127.0.0.1:46828 127.0.0.1:11211 ESTABLISHED
tcp 0 0 127.0.0.1:46834 127.0.0.1:11211 ESTABLISHED
tcp 31 0 127.0.0.1:46830 127.0.0.1:11211 ESTABLISHED
当python进程退出socket会被自动关闭。
yunpeng@yunpeng-duitang:/duitang/dist/app/trunk/duitang$ netstat -an | grep 11211
tcp 0 0 0.0.0.0:11211 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:44900 127.0.0.1:11211 TIME_WAIT
但是很明显,采用threading locale这种方式来保证线程安全存在一些缺陷:
1.要求web server采用thread pool的方式,如果thread每次执行完之后就结束了,这会导致不停的创建销毁socket链接。
2.要求使用python thread locale的语义,但不幸的是python的thread语义很容易被改变,gevent就可以直接把python的一个thread转换成greenlet。
gevent的monkey提供的patch方法
patch_all() 调用所有的monkey patch
patch_os() os.fork()替换成gevent.fork
patch_select(aggressive=False) `select.select`替换成`gevent.select.select`
patch_socket(dns=True, aggressive=True) 标准的socket object 替换成 gevent's cooperative sockets.
patch_thread(threading=True, _threading_local=True) thread` module 替换成 gevent's thread
patch_time() 把标准的`time.sleep` 替换成`gevent.sleep`.
gunicorn如何使用gevent?
代码:
/duitang/dist/sys/python/lib/python2.7/site-packages/gunicorn-0.14.6-py2.7.egg/gunicorn/workers/ggevent.py
# -*- coding: utf-8 - # # This file is part of gunicorn released under the MIT license. # See the NOTICE for more information. from __future__ import with_statement import os import sys from datetime import datetime # workaround on osx, disable kqueue if sys.platform == "darwin": os.environ['EVENT_NOKQUEUE'] = "1" try: import gevent except ImportError: raise RuntimeError("You need gevent installed to use this worker.") from gevent.pool import Pool from gevent.server import StreamServer from gevent import pywsgi import gunicorn from gunicorn.workers.async import AsyncWorker VERSION = "gevent/%s gunicorn/%s" % (gevent.__version__, gunicorn.__version__) BASE_WSGI_ENV = { 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_SOFTWARE': VERSION, 'SCRIPT_NAME': '', 'wsgi.version': (1, 0), 'wsgi.multithread': False, 'wsgi.multiprocess': False, 'wsgi.run_once': False } class GeventWorker(AsyncWorker): server_class = None wsgi_handler = None @classmethod def setup(cls): from gevent import monkey monkey.noisy = False monkey.patch_all() def timeout_ctx(self): return gevent.Timeout(self.cfg.keepalive, False) def run(self): self.socket.setblocking(1) pool = Pool(self.worker_connections) if self.server_class is not None: server = self.server_class( self.socket, application=self.wsgi, spawn=pool, log=self.log, handler_class=self.wsgi_handler) else: server = StreamServer(self.socket, handle=self.handle, spawn=pool) server.start() pid = os.getpid() try: while self.alive: self.notify() if pid == os.getpid() and self.ppid != os.getppid(): self.log.info("Parent changed, shutting down: %s", self) break gevent.sleep(1.0) except KeyboardInterrupt: pass try: # Try to stop connections until timeout self.notify() server.stop(timeout=self.cfg.graceful_timeout) except: pass def handle_request(self, *args): try: super(GeventWorker, self).handle_request(*args) except gevent.GreenletExit: pass if gevent.version_info[0] == 0: def init_process(self): #gevent 0.13 and older doesn't reinitialize dns for us after forking #here's the workaround import gevent.core gevent.core.dns_shutdown(fail_requests=1) gevent.core.dns_init() super(GeventWorker, self).init_process() class GeventResponse(object): status = None headers = None response_length = None def __init__(self, status, headers, clength): self.status = status self.headers = headers self.response_length = clength class PyWSGIHandler(pywsgi.WSGIHandler): def log_request(self): start = datetime.fromtimestamp(self.time_start) finish = datetime.fromtimestamp(self.time_finish) response_time = finish - start resp = GeventResponse(self.status, self.response_headers, self.response_length) req_headers = [h.split(":", 1) for h in self.headers.headers] self.server.log.access(resp, req_headers, self.environ, response_time) def get_environ(self): env = super(PyWSGIHandler, self).get_environ() env['gunicorn.sock'] = self.socket env['RAW_URI'] = self.path return env class PyWSGIServer(pywsgi.WSGIServer): base_env = BASE_WSGI_ENV class GeventPyWSGIWorker(GeventWorker): "The Gevent StreamServer based workers." server_class = PyWSGIServer wsgi_handler = PyWSGIHandler
测试:ab -n100 http://7199.t.duitang.com:7199/cache/
[admin@server2 duitang]$ netstat -an| grep 11211 |wc -l
306
总结:使用了gevent之后thread local有太多不可控.
gevent代码:/duitang/dist/sys/python/lib/python2.7/site-packages/gevent
gevent+django:http://www.slideshare.net/mahendram/scaling-django-with-gevent
发表评论
-
python读取图片exif信息
2014-11-06 10:53 2407f = open("/home/admin/tlo ... -
Python程序的执行原理
2014-04-14 15:44 17331. 过程概述 Python先把代码(.py文件)编译成字 ... -
如何创建一个短链服务
2013-12-26 16:23 0参考: http://stackoverflow.com ... -
python 解析命令参数(argument)组件argparse
2013-12-11 17:35 1410参考: http://youngsterxyf.githu ... -
pyhon命令行工具optparse
2013-11-10 16:27 1045使用python optparse 可以创建命令行工具,下面 ... -
Python在豆瓣的应用
2013-10-21 10:46 1202Python在豆瓣的应用,hongqiangning分享 ... -
用python爬虫抓站的一些技巧总结
2013-10-10 14:12 1686学用python也有3个多月了,用得最多的还是各类爬虫 ... -
python小技巧
2013-10-10 11:50 7481. 声明长度256的数组 a=[0]*256 ... -
使用tesseract-ocr破解网站验证码
2013-10-09 10:25 1215原文:使用tesseract-ocr破解网站验证码 ... -
和豆瓣CMGS交流
2013-06-20 17:36 5849蒋云鹏: 在?CMGS: 在蒋 ... -
python乱码问题('ascii' codec can't encode character u'\u4e2d' in position 0)
2013-05-20 19:03 4258>>> k = u'中' >> ... -
python shell 交互模式
2013-04-28 22:17 1643python 通过code模块可以很容易的进入交互模式: ... -
jython和gunicorn性能测试对比
2013-04-13 13:03 1313helloworld,笔记本上: gunicorn ... -
python的mysql客户端-MySQLdb
2013-04-04 10:13 1176平时的主要编程语言是Java,开发时也主要用Mysql,经常 ... -
Python几种并发实现方案的性能比较
2013-03-18 21:14 2970原文:http://www.elias.cn/P ... -
python汉字和Unicode码(utf-8)之间的转换(Pack/Unpack)
2013-03-18 21:13 1654保证你要转换的字符串编码为UTF8,如果不是,请iconv ... -
python反序列化的坑
2013-01-06 18:06 1285今天遇到python一个坑,调用memcached的get_m ... -
sqlalchemy connection pool.py 源代码
2012-12-29 22:58 2254把 sqlalchemy pool源代码copy下来,有空看看 ... -
SQLAlchemy简单介绍
2012-12-28 22:41 0文档参考:http://docs.sqlalchemy.org ... -
pymysql简单使用
2012-12-28 12:38 2125import pymysql conn = pymysq ...
相关推荐
4. **原子操作**:Python-memcached支持原子操作,如增加(incr)、减少(decr)整数值,这些操作在多线程环境下是安全的。 5. **前缀支持**:通过设置键的前缀,可以在同一个Memcached实例中隔离不同应用的数据,...
《PyPI上的腾讯云Python Memcached SDK:tencentcloud-sdk-python-memcached-3.0.315详解》 PyPI(Python Package Index)是Python开发者常用的软件包仓库,提供了一个广泛且丰富的Python库集合,供全球的开发人员...
10. 性能优化:Python3-memcached-master利用多线程,允许并行执行多个操作,以提高性能。此外,它使用了有效的序列化和反序列化策略,如使用pickle模块,来转换Python对象。 总之,Python3-memcached-master是...
一个纯python模块(线程安全),可以通过具有SASL auth支持的二进制文件访问memcached。 该模块的主要目的是能够与使用二进制协议的memcached通信并支持身份验证,因此它可以与Heroku一起使用。 有关在阅读文档的...
shdict可能提供线程安全、快速的缓存操作,以优化对memcached的访问。 3. **Python编程**:熟悉Python语言基础,包括变量、数据类型、控制流、函数和类,这些都是编写客户端库的基础。 4. **异步编程**:由于...
- `memcached`的核心设计理念是简单而高效,提供了一个键值对存储的接口,支持多线程服务,使用libevent库处理网络事件。 - `1.5.4`版本是一个稳定版,修复了前一版本中的已知问题,提高了系统的稳定性和性能。 2...
1. **Python** - `python-memcached` 和 `pylibmc`:Python社区提供了两个常用的Memcached客户端库。`python-memcached` 是一个轻量级的客户端,简单易用;而 `pylibmc` 增强了错误处理和更好的内存管理,支持多线程...
4. **并发与线程安全**:由于Python的全局解释器锁(GIL),多线程环境下的缓存设计需要考虑线程安全,确保在并发访问时数据的一致性和完整性。 5. **序列化与反序列化**:如果缓存的数据类型不是基本类型,可能...
- **封装示例**:以Python为例,使用python-memcached库可以非常方便地与Memcached服务器交互,包括设置键值对、获取值等基本操作。 以上内容详细介绍了Memcached的状态查看方法、存储机制以及内存资源的有效利用...
- 数据分布是基于一致性哈希,使得数据能够均匀分布在多个memcached服务器上,避免了热点问题。 4. **性能优势** - 使用内存存储,读写速度快,且支持多线程,能处理大量并发请求。 - 轻量级,对服务器资源需求...
4. **并发处理**:通过多线程或者异步IO(如Python的asyncio库)实现并行操作,提升批量操作时的吞吐量。 **使用CSSDBPy** 在Python项目中使用`csssdbpy`,首先需要安装这个库,通常可以通过`pip`进行: ```bash ...
- memcached 使用 TCP 或 UDP 协议在客户端和服务器之间通信,支持多线程处理,具有低延迟和高吞吐量的特性。 - 由于其内存存储的特性,它不适合存储大量的持久化数据,但非常适合缓存短期、频繁访问的数据。 2. ...
然而,多线程也带来了挑战,如线程安全问题。当多个线程共享同一资源时,可能会出现竞态条件、死锁或活锁等问题。为此,我们需要使用同步机制,如Java的`synchronized`关键字、互斥锁、信号量等,来控制对共享资源的...
- 相比之下,Memcached 不会出现阻塞问题,其速度非常快。 2. **与共享内存相比:** - 最初的缓存方法是在线程内部缓存对象,但由于进程间无法共享缓存,缓存命中率较低。 - 后来的共享内存缓存虽然允许多个进程...
3. **并发处理**:Memcached是线程安全的,可以处理多线程并发请求。 4. **性能优化**:合理设置缓存大小、减少网络延迟、优化数据结构和编码方式等都可以提升性能。 通过本示例,你可以了解到如何在实际项目中集成...
使用`python-memcached`库,首先需要安装:`pip install python-memcached`。然后,你可以创建一个客户端实例并执行基本操作: ```python import memcache mc = memcache.Client(['127.0.0.1:11211'], debug=0) ...
第 21 章 服务端 socket 开发之多线程和 gevent 框架并发测试[python 语言] 第 22 章 利用 pypy 提高 python 脚本的执行速度及测试性能 第 23 章 python 实现 select 和 epoll 模型 socket 网络编程 第 24 章 对 ...
Memcached 3.0.4是这个开源项目的最新迭代,它在性能、稳定性和安全性方面进行了优化。这个版本的发布,旨在进一步提升系统响应速度,增强系统健壮性,确保数据处理的高效与可靠。对于依赖于快速数据访问的大型Web...
7. **客户端连接**:应用可以通过各种语言(如 PHP、Python、Java 等)的客户端库与 memcached 通信,进行数据的存取。 memcached 支持的特性包括: - **TCP/IP 协议**:作为网络服务,它通过 TCP 连接与客户端通信...
5. **高性能**: Memcached设计简洁,无锁操作和多线程模型使其能处理大量并发请求。 6. **多语言支持**:提供了多种编程语言的客户端库,如PHP、Python、Java、Ruby、C++等,方便开发者集成到各种应用中。 **...