libmc

module
v1.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 20, 2021 License: BSD-3-Clause

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

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL