美文网首页
redis zipmap (10)

redis zipmap (10)

作者: lmem | 来源:发表于2017-06-02 21:24 被阅读211次

    zipmap 是redis里的hashmap, 主要在保证速度的同时减少内存的使用,存储结构是一个字符串,通过内存定位来操作数据结构。
    数据结构
    zmlen 1 字节 len 1或者5字节

    <zmlen><len>"foo"<len><free>"bar"<len>"hello"<len><free>"world"
    
     * String -> String Map data structure optimized for size.
     * This file implements a data structure mapping strings to other strings
     * implementing an O(n) lookup data structure designed to be very memory
     * efficient.
     *
     * The Redis Hash type uses this data structure for hashes composed of a small
     * number of elements, to switch to a hash table once a given number of
     * elements is reached.
     *
     * Given that many times Redis Hashes are used to represent objects composed
     * of few fields, this is a very big win in terms of used memory.
     *
    
     * Memory layout of a zipmap, for the map "foo" => "bar", "hello" => "world":
     * 数据格式
     * <zmlen><len>"foo"<len><free>"bar"<len>"hello"<len><free>"world"
     *
     * zmlen 表示长度,如果大于等于254则只能遍历了!!
     * <zmlen> is 1 byte length that holds the current size of the zipmap.
     * When the zipmap length is greater than or equal to 254, this value
     * is not used and the zipmap needs to be traversed to find out the length.
     *
     * <len>代表了后面字符串key 或 value的值的长度,长度一般被编码1个字节或5个字节表示,这个和ziplist类似
     * 如果后面的字符串长度小于等于252个,可与用单字节表示,其他253,254等长度被用来表示其他作用了,当超过这个数时候
     * 则直接按5字节的方式存储长度。
     * <len> is the length of the following string (key or value).
     * <len> lengths are encoded in a single value or in a 5 bytes value.
     * If the first byte value (as an unsigned 8 bit value) is between 0 and
     * 253, it's a single-byte length. If it is 254 then a four bytes unsigned
     * integer follows (in the host byte ordering). A value of 255 is used to
     * signal the end of the hash.
     *
     * <free> is the number of free unused bytes after the string, resulting
     * from modification of values associated to a key. For instance if "foo"
     * is set to "bar", and later "foo" will be set to "hi", it will have a
     * free byte to use if the value will enlarge again later, or even in
     * order to add a key/value pair if it fits.
     * free 用于表示现在未用的字节大小, 8bit大小
     * <free> is always an unsigned 8 bit number, because if after an
     * update operation there are more than a few free bytes, the zipmap will be
     * reallocated to make sure it is as small as possible.
     *
     * The most compact representation of the above two elements hash is actually:
     *
     * "\x02\x03foo\x03\x00bar\x05hello\x05\x00world\xff"
     *
     * Note that because keys and values are prefixed length "objects",
     * the lookup will take O(N) where N is the number of elements
     * in the zipmap and *not* the number of bytes needed to represent the zipmap.
     * This lowers the constant times considerably.
    
    

    1.查找

    * Search a key and retrieve the pointer and len of the associated value.
     * If the key is found the function returns 1, otherwise 0. */
    // 根据key返回对应的地址
    int zipmapGet(unsigned char *zm, unsigned char *key, unsigned int klen, unsigned char **value, unsigned int *vlen) {
        unsigned char *p;
    
        if ((p = zipmapLookupRaw(zm,key,klen,NULL)) == NULL) return 0;
        p += zipmapRawKeyLength(p);
        *vlen = zipmapDecodeLength(p);
        *value = p + ZIPMAP_LEN_BYTES(*vlen) + 1;
        return 1;
    }
    

    2.删除

    /* Remove the specified key. If 'deleted' is not NULL the pointed integer is
     * set to 0 if the key was not found, to 1 if it was found and deleted. */
    unsigned char *zipmapDel(unsigned char *zm, unsigned char *key, unsigned int klen, int *deleted) {
        unsigned int zmlen, freelen;
        unsigned char *p = zipmapLookupRaw(zm,key,klen,&zmlen);
        if (p) {
            freelen = zipmapRawEntryLength(p);
            memmove(p, p+freelen, zmlen-((p-zm)+freelen+1));
            zm = zipmapResize(zm, zmlen-freelen);
    
            /* Decrease zipmap length */
            if (zm[0] < ZIPMAP_BIGLEN) zm[0]--;
    
            if (deleted) *deleted = 1;
        } else {
            if (deleted) *deleted = 0;
        }
        return zm;
    }
    

    3.下一个

    /* This function is used to iterate through all the zipmap elements.
     * In the first call the first argument is the pointer to the zipmap + 1.
     * In the next calls what zipmapNext returns is used as first argument.
     * Example:
     *
     * unsigned char *i = zipmapRewind(my_zipmap);
     * while((i = zipmapNext(i,&key,&klen,&value,&vlen)) != NULL) {
     *     printf("%d bytes key at $p\n", klen, key);
     *     printf("%d bytes value at $p\n", vlen, value);
     * }
     */
    // (unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen ) is return value
    //迭代key
    unsigned char *zipmapNext(unsigned char *zm, unsigned char **key, unsigned int *klen, unsigned char **value, unsigned int *vlen) {
        if (zm[0] == ZIPMAP_END) return NULL;
        if (key) {
            *key = zm;
            *klen = zipmapDecodeLength(zm);
            *key += ZIPMAP_LEN_BYTES(*klen);
        }
        zm += zipmapRawKeyLength(zm);
        if (value) {
            *value = zm+1;
            *vlen = zipmapDecodeLength(zm);
            *value += ZIPMAP_LEN_BYTES(*vlen);
        }
        zm += zipmapRawValueLength(zm);
        return zm;
    }
    

    相关文章

      网友评论

          本文标题:redis zipmap (10)

          本文链接:https://www.haomeiwen.com/subject/aqqyfxtx.html