前言: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数据类型 1.String(字符串) string是redis最基本的类型,一个key对应一个value. string类型是二进制安全的.意思是redis的string可以包含任何数据 ...

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

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

  3. Redis数据类型介绍

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

  4. redis数据类型

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

  5. Redis-cluster集群【第一篇】:redis安装及redis数据类型

    Redis介绍: 一.介绍 redis 是一个开源的.使用C语言编写的.支持网络交互的.可以基于内存也可以持久化的Key-Value数据库. redis的源码非常简单,只要有时间看看谭浩强的C语言,在 ...

  6. Lua 数据类型和 Redis 数据类型之间转换

    当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候,命令的返回值会被转换成 Lua 数据结构. 同样地,当 Lua 脚本在 Redis 内置的解释器里运行时,Lua ...

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

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

  8. redis数据类型-字符串类型

    Redis数据类型 字符串类型 字符串类型是Redis中最基本的数据类型,它能存储任何形式的字符串,包括二进制数据.你可以用其存储用户的邮箱.JSON化的对象甚至是一张图片.一个字符串类型键允许存储的 ...

  9. redis笔记总结之redis数据类型及常用命令

    三.常用命令 3.1 字符串类型(string) 字符串类型是Redis中最基本的数据类型,一个字符串类型的键允许存储的数据的最大容量为512MB. 3.1.1 赋值与取值: SET key valu ...

  10. redis介绍、安装、redis持久化、redis数据类型

    1.redis介绍  2.安装管网:https://redis.io/下载:wget -c http://download.redis.io/releases/redis-4.0.11.tar.gz解 ...

随机推荐

  1. Java设计模式随笔

    大家都知道Java23种设计模式,大神总结如下: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接 ...

  2. Python安装mysqldb

    1.根据Python版本和自己的系统下载mysqldb http://www.codegood.com/downloads

  3. pdf.js实现在HTML下直接浏览pdf文档,无需插件即可实现

    近期,有一个朋友做B端,服务器存了大量的金融类数据,很多都是pdf文档,他现在的做法是,先将pdf文档转换成flash,再放到浏览器上给用户浏览,但是他告诉我,这种体验太差了,而且很好资源,空间已经快 ...

  4. Docker - 定制镜像

    Dockerfile Docker Hub拥有大量高质的官方镜像:可直接使用的服务类镜像.语言应用镜像.基础操作系统镜像等,满足绝大部分需求. 此外,可以通过定制镜像的方式来满足实际使用中的特定需求. ...

  5. elasticsearch系列(二) esrally压测

    环境准备 linux centOS(工作环境) python3.4及以上 pip3 JDK8 git1.9及以上 gradle2.13级以上 准备过程中的坑 这些环境准备没什么太大问题,都是wget下 ...

  6. dbunit进行DAO层Excel单元测试

    DAO层测试难点 可重复性,每次运行单元测试,得到的数据是重复的 独立性,测试数据与实际数据相互独立 数据库中脏数据预处理 不能给数据库中数据带来变化 DAO层测试方法 使用内存数据库,如H2.优点: ...

  7. Android开发中使用static变量应该注意的问题

    package com.highxin.launcher01; import java.util.ArrayList; import java.util.HashMap; import java.ut ...

  8. swfit - 实现类似今日头条顶部标签和底部内容的动态解决方案

    TYPageView TYPageView 类似今日头条 的标签导航解决方案,支持多种样式选择,基于swift3.0,支持文字颜色动态变化,底部选中线的动态变化 配图: 使用方法: let title ...

  9. 开涛spring3(6.9) - 对JDBC的支持 之 7.1 概述

    7.1  概述 7.1.1  JDBC回顾 传统应用程序开发中,进行JDBC编程是相当痛苦的,如下所示: //cn.javass.spring.chapter7. TraditionalJdbcTes ...

  10. APP为什么需要着陆页

    小编APP运营团队一直认为,虽然大多数的用户会在App Store或安卓应用商店中搜寻我们的应用,但也有许多用户会通过传统的PC端搜索来寻找答案.而且在APP营销中,为了更好的将用户转换为下载或购买, ...