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].portandaliasare optional. Ifportis not given, default port11211will be used.aliaswill be used to compute server hash if given, otherwise server hash will be computed based onhostandport(i.e.: Ifportis not given or it is equal to11211,hostwill be used to compute server hash. Ifportis not equal to11211,host:portwill be used). -
do_split: Memcached server will refuse to store value if size >= 1MB, ifdo_splitis 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'snoreplybehaviour. default:False -
prefix: The key prefix. default:'' -
hash_fn: hashing function for keys. possible values:MC_HASH_MD5MC_HASH_FNV1_32MC_HASH_FNV1A_32MC_HASH_CRC_32
default:
MC_HASH_MD5NOTE: 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_TIMEOUTTimeout parameter used during set/get procedure. (default:300ms) -
MC_CONNECT_TIMEOUTTimeout parameter used when connecting to memcached server on initial phase. (default:100ms) -
MC_RETRY_TIMEOUTWhen a server is not available dur to server-end error. libmc will try to establish the broken connection in everyMC_RETRY_TIMEOUTs until the connection is back to live.(default:5s)
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