libmc
libmc copied to clipboard
Fast and light-weight memcached client for C++ / #python / #golang #libmc
libmc
|build_go| |build_py| |status| |pypiv| |pyversions| |wheel| |license|
libmc is a memcached client library for Python without any other
dependencies in runtime. It's mainly written in C++ and Cython. libmc
can be considered as a drop in replacement for libmemcached and
python-libmemcached <https://github.com/douban/python-libmemcached>
__.
libmc is developing and maintaining by Douban Inc. Currently, It is
working in production environment, powering all web traffics in
douban.com. Realtime benchmark result <https://travis-ci.org/douban/libmc/builds/57124335#L1611>
__ is
available on travis.
Build and Installation
For users:
::
pip install libmc
Usage:
.. code:: python
import libmc
mc = libmc.Client(['localhost:11211', 'localhost:11212'])
mc.set('foo', 'bar')
assert mc.get('foo') == 'bar'
Under the hood
Under the hood, libmc consists of 2 parts: an internal fully-functional
memcached client implementation in C++ and a Cython wrapper around that
implementation. Dynamic memory allocation and memory-copy are slow, so
we tried our best to avoid them. The set_multi
command is not
natively supported by the memcached protocol <https://github.com/memcached/memcached/blob/master/doc/protocol.txt>
__.
Some techniques are applied to make set_multi
command extremely fast
in libmc (compared to some other similiar libraries).
Configuration
.. code:: python
import libmc
from libmc import (
MC_HASH_MD5, MC_POLL_TIMEOUT, MC_CONNECT_TIMEOUT, MC_RETRY_TIMEOUT
)
mc = libmc.Client(
[
'localhost:11211',
'localhost:11212',
'remote_host',
'remote_host mc.mike',
'remote_host:11213 mc.oscar'
],
do_split=True,
comp_threshold=0,
noreply=False,
prefix=None,
hash_fn=MC_HASH_MD5,
failover=False
)
mc.config(MC_POLL_TIMEOUT, 100) # 100 ms
mc.config(MC_CONNECT_TIMEOUT, 300) # 300 ms
mc.config(MC_RETRY_TIMEOUT, 5) # 5 s
-
servers
: is a list of memcached server addresses. Each address can be in format ofhostname[:port] [alias]
.port
andalias
are optional. Ifport
is not given, default port11211
will be used.alias
will be used to compute server hash if given, otherwise server hash will be computed based onhost
andport
(i.e.: Ifport
is not given or it is equal to11211
,host
will be used to compute server hash. Ifport
is not equal to11211
,host:port
will be used). -
do_split
: Memcached server will refuse to store value if size >= 1MB, ifdo_split
is enabled, large value (< 10 MB) will be splitted into several blocks. If the value is too large (>= 10 MB), it will not be stored. default:True
-
comp_threshold
: All kinds of values will be encoded into string buffer. Ifbuffer length > comp_threshold > 0
, it will be compressed using zlib. Ifcomp_threshold = 0
, string buffer will never be compressed using zlib. default:0
-
noreply
: Whether to enable memcached'snoreply
behaviour. default:False
-
prefix
: The key prefix. default:''
-
hash_fn
: hashing function for keys. possible values:-
MC_HASH_MD5
-
MC_HASH_FNV1_32
-
MC_HASH_FNV1A_32
-
MC_HASH_CRC_32
default:
MC_HASH_MD5
NOTE: fnv1_32, fnv1a_32, crc_32 implementations in libmc are per each spec, but they're not compatible with corresponding implementions in libmemcached.
-
-
failover
: Whether to failover to next server when current server is not available. default:False
-
MC_POLL_TIMEOUT
Timeout parameter used during set/get procedure. (default:300
ms) -
MC_CONNECT_TIMEOUT
Timeout parameter used when connecting to memcached server on initial phase. (default:100
ms) -
MC_RETRY_TIMEOUT
When a server is not available dur to server-end error. libmc will try to establish the broken connection in everyMC_RETRY_TIMEOUT
s until the connection is back to live.(default:5
s)
NOTE: The hashing algorithm for host mapping on continuum is always md5.
Contributing to libmc
Feel free to send a Pull Request. For feature requests or any questions, please open an Issue.
For SECURITY DISCLOSURE, please disclose the information responsibly by sending an email to [email protected] directly instead of creating a GitHub issue.
FAQ
Does libmc support PHP? ^^^^^^^^^^^^^^^^^^^^^^^
No. But if you like, you can write a wrapper for PHP based on the C++ implementation.
Is Memcached binary protocol supported ? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
No. Only Memcached ASCII protocol is supported currently.
Why reinventing the wheel? ^^^^^^^^^^^^^^^^^^^^^^^^^^
Before libmc, we're using
python-libmemcached <https://github.com/douban/python-libmemcached>
,
which is a python extention for
libmemcached <http://libmemcached.org/libMemcached.html>
.
libmemcached is quite weird and buggy. After nearly one decade, there're
still some unsolved bugs.
Is libmc thread-safe ? ^^^^^^^^^^^^^^^^^^^^^^
libmc is a single-threaded memcached client. If you initialize a libmc
client in one thread but reuse that in another thread, a Python
Exception ThreadUnsafe
will raise in Python.
Is libmc compatible with gevent? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Yes, with the help of greenify <https://github.com/douban/greenify>
__,
libmc is friendly to gevent. Read tests/shabby/gevent_issue.py
for
details.
Notice:
gevent.monkey.patch_all()
will override
threading.current_thread().ident
to Greenlet's ID,
this will cause libmc to throw a ThreadUnSafe error
or run into dead lock, you should only patch the things
that you need, e.g.
.. code:: python
from gevent import monkey
monkey.patch_socket()
Acknowledgments
- Thanks to
@fahrenheit2539 <https://github.com/fahrenheit2539>
__ and the llvm project for the standalone.SmallVector <http://fahrenheit2539.blogspot.com/2012/06/introduction-in-depths-look-at.html>
__ implementation. - Thanks to
@miloyip <https://github.com/miloyip>
__ for the high performancei64toa <https://github.com/miloyip/itoa-benchmark>
__ implementation. - Thanks to
Ivan Novikov <https://twitter.com/d0znpp>
__ for the research inTHE NEW PAGE OF INJECTIONS BOOK: MEMCACHED INJECTIONS <https://www.blackhat.com/us-14/briefings.html#the-new-page-of-injections-book-memcached-injections>
__. - Thanks to the PolarSSL project for the md5 implementation.
- Thanks to
@lericson <https://github.com/lericson>
__ for thebenchmark script in pylibmc <https://github.com/lericson/pylibmc/blob/master/bin/runbench.py>
__. - Thanks to the libmemcached project and some other projects possibly not mentioned here.
Contributors
-
@mckelvin <https://github.com/mckelvin>
__ -
@zzl0 <https://github.com/zzl0>
__ -
@windreamer <https://github.com/windreamer>
__ -
@lembacon <https://github.com/lembacon>
__ -
@seansay <https://github.com/seansay>
__ -
@mosasiru <https://github.com/mosasiru>
__ -
@jumpeiMano <https://github.com/jumpeiMano>
__
Who is using
-
豆瓣 <https://douban.com>
__ -
下厨房 <https://www.xiachufang.com>
__ -
Some other projects on GitHub <https://github.com/douban/libmc/network/dependents>
__ - Want to add your company/organization name here? Please feel free to send a PR!
Documentation
https://github.com/douban/libmc/wiki
LICENSE
Copyright (c) 2014-2020, Douban Inc. All rights reserved.
Licensed under a BSD license: https://github.com/douban/libmc/blob/master/LICENSE.txt
.. |build_go| image:: https://github.com/douban/libmc/actions/workflows/golang.yml/badge.svg :target: https://github.com/douban/libmc/actions/workflows/golang.yml
.. |build_py| image:: https://github.com/douban/libmc/actions/workflows/python.yml/badge.svg :target: https://github.com/douban/libmc/actions/workflows/python.yml
.. |pypiv| image:: https://img.shields.io/pypi/v/libmc :target: https://pypi.org/project/libmc/
.. |status| image:: https://img.shields.io/pypi/status/libmc .. |pyversions| image:: https://img.shields.io/pypi/pyversions/libmc .. |wheel| image:: https://img.shields.io/pypi/wheel/libmc .. |license| image:: https://img.shields.io/pypi/l/libmc?color=blue