前言:set类似于数学上面的集合概念,包含的元素无序,不能重复,能进行交、并、差操作。

一、内部原理

             set数据结构,也是随着元素数目的多少而变化。当set中添加的元素都是整数且元素数据较少时,set使用intset为底层的数据结构,否则,set使用dict作为底层的数据结构。

   intset是什么?

             从字面意思可以看出是由整数组成的集合。是一个整数组成的有序集合,便于进行二分查找,快速判断一个元素是否属于这个集合。内存分配上也是一整块连续的内存空间,而且根据数值的大小采取了不同的编码,对内存使用进行了优化。
             intset数据结构如下:

 typedef struct intset {
uint32_t encoding;/*数据编码,表示intset中每个数据元素用几个字节来存储。有三种:数据编码,表示intset中每个数据元素用几个字节来存储。
1.INTSET_ENC_INT16表示每个元素用2个字节存储,
2.INTSET_ENC_INT32表示每个元素用4个字节存储,
3.INTSET_ENC_INT64表示每个元素用8个字节存储。
因此,intset中存储的整数最多只能占用64bit*/
uint32_t length; /*元素个数。encoding和length组成了intset头部。*/
int8_t contents[]; /*是一个柔性数组,表示intset的header后面紧跟着数据元素。这个数组的总长度(即总字节数)等于encoding * length*/
} intset;

注:intset可能会随着数据的添加而改变它的数据编码,创建时intset使用占内存最小的INTSET_ENC_INT16作为编码,每增加一个元素,则根据大小决定是否对数据编码进行改变。

例子:

     如上图:
             1、新建一个intset只有一个header,总共8个字节,encoding=2,length=0。
             2.、添加6,15之后,因为数值较小,所以encoding不变,length=2。
             3、添加32768的时候,超过了两个字节(2个字节能表达的数据范围是-32768~32767),此时encoding升级到INTSET_ENC_INT32为4,即用4个字节表示一个元素。
             4、添加元素都是按照从小到大的顺序。
             5、intset是按little endian模式存储的。在上图intset添加完所有数据之后,32768=>0x00008000
             什么时间转为dict?
             1、大于512,默认设置:set-max-intset-entries 512
             2、超出最大范围-264~264-1
             3、元素里面包含非数字
             set底层用dict时,key是要添加的元素,value为NULL。
             区别:
             小集合(整数)用intset存储节省内存。dict带来的开销很大(包含元数据信息,两个hash表、链表指针等等)
             从时间复杂度上看,intset是o(log n),而dict可以认为是o(1)(因为zipmap),但是intset元素个数较少,影响不大

二、相关操作
             SADD key member [member ...]
             将一个或多个元素加入到集合key中,已存在被忽略。若不存在,则创建。
             SCARD key
             返回集合key的数目。
             SDIFF key [key ...]
             返回集合之间的差集
             SDIFFSTORE destination key [key ...]
             返回集合之间的差集,并将结果存储到目标集合。
             SINTER key [key ...]
             返回集合集合之间的交集
             SINTERSTORE destination key [key ...]
             返回集合之间的交集,并将结果存储到目标集合。
             SISMEMBER key member
             判断元素是否属于集合key的成员。
             SMOVE source destination member
             将元素从源集合移动到目标集合。
             SPOP key
             随机移除key集合的某一元素,并返回该元素。
             SRANDMEMBER key [count]
             随机返回一个key集合的元素,若提供count参数,则返回一个包含count个元素的数组。
             SREM key member [member ...]
             移除集合中的一个或多个元素。不存在则忽略。
             SUNION key [key ...]
             返回若干个集合的并集。
             SUNIONSTORE destination key [key ...]
             返回若干个集合的并集,并存储在目标集合

Redis数据类型之Set(四)的更多相关文章

  1. 四、redis数据类型

    四.redis数据类型 redis可以理解成一个全局的大字典,key就是数据的唯一标识符.根据key对应的值不同,可以划分成5个基本数据类型. 1. string类型: 字符串类型,是 Redis 中 ...

  2. redis数据类型-散列类型

    Redis数据类型 散列类型 Redis是采用字典结构以键值对的形式存储数据的,而散列类型(hash)的键值也是一种字典结构,其存储了字段(field)和字段值的映射,但字段值只能是字符串,不支持其他 ...

  3. 二:Redis数据类型

    一.nosql(非关系性数据库): mongoDB hbase redis nulch hive pig mahout zookeeper 二:redis 数据类型 1.存储string: 常用命令 ...

  4. Redis学习笔记(二) Redis 数据类型

    Redis 支持五种数据类型:string(字符串).list(列表).hash(哈希).set(集合)和 zset(有序集合),接下来我们讲解分别讲解一下这五种类型的的使用. String(字符串) ...

  5. redis深入学习(一)-----CAP、redis数据类型

    NoSQL数据库的四大分类 KV键值: memcache+redis 文档型数据库(bson格式比较多): MongoDB MongoDB 是一个基于分布式文件存储的数据库.由 C++ 语言编写.旨在 ...

  6. redis教程(一)-----redis数据类型、基本命令、发布订阅以及持久化

    简介 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发工作由VMwa ...

  7. redis基础:redis下载安装与配置,redis数据类型使用,redis常用指令,jedis使用,RDB和AOF持久化

    知识点梳理 课堂讲义 课程计划 1. REDIS 入 门 (了解) (操作)   2. 数据类型 (重点) (操作) (理解) 3. 常用指令   (操作)   4. Jedis (重点) (操作) ...

  8. 初识redis数据类型

    初识redis数据类型 1.String(字符串) string是redis最基本的类型,一个key对应一个value. string类型是二进制安全的.意思是redis的string可以包含任何数据 ...

  9. redis数据类型及使用场景

    Redis数据类型  String: Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字. 常用命令:  set,get,decr,incr,mge ...

  10. Redis数据类型介绍

    Redis 数据类型 Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合). String(字符串) st ...

随机推荐

  1. nginx访问日志出现大量的500状态信息,用postman返回 Internal Server Error,Too Many Attempts.错误的解决办法

    用postman的post方法访问某个URL时,出现以下错误: { "status": "1", "message": " Int ...

  2. [Leetcode] Backtracking回溯法解题思路

    碎碎念: 最近终于开始刷middle的题了,对于我这个小渣渣确实有点难度,经常一两个小时写出一道题来.在开始写的几道题中,发现大神在discuss中用到回溯法(Backtracking)的概率明显增大 ...

  3. Integer.parseInt不同jdk源码解析

    执行以下代码: System.out.println(Integer.parseInt("-123")); System.out.println(Integer.parseInt( ...

  4. P2572 [SCOI2010]序列操作

    对自己 & \(RNG\) : 骄兵必败 \(lpl\)加油! P2572 [SCOI2010]序列操作 题目描述 lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要 ...

  5. Java基础-程序流程控制第二弹(循环结构)

    Java基础-程序流程控制第二弹(循环结构) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 流程控制有三种基本结构:顺序结构,选择结构和循环结构.一个脚本就是顺序结构执行的,选择结 ...

  6. 安装lsb_release

    lsb_release命令用来查看当前系统的发行版信息(prints certain LSB (Linux Standard Base) and Distribution information.). ...

  7. [洛谷P3643] [APIO2016]划艇

    洛谷题目链接:[APIO2016]划艇 题目描述 在首尔城中,汉江横贯东西.在汉江的北岸,从西向东星星点点地分布着 \(N\) 个划艇学校,编号依次为 \(1\) 到 \(N\).每个学校都拥有若干艘 ...

  8. Redis学习五:Redis的持久化-RDB

    RDB(Redis DataBase) 一.是什么 1.概念:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里 2.执行方式: R ...

  9. NYOJ 123 士兵杀敌(四) (线段树)

    题目链接 描述 南将军麾下有百万精兵,现已知共有M个士兵,编号为1~M,每次有任务的时候,总会有一批编号连在一起人请战(编号相近的人经常在一块,相互之间比较熟悉),最终他们获得的军功,也将会平分到每个 ...

  10. beego项目运行过程

    一:首先man.go,整个程序的入口 func main() { beego.Run() } 然后beego.run()代码 // Run beego application. // beego.Ru ...