String

字符串类型是redis的最基本类型,首先无论值是什么数据类型,其键都是字符串,且其他数据类型的数据结构都是在字符串的基础上搭建的,相信读者能够体会到字符串在redis的地位是有多么的重要。

那么字符串的值可以是什么呢?

  • 简单的字符串,复杂的字符串如JSON,XML的格式的字符串都是可以的。
  • 数字(整数、浮点数)
  • 二进制如音频、图片的

当然值的大小不是无限的,不然的话你买内存的钱就可以买整个宇宙了。redis规定其值最大不能大过512M。

操作String

  • 往redis种插入字符串类型的值

    set key value
  • 根据键获取值

    get key
  • 查看字符串长度

    strlen key
  • 批量设置值

    mset key value [key value]
  • 批量取值

    mget key [key]

批量操作的命令可有效地提高开发命令,但mget、mset的时间复杂度是O(n),因此一次设置的键值对多的话,可能会引起redis服务器的阻塞。

  • 如果字符串类型的值是数字,自增命令(每次加1)

    incr key
  • 指定每次加的值

    incrby key amount
  • 如果字符串类型的值是数字,自减命令(每次减1)

    decr key
  • 往字符串里面追加字符串 (类似JAVA中StringBuilder的append)

    append key value
  • 根据开始索引和结束索引获取字符串的部分

    getrange key start_index end_index
  • 根据索引设定指定位置的值

    setrange key index value
  • 设置后,其他命令不能够修改该键值,直到键删除或者时间到了后释放(redis官方给出了使用setnx实现分步锁的方式)

    set key value nx ex 10
  • 为键设置秒级过期时间/毫秒级过期时间

    setex/setpx key 10 value

String的内部编码

字符串类型的内部编码有三种类型:

  • int 8个字节的长整型
  • embstr 小于等于32字节的字符串
  • raw 大于32字节

redis的底层数据结构类似JAVA中的ArrayList类型,都是有着预分配冗余空间,防止反复的空间扩展降低效率,redis中规定如果当前的字符串大小小于1M时扩容都是当前大小的加倍,而如果字符串的大小大于1M的时候,无论大于多少只会扩容1M,而前面说到redis规定值的大小只有512M。

List

List类型是用来存储多个有序字符串的,List中的每个元素称为元素,可以往左push添加元素,也可以往右push元素,当然也可以获取指定范围的元素,还可以按照自己的需求获取List中指定的元素。一个列表中最多可以存储2^23-1个元素,它底层其实是一个双向的链表,对两端的性能很高,而通过索引下标操作中间的节点时性能会较差。

List有如下两个特点:

  • List中的元素都是有序的,因此我们能够根据索引或者起始位置加终止位置获取我们想要的值。
  • List中的元素是能够重复。

操作List

  • 往左插入元素

    lpush key value [value]
  • 往右插入元素

    rpush key value [value]
  • 往值位置的前面或者后面加入元素

    linsert key BEFORE|AFTER value new_value
  • 根据起始索引和终止索引查看范围的值

    lrange key start_index end_index
  • 根据值在列表中的索引查找值

    lindex key index
  • 获取列表的长度

    lren key
  • 弹出列表左边的元素

    lpop key
  • 弹出列表右边的元素

    rpop key
  • 删除指定元素

    lrem key count value

  • 裁剪列表

    ltrim key start_index end_index
  • 修改特定的值

    lset key index value
  • 阻塞式向右弹出

    brpop key
  • 阻塞式向左弹出

    blpop key

List内部编码

列表类型的内部编码有两种。

  • ziplist:当列表的值元素个数小于list-max-ziplist-entries(默认是512个),且每个元素的值小于64自己时,redis采用ziplist的形式存储列表,减少了内存的使用。
  • linkedlist:当列表其值不满足ziplist的条件的时候,redis会采用链表的形式存储值。

