README ¶
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 of ``hostname[:port] [alias]``. ``port`` and ``alias`` are optional. If ``port`` is not given, default port ``11211`` will be used. ``alias`` will be used to compute server hash if given, otherwise server hash will be computed based on ``host`` and ``port`` (i.e.: If ``port`` is not given or it is equal to ``11211``, ``host`` will be used to compute server hash. If ``port`` is not equal to ``11211``, ``host:port`` will be used). - ``do_split``: Memcached server will refuse to store value if size >= 1MB, if ``do_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. If ``buffer length > comp_threshold > 0``, it will be compressed using zlib. If ``comp_threshold = 0``, string buffer will never be compressed using zlib. default: ``0`` - ``noreply``: Whether to enable memcached's ``noreply`` 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 every ``MC_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 security@douban.com 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 performance `i64toa <https://github.com/miloyip/itoa-benchmark>`__ implementation. - Thanks to `Ivan Novikov <https://twitter.com/d0znpp>`__ for the research in `THE 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 the `benchmark 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
Click to show internal directories.
Click to hide internal directories.