Set详解 [toc]
Set是Redis中的单列集合,具有以下特点:
Set的底层是哈希表,也就是Dict数据结构。
Dict中的key用来存储元素,value一律设为null(Redis6)
Redis7中,若元素数量不多,使用listpack
当存储的所有数据都是整数,且元素数量不超过set-max-intset-entries时,Set会采用intset编码,节省内存。
当插入元素时Redis会进行检查,如果不满足条件,编码将转换为HT(listpack / intset -> HT)
示例: 以下是基于Redis6的示例图。
空Set插入三个整数5、10、20。由于插入的都是整数,且数量较少,因此采用intset编码。
之后插入了字符串,不满足条件,编码由intset转为HT。
源码
1 2 3 4 5 6 robj *setTypeCreate (sds value) { if (isSdsRepresentableAsLongLong(value,NULL ) == C_OK) return createIntsetObject(); return createSetObject(); }
1 2 3 4 5 6 7 8 9 10 11 12 13 robj *setTypeCreate (sds value, size_t size_hint) { if (isSdsRepresentableAsLongLong(value,NULL ) == C_OK && size_hint <= server.set_max_intset_entries) return createIntsetObject(); if (size_hint <= server.set_max_listpack_entries) return createSetListpackObject(); robj *o = createSetObject(); dictExpand(o->ptr, size_hint); return o; }
1 2 3 4 5 6 7 8 void setTypeMaybeConvert (robj *set , size_t size_hint) { if ((set ->encoding == OBJ_ENCODING_LISTPACK && size_hint > server.set_max_listpack_entries) || (set ->encoding == OBJ_ENCODING_INTSET && size_hint > server.set_max_intset_entries)) { setTypeConvertAndExpand(set , OBJ_ENCODING_HT, size_hint, 1 ); } }