但在redis3.2版本之后(笔者采用的是redis6.2.5),当元素大于512个或元素大小超过64个字节,内部编码已从linkedlist变为quicklist。

quicklist采用了ziplist的优点和linkedlist的优点,也就是每个节点都是一个ziplist节点之间用双向的指针联系起来,这样即使得内存使用的减少满足了快速的插入和删除,也减少了空间的冗余。

Set

Set类型也是用来存储多个元素的,但是集合内的元素是无序的,而且它不允许有重复的元素出现在同一个键中,类似JAVA中的Set集合。这些特性促使了用户在操作集合时没有办法通过索引去查找元素,也没有办法去获取一个范围之内的值。与List一样,redis规定一个集合类型中最多可以存储2^23-1个元素,同时集合还支持交集、并集、差集,功能颇多。

操作Set

  • 往集合中插入元素

    sadd key value [value]
  • 删除集合中的元素

    srem key value
  • 查询一个集合中的元素的个数

    scard key
  • 判断一个元素于一个集合中存在与否

    sismember key value
  • 随机在集合中获取想要个数的元素(默认是一个)

    srandmember key [count]
  • 随机在集合中弹出想要个数的元素(默认是一个)

    spop key [count]
  • 查询一个集合中所有的元素

    smembers key
  • 对两个集合做交集计算

    sinter first_key second_key
  • 对两个集合做并集计算

    sunion first_key second_key
  • 对两个集合做差集计算

    sdiff first_key second_key
  • 将两个集合交\并\差集的计算结果存入另一个键中

    sinterstore store_key first_key second_key
    sunionstore store_key first_key second_key
    sdiffstore store_key first_key second_key

Set的内部编码

  • intset:当集合中的元素都是整数且元素的个数不超过set-max-intset-entries(512)时,redis内部用intset来实现集合,目的还是为了减少内存的使用。
  • hashtable:当集合内部的元素类型、个数不满足intset的要求的话,redis将用hsahtable来实现集合的内部。就如JAVA中的HashSet一样其内部使用HashMap来实现的,只不过是多个值对一个键,hashtable和其一样,内部都是用HashMap来实现的,也是多个值对一个键。

Hash

Hash可以是哈希,字典,也可以是关联数组。在redis中,哈希类型指值是一个键值对结构,这有点套娃,不知道为什么笔者总感觉其值很像JSON对象。哈希类型中的映射关系叫作field-value,这里的value是指值中field对应的值,可不敢是键的值。笔者认为Hash特点适合去存储对象,当然String类型也可以去存储对象的信息,但是你说一个人的特征拆成块,放到大海中,需要的时候去寻找,你就不怕男变女吗? Hash中键可以存储多个field-value,每个field不能相同,field与value映射,这就很好地把一个对象兜起来了。

操作Hash

  • 插入数据

    hset key field value [field value]
  • 根据field取出值

    hget key field
  • 批量插入数据

    hmset key field value [key field value]
  • 根据field批量取出数据

    hmget key field [field]
  • 根据field删除数据

    hdel key field [field]
  • 查看哈希类型所有的field

    hkeys key
  • 查看哈希类型所有的value

    hvals key
  • 判断field是否存在

    hexists key field
  • 获取哈希所有的field-value

    hgetall key

Hash内部编码

  • ziplist: 当哈希类型元素小于hash-max-ziplist-entries(默认512个),且其大小小于hash-max-ziplist-value(62字节)时,redis内部采用ziplist形式对其编码,目的是为了减少内存的使用,为什么?因为内存很贵啊。
  • hashtable: 当哈希类型元素不满足ziplist的条件时,redis内部使用hashtable的形式对其编码。hashtable就像JAVA中的HashSet一样,底层都是用HashMap实现的,特点是一个键对多个值,我想哈希类型的field-value十分像Map<String,Object>,可能其底层是Map<String,Map<String,Object>>,很套娃很喜欢。

Zset

