当前位置:Gxlcms > 数据库问题 > Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

Python操作 RabbitMQ、Redis、Memcache、SQLAlchemy

时间:2021-07-01 10:21:17 帮助过:3人阅读

wget http://memcached.org/latest 2 tar -zxvf memcached-1.x.x.tar.gz 3 cd memcached-1.x.x 4 ./configure && make && make test && sudo make install 5 6 PS:依赖libevent 7 yum install libevent-devel 8 apt-get install libevent-dev

启动Memcached

 1 memcached -d -m 10    -u root -l 10.211.55.4 -p 12000 -c 256 -P /tmp/memcached.pid
 2  
 3 参数说明:
 4     -d 是启动一个守护进程
 5     -m 是分配给Memcache使用的内存数量,单位是MB
 6     -u 是运行Memcache的用户
 7     -l 是监听的服务器IP地址
 8     -p 是设置Memcache监听的端口,最好是1024以上的端口
 9     -c 选项是最大运行的并发连接数,默认是1024,按照你服务器的负载量来设定
10     -P 是设置保存Memcache的pid文件

Memcached命令

1 存储命令: set/add/replace/append/prepend/cas
2 获取命令: get/gets
3 其他命令: delete/stats..

Python操作Memcached

安装API

1 python操作Memcached使用Python-memcached模块
2 下载安装:https://pypi.python.org/pypi/python-memcached

常用操作