Zset与Set相似,一样是集合,集合中的元素不能够相同,但是不同的是有序集合的每一个元素都有自己的分数,所以有序集合可以根据分数来进行排序,这也说明我们能够以索引/分数的方式获取到一个或者一个范围中的值。在实际的开发中,有序集合给我们提供了分数查询,范围查询,事物排行榜的功能。

尽管有序集合中,元素不能够相同,但是各元素的分数是能够相同的!拜托!你是你我是我,又不是抄你试卷,为什么分数不能一样呢?

操作Zset

  • 往有序集合中添加元素

    zadd key score value [score value]
  • 删除有序集合中的元素

    zrem key value
  • 计算有序集合中元素的个数

    zcard key
  • 计算某个元素的分数

    zscore key value
  • 查询某个元素的排名

    zrank key value
    zrevrank key value//倒序排名
  • 获取指定排名的元素

    zrange key start end
    zrange key start end withscores
    zrevrange key start end
    zrevrange key start end withscores

有序集合是按照分数的高低来排名的,所以zrange命令获取的是一份从低到高的排行榜,zrevrange反之,而后面带着withscores命令的,在展示排行榜的时候会带上每一个元素的分数。

  • 为指定元素增加指定分数

    zincrby key value score
  • 根据分数的范围获取指定范围的元素

    zrangebyscore key min max  [withscores]
    zrevrangebyscore key max min [withscores]

其中min、max支持开区间,闭区间,而-inf和+inf分别代表无穷小和无穷大。

示例:

  • 有序集合的交\并\差集计算

    zinterstore store_key num_key actual_key [actual_key]
    zunionstore store_key num_key actual_key [actual_key]
    zdiffstore store_key num_key actual_key [actual_key]

此计算与集合的计算一致,多了个num_key,其实就是你要计算的键的数量,相较于集合来说便是一次可计算多个键。

Zset内部编码

  • ziplist: 当有序集合中的元素个数不超过zset-max-ziplist-entires(512),且每个元素的大小不超过zset-max-ziplist-value时,zset在redis的内部编码是ziplist,减少内存的使用。
  • skiplist: 当有序集合里的元素不满足ziplist的条件时,zset在redis的内部编码是shiplist,俗称跳跃表。

所谓的跳跃表便是不循环地遍历每个节点,而是跳跃形式地搜查,如果搜查到的节点比要找的节点要小的话便继续跳跃搜查,如果要大的话,便转换到下一层的搜查,直到找到为止,这比ziplist的查找减少了次数,提高了查找的效率。

似乎redis的单线程结构挺重要的,但是由于我现在不想写,所以等有空的时候吧。

Redis5种常用数据类型的使用以及内部编码的更多相关文章

  1. Java中几种常用数据类型之间转换的方法

    Java中几种常用的数据类型之间转换方法: 1. short-->int 转换 exp: short shortvar=0; int intvar=0; shortvar= (short) in ...

  2. Redis5种常用的数据结构

    一.数据结构 五种常用的数据结构:string.hash.list.set.zse,以及三种不常用的:hyperloglog.geospatial.streams. 二.常用数据结构的使用 1.Str ...

  3. Redis五种常用数据类型

    string 字符串常用操作 1.存入字符串键值对  SET key value 2.批量存储字符串键值对  MSET key value [key value ...] 3.获取一个字符串键值  G ...

  4. 04Redis入门指南笔记(内部编码规则简介)

    Redis是一个基于内存的数据库,所有的数据都存储在内存中.所以如何优化存储,减少内存空间占用是一个非常重要的话题.精简键名和键值是最直观的减少内存占用的方式,如将键名very.important.p ...

  5. Java常用类之【八种基本数据类型】

    一.装箱和拆箱 装箱:将基本数据类型包装为对应的包装类对象 拆箱:将包装类对象转换成对应的基本数据类型 JDK5.0中为基本数据类型提供了自动装箱(boxing).拆箱(unboxing)功能 二.八 ...

  6. 二、python 中五种常用的数据类型

    一.字符串 单引号定义: str1 = 'hello' 双引号定义: str1 = "hello" 三引号定义:""" 人生苦短, 我用python! ...

  7. NoSQL初探之人人都爱Redis:(2)Redis API与常用数据类型简介

    一.Redis API For .Net 首先,不得不说Redis官方提供了众多的API开发包,但是目前Redis官方版本不支持.Net直接进行连接,需要使用一些第三方的开源类库.目前最流行的就是Se ...

  8. 【转】NoSQL初探之人人都爱Redis:(2)Redis API与常用数据类型简介

    一.Redis API For .Net 首先,不得不说Redis官方提供了众多的API开发包,但是目前Redis官方版本不支持.Net直接进行连接,需要使用一些第三方的开源类库.目前最流行的就是Se ...

  9. Redis常用数据类型介绍、使用场景及其操作命令

    Redis常用数据类型介绍.使用场景及其操作命令 本文章同时也在cpper.info发布. Redis目前支持5种数据类型,分别是: 1.String(字符串) 2.List(列表) 3.Hash(字 ...

随机推荐

  1. LeetCode42. 接雨水(java)

    42.接雨水 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水. 上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种 ...

  2. java 将字符串拆分成块装数组

    split 将字符串拆分 regex=???,根据???以其为界进行拆分. public String[] split(String regex) 根据给定正则表达式的匹配拆分此字符串. 该方法的作用 ...

  3. opencv入门系列教学(六)图像上的算术运算(加法、融合、按位运算)

    0.序言 这一篇博客我们将学习图像的几种算术运算,例如加法,减法,按位运算等. 1.图像加法 我们可以通过OpenCV函数 cv.add() 或仅通过numpy操作 res=img1+img2 res ...

  4. 接口测试进阶接口脚本使用--apipost(预/后执行脚本)

    预执行脚本的作用时间 预执行脚本是一个请求发送前执行的脚本. 预执行脚本的作用 预执行脚本可以完成以下作用: 编写JS函数等实现复杂计算: 变量的打印 定义.获取.删除.清空环境变量 定义.获取.删除 ...

  5. 笔记本+ubuntu18.04 关闭触摸板touchpad

    方法1: Settings -> Devices -> Mouse&Touchpad -> Touchpad OFF 方法2: 终端运行如下命令 touchpad off:  ...

  6. Spring Boot 入门系列(二十三)整合Mybatis,实现多数据源配置!

    d之前介绍了Spring Boot 整合mybatis 使用注解方式配置的方式实现增删改查以及一些复杂自定义的sql 语句 .想必大家对spring boot 项目中,如何使用mybatis 有了一定 ...

  7. cmd(命令行)超好用的技巧,很不错的打开方式

    超快速打开管理cmd widows + x 按a 直接打开文件位置,在地址栏输入cmd 地址----直接cmd打开到所在文件位置 ex:cmd D:\work cd ../../../ 返回上几层的方 ...

  8. Sublime Text 快速分别独立选中多行

    效果图 直接上代码 import sublime, sublime_plugin # 独立选择每一行(在当前选中范围内) class SelectEverySingleLine(sublime_plu ...

  9. 微信小程序基础知识笔记

    微信小程序笔记 文件构成 全局文件 app.json 小程序全局配置文件,必要,自动生成 app.js 小程序入口JS文件,一般只需申明全局变量.处理生命周期以及版本升级即可,必要 app.wxss ...

  10. Java最大栈深度有多大?-从一道面试题开始学习JVM

    一.问题:Java最大支持栈深度有多大? 1.分析 有JVM的内存结构我们可知: 随着线程栈的大小越大,能够支持越多的方法调用,也即是能够存储更多的栈帧: 局部变量表内容越多,那么栈帧就越大,栈深度就 ...