1 import memcache
2  
3 mc = memcache.Client([10.211.55.4:12000], debug=True)
4 mc.set("foo", "bar")
5 ret = mc.get(foo)
6 print ret
技术分享
class Client(threading.local):
    """Object representing a pool of memcache servers.

    See L{memcache} for an overview.

    In all cases where a key is used, the key can be either:
        1. A simple hashable type (string, integer, etc.).
        2. A tuple of C{(hashvalue, key)}.  This is useful if you want
        to avoid making this module calculate a hash value.  You may
        prefer, for example, to keep all of a given user‘s objects on
        the same memcache server, so you could use the user‘s unique
        id as the hash value.


    @group Setup: __init__, set_servers, forget_dead_hosts,
    disconnect_all, debuglog
    @group Insertion: set, add, replace, set_multi
    @group Retrieval: get, get_multi
    @group Integers: incr, decr
    @group Removal: delete, delete_multi
    @sort: __init__, set_servers, forget_dead_hosts, disconnect_all,
           debuglog,\ set, set_multi, add, replace, get, get_multi,
           incr, decr, delete, delete_multi
    """
    _FLAG_PICKLE = 1 << 0
    _FLAG_INTEGER = 1 << 1
    _FLAG_LONG = 1 << 2
    _FLAG_COMPRESSED = 1 << 3

    _SERVER_RETRIES = 10  # how many times to try finding a free server.

    # exceptions for Client
    class MemcachedKeyError(Exception):
        pass

    class MemcachedKeyLengthError(MemcachedKeyError):
        pass

    class MemcachedKeyCharacterError(MemcachedKeyError):
        pass

    class MemcachedKeyNoneError(MemcachedKeyError):
        pass

    class MemcachedKeyTypeError(MemcachedKeyError):
        pass

    class MemcachedStringEncodingError(Exception):
        pass

    def __init__(self, servers, debug=0, pickleProtocol=0,
                 pickler=pickle.Pickler, unpickler=pickle.Unpickler,
                 compressor=zlib.compress, decompressor=zlib.decompress,
                 pload=None, pid=None,
                 server_max_key_length=None, server_max_value_length=None,
                 dead_retry=_DEAD_RETRY, socket_timeout=_SOCKET_TIMEOUT,
                 cache_cas=False, flush_on_reconnect=0, check_keys=True):
        """Create a new Client object with the given list of servers.

        @param servers: C{servers} is passed to L{set_servers}.
        @param debug: whether to display error messages when a server
        can‘t be contacted.
        @param pickleProtocol: number to mandate protocol used by
        (c)Pickle.
        @param pickler: optional override of default Pickler to allow
        subclassing.
        @param unpickler: optional override of default Unpickler to
        allow subclassing.
        @param pload: optional persistent_load function to call on
        pickle loading.  Useful for cPickle since subclassing isn‘t
        allowed.
        @param pid: optional persistent_id function to call on pickle
        storing.  Useful for cPickle since subclassing isn‘t allowed.
        @param dead_retry: number of seconds before retrying a
        blacklisted server. Default to 30 s.
        @param socket_timeout: timeout in seconds for all calls to a
        server. Defaults to 3 seconds.
        @param cache_cas: (default False) If true, cas operations will
        be cached.  WARNING: This cache is not expired internally, if
        you have a long-running process you will need to expire it
        manually via client.reset_cas(), or the cache can grow
        unlimited.
        @param server_max_key_length: (default SERVER_MAX_KEY_LENGTH)
        Data that is larger than this will not be sent to the server.
        @param server_max_value_length: (default
        SERVER_MAX_VALUE_LENGTH) Data that is larger than this will
        not be sent to the server.
        @param flush_on_reconnect: optional flag which prevents a
        scenario that can cause stale data to be read: If there‘s more
        than one memcached server and the connection to one is
        interrupted, keys that mapped to that server will get
        reassigned to another. If the first server comes back, those
        keys will map to it again. If it still has its data, get()s
        can read stale data that was overwritten on another
        server. This flag is off by default for backwards
        compatibility.
        @param check_keys: (default True) If True, the key is checked
        to ensure it is the correct length and composed of the right
        characters.
        """
        super(Client, self).__init__()
        self.debug = debug
        self.dead_retry = dead_retry
        self.socket_timeout = socket_timeout
        self.flush_on_reconnect = flush_on_reconnect
        self.set_servers(servers)
        self.stats = {}
        self.cache_cas = cache_cas
        self.reset_cas()
        self.do_check_key = check_keys

        # Allow users to modify pickling/unpickling behavior
        self.pickleProtocol = pickleProtocol
        self.pickler = pickler
        self.unpickler = unpickler
        self.compressor = compressor
        self.decompressor = decompressor
        self.persistent_load = pload
        self.persistent_id = pid
        self.server_max_key_length = server_max_key_length
        if self.server_max_key_length is None:
            self.server_max_key_length = SERVER_MAX_KEY_LENGTH
        self.server_max_value_length = server_max_value_length
        if self.server_max_value_length is None:
            self.server_max_value_length = SERVER_MAX_VALUE_LENGTH

        #  figure out the pickler style
        file = BytesIO()
        try:
            pickler = self.pickler(file, protocol=self.pickleProtocol)
            self.picklerIsKeyword = True
        except TypeError:
            self.picklerIsKeyword = False

    def _encode_key(self, key):
        if isinstance(key, tuple):
            if isinstance(key[1], six.text_type):
                return (key[0], key[1].encode(utf8))
        elif isinstance(key, six.text_type):
            return key.encode(utf8)
        return key

    def _encode_cmd(self, cmd, key, headers, noreply, *args):
        cmd_bytes = cmd.encode() if six.PY3 else cmd
        fullcmd = [cmd_bytes, b , key]

        if headers:
            if six.PY3:
                headers = headers.encode()
            fullcmd.append(b )
            fullcmd.append(headers)

        if noreply:
            fullcmd.append(b noreply)

        if args:
            fullcmd.append(b )
            fullcmd.extend(args)
        return b‘‘.join(fullcmd)

    def reset_cas(self):
        """Reset the cas cache.

        This is only used if the Client() object was created with
        "cache_cas=True".  If used, this cache does not expire
        internally, so it can grow unbounded if you do not clear it
        yourself.
        """
        self.cas_ids = {}

    def set_servers(self, servers):
        """Set the pool of servers used by this client.

        @param servers: an array of servers.
        Servers can be passed in two forms:
            1. Strings of the form C{"host:port"}, which implies a
            default weight of 1.
            2. Tuples of the form C{("host:port", weight)}, where
            C{weight} is an integer weight value.

        """
        self.servers = [_Host(s, self.debug, dead_retry=self.dead_retry,
                              socket_timeout=self.socket_timeout,
                              flush_on_reconnect=self.flush_on_reconnect)
                        for s in servers]
        self._init_buckets()

    def get_stats(self, stat_args=None):
        """Get statistics from each of the servers.

        @param stat_args: Additional arguments to pass to the memcache
            "stats" command.

        @return: A list of tuples ( server_identifier,
            stats_dictionary ).  The dictionary contains a number of
            name/value pairs specifying the name of the status field
            and the string value associated with it.  The values are
            not converted from strings.
        """
        data = []
        for s in self.servers:
            if not s.connect():
                continue
            if s.family == socket.AF_INET:
                name = %s:%s (%s) % (s.ip, s.port, s.weight)
            elif s.family == socket.AF_INET6:
                name = [%s]:%s (%s) % (s.ip, s.port, s.weight)
            else:
                name = unix:%s (%s) % (s.address, s.weight)
            if not stat_args:
                s.send_cmd(stats)
            else:
                s.send_cmd(stats  + stat_args)
            serverData = {}
            data.append((name, serverData))
            readline = s.readline
            while 1:
                line = readline()
                if not line or line.strip() == END:
                    break
                stats = line.split( , 2)
                serverData[stats[1]] = stats[2]

        return(data)

    def get_slabs(self):
        data = []
        for s in self.servers:
            if not s.connect():
                continue
            if s.family == socket.AF_INET:
                name = %s:%s (%s) % (s.ip, s.port, s.weight)
            elif s.family == socket.AF_INET6:
                name = [%s]:%s (%s) % (s.ip, s.port, s.weight)
            else:
                name = unix:%s (%s) % (s.address, s.weight)
            serverData = {}
            data.append((name, serverData))
            s.send_cmd(stats items)
            readline = s.readline
            while 1:
                line = readline()
                if not line or line.strip() == END:
                    break
                item = line.split( , 2)
                # 0 = STAT, 1 = ITEM, 2 = Value
                slab = item[1].split(:, 2)
                # 0 = items, 1 = Slab #, 2 = Name
                if slab[1] not in serverData:
                    serverData[slab[1]] = {}
                serverData[slab[1]][slab[2]] = item[2]
        return data

    def flush_all(self):
        """Expire all data in memcache servers that are reachable."""
        for s in self.servers:
            if not s.connect():
                continue
            s.flush()

    def debuglog(self, str):
        if self.debug:
            sys.stderr.write("MemCached: %s\n" % str)

    def _statlog(self, func):
        if func not in self.stats:
            self.stats[func] = 1
        else:
            self.stats[func] += 1

    def forget_dead_hosts(self):
        """Reset every host in the pool to an "alive" state."""
        for s in self.servers:
            s.deaduntil = 0

    def _init_buckets(self):
        self.buckets = []
        for server in self.servers:
            for i in range(server.weight):
                self.buckets.append(server)

    def _get_server(self, key):
        if isinstance(key, tuple):
            serverhash, key = key
        else:
            serverhash = serverHashFunction(key)

        if not self.buckets:
            return None, None

        for i in range(Client._SERVER_RETRIES):
            server = self.buckets[serverhash % len(self.buckets)]
            if server.connect():
                # print("(using server %s)" % server,)
                return server, key
            serverhash = serverHashFunction(str(serverhash) + str(i))
        return None, None

    def disconnect_all(self):
        for s in self.servers:
            s.close_socket()

    def delete_multi(self, keys, time=0, key_prefix=‘‘, noreply=False):
        """Delete multiple keys in the memcache doing just one query.

        >>> notset_keys = mc.set_multi({‘a1‘ : ‘val1‘, ‘a2‘ : ‘val2‘})
        >>> mc.get_multi([‘a1‘, ‘a2‘]) == {‘a1‘ : ‘val1‘,‘a2‘ : ‘val2‘}
        >>> mc.delete_multi([‘key1‘, ‘key2‘])
        >>> mc.get_multi([‘key1‘, ‘key2‘]) == {}

        This method is recommended over iterated regular L{delete}s as
        it reduces total latency, since your app doesn‘t have to wait
        for each round-trip of L{delete} before sending the next one.

        @param keys: An iterable of keys to clear
        @param time: number of seconds any subsequent set / update
        commands should fail. Defaults to 0 for no delay.
        @param key_prefix: Optional string to prepend to each key when
            sending to memcache.  See docs for L{get_multi} and
            L{set_multi}.
        @param noreply: optional parameter instructs the server to not send the
            reply.
        @return: 1 if no failure in communication with any memcacheds.
        @rtype: int
        """

        self._statlog(delete_multi)

        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(
            keys, key_prefix)

        # send out all requests on each server before reading anything
        dead_servers = []

        rc = 1
        for server in six.iterkeys(server_keys):
            bigcmd = []
            write = bigcmd.append
            extra =  noreply if noreply else ‘‘
            if time is not None:
                for key in server_keys[server]:  # These are mangled keys
                    write("delete %s %d%s\r\n" % (key, time, extra))
            else:
                for key in server_keys[server]:  # These are mangled keys
                    write("delete %s%s\r\n" % (key, extra))
            try:
                server.send_cmds(‘‘.join(bigcmd))
            except socket.error as msg:
                rc = 0
                if isinstance(msg, tuple):
                    msg = msg[1]
                server.mark_dead(msg)
                dead_servers.append(server)

        # if noreply, just return
        if noreply:
            return rc

        # if any servers died on the way, don‘t expect them to respond.
        for server in dead_servers:
            del server_keys[server]

        for server, keys in six.iteritems(server_keys):
            try:
                for key in keys:
                    server.expect("DELETED")
            except socket.error as msg:
                if isinstance(msg, tuple):
                    msg = msg[1]
                server.mark_dead(msg)
                rc = 0
        return rc

    def delete(self, key, time=0, noreply=False):
        ‘‘‘Deletes a key from the memcache.

        @return: Nonzero on success.
        @param time: number of seconds any subsequent set / update commands
        should fail. Defaults to None for no delay.
        @param noreply: optional parameter instructs the server to not send the
            reply.
        @rtype: int
        ‘‘‘
        return self._deletetouch([bDELETED, bNOT_FOUND], "delete", key,
                                 time, noreply)

    def touch(self, key, time=0, noreply=False):
        ‘‘‘Updates the expiration time of a key in memcache.

        @return: Nonzero on success.
        @param time: Tells memcached the time which this value should
            expire, either as a delta number of seconds, or an absolute
            unix time-since-the-epoch value. See the memcached protocol
            docs section "Storage Commands" for more info on <exptime>. We
            default to 0 == cache forever.
        @param noreply: optional parameter instructs the server to not send the
            reply.
        @rtype: int
        ‘‘‘
        return self._deletetouch([bTOUCHED], "touch", key, time, noreply)

    def _deletetouch(self, expected, cmd, key, time=0, noreply=False):
        key = self._encode_key(key)
        if self.do_check_key:
            self.check_key(key)
        server, key = self._get_server(key)
        if not server:
            return 0
        self._statlog(cmd)
        if time is not None and time != 0:
            fullcmd = self._encode_cmd(cmd, key, str(time), noreply)
        else:
            fullcmd = self._encode_cmd(cmd, key, None, noreply)

        try:
            server.send_cmd(fullcmd)
            if noreply:
                return 1
            line = server.readline()
            if line and line.strip() in expected:
                return 1
            self.debuglog(%s expected %s, got: %r
                          % (cmd,  or .join(expected), line))
        except socket.error as msg:
            if isinstance(msg, tuple):
                msg = msg[1]
            server.mark_dead(msg)
        return 0

    def incr(self, key, delta=1, noreply=False):
        """Increment value for C{key} by C{delta}

        Sends a command to the server to atomically increment the
        value for C{key} by C{delta}, or by 1 if C{delta} is
        unspecified.  Returns None if C{key} doesn‘t exist on server,
        otherwise it returns the new value after incrementing.

        Note that the value for C{key} must already exist in the
        memcache, and it must be the string representation of an
        integer.

        >>> mc.set("counter", "20")  # returns 1, indicating success
        >>> mc.incr("counter")
        >>> mc.incr("counter")

        Overflow on server is not checked.  Be aware of values
        approaching 2**32.  See L{decr}.

        @param delta: Integer amount to increment by (should be zero
        or greater).

        @param noreply: optional parameter instructs the server to not send the
        reply.

        @return: New value after incrementing, no None for noreply or error.
        @rtype: int
        """
        return self._incrdecr("incr", key, delta, noreply)

    def decr(self, key, delta=1, noreply=False):
        """Decrement value for C{key} by C{delta}

        Like L{incr}, but decrements.  Unlike L{incr}, underflow is
        checked and new values are capped at 0.  If server value is 1,
        a decrement of 2 returns 0, not -1.

        @param delta: Integer amount to decrement by (should be zero
        or greater).

        @param noreply: optional parameter instructs the server to not send the
        reply.

        @return: New value after decrementing,  or None for noreply or error.
        @rtype: int
        """
        return self._incrdecr("decr", key, delta, noreply)

    def _incrdecr(self, cmd, key, delta, noreply=False):
        key = self._encode_key(key)
        if self.do_check_key:
            self.check_key(key)
        server, key = self._get_server(key)
        if not server:
            return None
        self._statlog(cmd)
        fullcmd = self._encode_cmd(cmd, key, str(delta), noreply)
        try:
            server.send_cmd(fullcmd)
            if noreply:
                return
            line = server.readline()
            if line is None or line.strip() == bNOT_FOUND:
                return None
            return int(line)
        except socket.error as msg:
            if isinstance(msg, tuple):
                msg = msg[1]
            server.mark_dead(msg)
            return None

    def add(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Add new key with value.

        Like L{set}, but only stores in memcache if the key doesn‘t
        already exist.

        @return: Nonzero on success.
        @rtype: int
        ‘‘‘
        return self._set("add", key, val, time, min_compress_len, noreply)

    def append(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Append the value to the end of the existing key‘s value.

        Only stores in memcache if key already exists.
        Also see L{prepend}.

        @return: Nonzero on success.
        @rtype: int
        ‘‘‘
        return self._set("append", key, val, time, min_compress_len, noreply)

    def prepend(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Prepend the value to the beginning of the existing key‘s value.

        Only stores in memcache if key already exists.
        Also see L{append}.

        @return: Nonzero on success.
        @rtype: int
        ‘‘‘
        return self._set("prepend", key, val, time, min_compress_len, noreply)

    def replace(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Replace existing key with value.

        Like L{set}, but only stores in memcache if the key already exists.
        The opposite of L{add}.

        @return: Nonzero on success.
        @rtype: int
        ‘‘‘
        return self._set("replace", key, val, time, min_compress_len, noreply)

    def set(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Unconditionally sets a key to a given value in the memcache.

        The C{key} can optionally be an tuple, with the first element
        being the server hash value and the second being the key.  If
        you want to avoid making this module calculate a hash value.
        You may prefer, for example, to keep all of a given user‘s
        objects on the same memcache server, so you could use the
        user‘s unique id as the hash value.

        @return: Nonzero on success.
        @rtype: int

        @param time: Tells memcached the time which this value should
        expire, either as a delta number of seconds, or an absolute
        unix time-since-the-epoch value. See the memcached protocol
        docs section "Storage Commands" for more info on <exptime>. We
        default to 0 == cache forever.

        @param min_compress_len: The threshold length to kick in
        auto-compression of the value using the compressor
        routine. If the value being cached is a string, then the
        length of the string is measured, else if the value is an
        object, then the length of the pickle result is measured. If
        the resulting attempt at compression yeilds a larger string
        than the input, then it is discarded. For backwards
        compatability, this parameter defaults to 0, indicating don‘t
        ever try to compress.

        @param noreply: optional parameter instructs the server to not
        send the reply.
        ‘‘‘
        return self._set("set", key, val, time, min_compress_len, noreply)

    def cas(self, key, val, time=0, min_compress_len=0, noreply=False):
        ‘‘‘Check and set (CAS)

        Sets a key to a given value in the memcache if it hasn‘t been
        altered since last fetched. (See L{gets}).

        The C{key} can optionally be an tuple, with the first element
        being the server hash value and the second being the key.  If
        you want to avoid making this module calculate a hash value.
        You may prefer, for example, to keep all of a given user‘s
        objects on the same memcache server, so you could use the
        user‘s unique id as the hash value.

        @return: Nonzero on success.
        @rtype: int

        @param time: Tells memcached the time which this value should
        expire, either as a delta number of seconds, or an absolute
        unix time-since-the-epoch value. See the memcached protocol
        docs section "Storage Commands" for more info on <exptime>. We
        default to 0 == cache forever.

        @param min_compress_len: The threshold length to kick in
        auto-compression of the value using the compressor
        routine. If the value being cached is a string, then the
        length of the string is measured, else if the value is an
        object, then the length of the pickle result is measured. If
        the resulting attempt at compression yeilds a larger string
        than the input, then it is discarded. For backwards
        compatability, this parameter defaults to 0, indicating don‘t
        ever try to compress.

        @param noreply: optional parameter instructs the server to not
        send the reply.
        ‘‘‘
        return self._set("cas", key, val, time, min_compress_len, noreply)

    def _map_and_prefix_keys(self, key_iterable, key_prefix):
        """Compute the mapping of server (_Host instance) -> list of keys to
        stuff onto that server, as well as the mapping of prefixed key
        -> original key.
        """
        key_prefix = self._encode_key(key_prefix)
        # Check it just once ...
        key_extra_len = len(key_prefix)
        if key_prefix and self.do_check_key:
            self.check_key(key_prefix)

        # server (_Host) -> list of unprefixed server keys in mapping
        server_keys = {}

        prefixed_to_orig_key = {}
        # build up a list for each server of all the keys we want.
        for orig_key in key_iterable:
            if isinstance(orig_key, tuple):
                # Tuple of hashvalue, key ala _get_server(). Caller is
                # essentially telling us what server to stuff this on.
                # Ensure call to _get_server gets a Tuple as well.
                serverhash, key = orig_key

                key = self._encode_key(key)
                if not isinstance(key, six.binary_type):
                    # set_multi supports int / long keys.
                    key = str(key)
                    if six.PY3:
                        key = key.encode(utf8)
                bytes_orig_key = key

                # Gotta pre-mangle key before hashing to a
                # server. Returns the mangled key.
                server, key = self._get_server(
                    (serverhash, key_prefix + key))

                orig_key = orig_key[1]
            else:
                key = self._encode_key(orig_key)
                if not isinstance(key, six.binary_type):
                    # set_multi supports int / long keys.
                    key = str(key)
                    if six.PY3:
                        key = key.encode(utf8)
                bytes_orig_key = key
                server, key = self._get_server(key_prefix + key)

            #  alert when passed in key is None
            if orig_key is None:
                self.check_key(orig_key, key_extra_len=key_extra_len)

            # Now check to make sure key length is proper ...
            if self.do_check_key:
                self.check_key(bytes_orig_key, key_extra_len=key_extra_len)

            if not server:
                continue

            if server not in server_keys:
                server_keys[server] = []
            server_keys[server].append(key)
            prefixed_to_orig_key[key] = orig_key

        return (server_keys, prefixed_to_orig_key)

    def set_multi(self, mapping, time=0, key_prefix=‘‘, min_compress_len=0,
                  noreply=False):
        ‘‘‘Sets multiple keys in the memcache doing just one query.

        >>> notset_keys = mc.set_multi({‘key1‘ : ‘val1‘, ‘key2‘ : ‘val2‘})
        >>> mc.get_multi([‘key1‘, ‘key2‘]) == {‘key1‘ : ‘val1‘,
        ...                                    ‘key2‘ : ‘val2‘}


        This method is recommended over regular L{set} as it lowers
        the number of total packets flying around your network,
        reducing total latency, since your app doesn‘t have to wait
        for each round-trip of L{set} before sending the next one.

        @param mapping: A dict of key/value pairs to set.

        @param time: Tells memcached the time which this value should
            expire, either as a delta number of seconds, or an
            absolute unix time-since-the-epoch value. See the
            memcached protocol docs section "Storage Commands" for
            more info on <exptime>. We default to 0 == cache forever.

        @param key_prefix: Optional string to prepend to each key when
            sending to memcache. Allows you to efficiently stuff these
            keys into a pseudo-namespace in memcache:

            >>> notset_keys = mc.set_multi(
            ...     {‘key1‘ : ‘val1‘, ‘key2‘ : ‘val2‘},
            ...     key_prefix=‘subspace_‘)
            >>> len(notset_keys) == 0
            True
            >>> mc.get_multi([‘subspace_key1‘,
            ...               ‘subspace_key2‘]) == {‘subspace_key1‘: ‘val1‘,
            ...                                     ‘subspace_key2‘ : ‘val2‘}
            True

            Causes key ‘subspace_key1‘ and ‘subspace_key2‘ to be
            set. Useful in conjunction with a higher-level layer which
            applies namespaces to data in memcache.  In this case, the
            return result would be the list of notset original keys,
            prefix not applied.

        @param min_compress_len: The threshold length to kick in
            auto-compression of the value using the compressor
            routine. If the value being cached is a string, then the
            length of the string is measured, else if the value is an
            object, then the length of the pickle result is
            measured. If the resulting attempt at compression yeilds a
            larger string than the input, then it is discarded. For
            backwards compatability, this parameter defaults to 0,
            indicating don‘t ever try to compress.

        @param noreply: optional parameter instructs the server to not
            send the reply.

        @return: List of keys which failed to be stored [ memcache out
           of memory, etc. ].

        @rtype: list
        ‘‘‘
        self._statlog(set_multi)

        server_keys, prefixed_to_orig_key = self._map_and_prefix_keys(
            six.iterkeys(mapping), key_prefix)

        # send out all requests on each server before reading anything
        dead_servers = []
        notstored = []  # original keys.

        for server in six.iterkeys(server_keys):
            bigcmd = []
            write = bigcmd.append
            try:
                for key in server_keys[server]:  # These are mangled keys
                    store_info = self._val_to_store_info(
                        mapping[prefixed_to_orig_key[key]],
                        min_compress_len)
                    if store_info:
                        flags, len_val, val = store_info
                        headers = "%d %d %d" % (flags, time, len_val)
                        fullcmd = self._encode_cmd(set, key, headers,
                                                   noreply,
                                                   b\r\n, val, b\r\n)
                        write(fullcmd)
                    else:
                        notstored.append(prefixed_to_orig_key[key])
                server.send_cmds(b‘‘.join(bigcmd))
            except socket.error as msg:
                if isinstance(msg, tuple):
                    msg = msg[1]
                server.mark_dead(msg)
                dead_servers.append(server)

        # if noreply, just return early
        if noreply:
            return notstored

        # if any servers died on the way, don‘t expect them to respond.
        for server in dead_servers:
            del server_keys[server]

        #  short-circuit if there are no servers, just return all keys
        if not server_keys:
            return(mapping.keys())

        
                        
                    

人气教程排行