Redis是一个开源的Key-Value存储引擎,它支持string、hash、list、set和sorted set等多种值类型。由于其卓越的性能表现、丰富的数据类型及稳定性,广泛用于各种需要k/v存储的场景。甚至在一些分布式缓存系统中,也用它作为底层存储引擎。本文对redis最常用的数据类型进行剖析,从而让使用者在各自场景下选择合适的数据类型,从而发挥其最好的优势。

1、String

String是最常用的一种数据类型,普通的k/v存储都可以归为此类,内部由sds.h定义。在类型的设计上,除了包含字符数组buf,还会额外存储实际字符串的长度以及buf的剩余空间,从而提供更灵活的管理方式。特别需要提到的是,redis自己管理内存,从而自身可以掌握更多关于内存的信息,提高内存分配的性能以及作为其它功能的依据。此外,该结构还提供了一些字符串相关的操作函数,功能丰富,实现透明,使用方便。

常用命令:

命令

时间复杂度

描述

返回值

APPEND

O(1)

如果该Key已经存在,APPEND命令将参数Value的数据追加到已存在Value的末尾。如果该Key不存在,APPEND命令将会创建一个新的Key/Value。

追加后Value的长度

INCR

O(1)

将指定Key的Value原子性的递增1。如果该Key不存在,其初始值为0,在incr之后其值为1。如果Value的值不能转换为整型值,该操作将执行失败并返回相应的错误信息。

递增后的Value值

INCRBY

O(1)

将指定Key的Value原子性的增加increment。如果该Key不存在,其初始值为0,在incrby之后其值为increment。如果Value的值不能转换为整型值,该操作将执行失败并返回相应的错误信息。

增加后的Value值

DECR

O(1)

将指定Key的Value原子性的递减1。如果该Key不存在,其初始值为0,在decr之后其值为-1。如果Value的值不能转换为整型值,如Hello,该操作将执行失败并返回相应的错误信息。

递减后的Value值。

DECRBY

O(1)

将指定Key的Value原子性的减少decrement。如果该Key不存在,其初始值为0,在decrby之后其值为-decrement。如果Value的值不能转换为整型值,如Hello,该操作将执行失败并返回相应的错误信息。

减少后的Value值。

GET

O(1)

获取指定Key的Value。如果与该Key关联的Value不是string类型,Redis将返回错误信息。

与该Key相关的Value,如果该Key不存在,返回nil。

SET

O(1)

设定该Key持有指定的字符串Value,如果该Key已经存在,则覆盖其原有值。

返回"OK"

2、Hash

Hash是一个string类型的field和value的映射表,由dict.h定义。一个key可对应多个field,一个field对应一个value。将一个对象存储为hash类型,较于每个字段都存储成string类型更能节省内存,并且可以更方便的存取整个对象。hash内部存储的value为一个hashMap,并提供了直接存取这个Map成员的接口。

举个例子:我们要存储一个用户详细信息,就对每个用户设置一个userID作为key,而存储的value包含了包括姓名name,年龄age,生日birth,住址addr等信息。如果用普通的k/v结构存储,一般就是userID与value中的每一项组合作为key,而对应的内容作为value。如通过命令

mset user1_name ”张三” user1_age 18 user1_addr “杭州”

这种模式,在数据量大的时候,存在明显的内存浪费。而redis提供的hash结构就很好的解决了这个问题。对于上面的例子,通过执行命令hmset user1 name ”张三” age 18 addr “杭州”

user1作为key,而name、age、birth等作为属性。如此,便通过key+field的方式,避免了数据的重复存储。

提到Hash结构,不得不说的是key的冲突解决办法和哈希表的扩容方案。在Redis中,在冲突发生时,采取的是链式冲突解决办法。另外,redis采用了双哈希表结构(ht[2])。简单来说,就是初始k/v保存在ht[0]中,当冲突严重时,将ht[1]中桶的大小设置为ht[0]的两倍,并逐步将ht[0]中的元素迁移到ht[1]。等到所有元素都迁移完成后,再将ht[0]与ht[1]交换地址。

常用命令:

命令

时间复杂度

描述

返回值

HSET

O(1)

为指定的Key设定Field/Value对,如果Key不存在,该命令将创建新Key以参数中的Field/Value对,如果参数中的Field在该Key中已经存在,则用新值覆盖其原有值。

1表示新的Field被设置了新值,0表示Field已经存在,用新值覆盖原有值。

HGET

O(1)

返回指定Key中指定Field的关联值。

返回参数中Field的关联值,如果参数中的Key或Field不存,返回nil。

HEXISTS

O(1)

判断指定Key中的指定Field是否存在。

1表示存在,0表示参数中的Field或Key不存在。

3、List

List实现为一个双向链表,支持了反向的插入、查找和遍历,由adlist.h定义。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。在需要队列这样的数据结构时,List能提供非常丰富的接口,广泛用于缓冲队列,消息队列等应用场景。学过数据结构的朋友,对此肯定不会陌生。

常用命令:

命令

时间复杂度

描述

返回值

LPUSH

O(1)

在指定Key所关联的List Value的头部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的头部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。

插入后链表中元素的数量。

RPUSH

O(1)

在指定Key所关联的List Value的尾部插入参数中给出的所有Values。如果该Key不存在,该命令将在插入之前创建一个与该Key关联的空链表,之后再将数据从链表的尾部插入。如果该键的Value不是链表类型,该命令将返回相关的错误信息。

插入后链表中元素的数量。

LPOP

O(1)

返回并弹出指定Key关联的链表中的第一个元素,即头部元素。如果该Key不存,返回nil。

链表头部的元素。

RPOP

O(1)

返回并弹出指定Key关联的链表中的最后一个元素,即尾部元素。如果该Key不存,返回nil。

链表尾部的元素。

LLEN

O(1)

返回指定Key关联的链表中元素的数量,如果该Key不存在,则返回0。如果与该Key关联的Value的类型不是链表,则返回相关的错误信息。

链表中元素的数量。

4、Set

Set集合类型提供的是一个列表的功能,而且是可以自动去重的。它的内部实现其实是一个value值为null的HashMap,也正是因此来使得数据去重以及判断某个成员是否在集合内等其它一些重要接口变的简单。当某些应用场景需要存储一个列表,且不想要重复的数据时,就可以选择set这个结构来处理。

常用命令:

命令

时间复杂度

描述

返回值

SADD

O(N)

时间复杂度中的N表示操作的成员数量。如果在插入的过程用,参数中有的成员在Set中已经存在,该成员将被忽略,而其它成员仍将会被正常插入。如果执行该命令之前,该Key并不存在,该命令将会创建一个新的Set,此后再将参数中的成员陆续插入。如果该Key的Value不是Set类型,该命令将返回相关的错误信息。

本次操作实际插入的成员数量。

SREM

O(N)

时间复杂度中的N表示被删除的成员数量。从与Key关联的Set中删除参数中指定的成员,不存在的参数成员将被忽略,如果该Key并不存在,将视为空Set处理。

从Set中实际移除的成员数量,如果没有则返回0。

SCARD

O(1)

获取Set中成员的数量。

返回Set中成员的数量,如果该Key并不存在,返回0。

SISMEMBER

O(1)

判断参数中指定成员是否已经存在于与Key相关联的Set集合中。

1表示已经存在,0表示不存在,或该Key本身并不存在。

5、Sort Set

Sort Set的功能与Set非常相似,只不过它是可以通过用户提供一个优先级参数来实现自动排序的,而Set结构不会做自动排序。Sort set内部使用HashMap和SkipList来实现数据的有序存储,保证查询的效率以及元素有序性。在某些应用场景,比如需要为某个班级的学生根据成绩来排序,就可以将优先级参数设置为成绩分数,这样在插入到这个结构时,就可以实现自动的排序。

命令

时间复杂度

描述

返回值

APPEND

O(1)

如果该Key已经存在,APPEND命令将参数Value的数据追加到已存在Value的末尾。如果该Key不存在,APPEND命令将会创建一个新的Key/Value。

追加后Value的长度

INCR

O(1)

将指定Key的Value原子性的递增1。如果该Key不存在,其初始值为0,在incr之后其值为1。如果Value的值不能转换为整型值,该操作将执行失败并返回相应的错误信息。

递增后的Value值

INCRBY

O(1)

将指定Key的Value原子性的增加increment。如果该Key不存在,其初始值为0,在incrby之后其值为increment。如果Value的值不能转换为整型值,该操作将执行失败并返回相应的错误信息。

增加后的Value值

DECR

O(1)

将指定Key的Value原子性的递减1。如果该Key不存在,其初始值为0,在decr之后其值为-1。如果Value的值不能转换为整型值,如Hello,该操作将执行失败并返回相应的错误信息。

递减后的Value值。

DECRBY

O(1)

将指定Key的Value原子性的减少decrement。如果该Key不存在,其初始值为0,在decrby之后其值为-decrement。如果Value的值不能转换为整型值,如Hello,该操作将执行失败并返回相应的错误信息。

减少后的Value值。

GET

O(1)

获取指定Key的Value。如果与该Key关联的Value不是string类型,Redis将返回错误信息。

与该Key相关的Value,如果该Key不存在,返回nil。

SET

O(1)

设定该Key持有指定的字符串Value,如果该Key已经存在,则覆盖其原有值。

返回"OK"

redis常用数据结构解析的更多相关文章

  1. Redis常用数据结构

    Redis常用数据结构包括字符串(strings),列表(lists),哈希(hashes),集合(sets),有序集合(sorted sets). redis的key最大不能超过512M,可通过re ...

  2. php数组去重、魔术方法、redis常用数据结构及应用场景

    一.用函数对数组进行去重的方法 1.arrau_unique函数的作用 移除数组中重复的值. 将值作为字符串进行排序,然后保留每个值第一次出现的健名,健名保留不变. 第二个参数可以选择排序方式: SO ...

  3. Redis常用数据结构和操作

    1.String 存入字符类型 Set name luowen 设置name = luowen 存储 Get name 获取设置好的name的值 Setnx name luowen 设置name键值为 ...

  4. Redis 常用数据结构及其控制命令整合

    Redis 键值支持5种基本结构,分别是字符串,列表,哈希,集合,有序集合.每一种数据结构都有对应的取值和设值命令,辅助命令,除此之外,还有一些全局命令,用来管理Redis存储的所有 键. 全局命令 ...

  5. c#常用数据结构解析【转载】

    引用:http://blog.csdn.net/suifcd/article/details/42869341 前言:可能去过小匹夫博客的盆油们读过这篇对于数据结构的总结,但是小匹夫当时写那篇文章的时 ...

  6. Redis常用命令解析——INFO, MONITOR, SLOWLOG

    1. INFO info指令返回服务器相关信息,包括: server: General information about the Redis server clients: Client conne ...

  7. Redis 常用数据结构命令

    1. 字符串(string) 增加元素 set key value [EX seconds] [PX milliseconds] [NX|XX] EX seconds:为键设置秒级过期时间 PX mi ...

  8. Redis五种基础与三种高级数据结构解析

    记得点赞+关注呦. 前言 在 Redis 最重要最基础就属 它丰富的数据结构了,Redis 之所以能脱颖而出很大原因是他数据结构丰富,可以支持多种场景.并且 Redis 的数据结构实现以及应用场景在面 ...

  9. redis常用配置参数解析

    本文主要总结一下redis常用的配置参数的用法: 以下参数决定redis运行方式,默认前台运行,修改为yes可以让redis以后台守护进程方式运行 daemonize no 以下参数指定redis的p ...

随机推荐

  1. PAT1024 强行用链表写了一发。

    主要的思想还是 上课的那个PPT上面的 链表反转的思想. 然后加一点七七八八的 递推. 一层一层往下翻转就好啦. 1A 真开心. 代码:http://paste.ubuntu.net/16506799 ...

  2. ACM 第四天

    A - 最短路 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的 ...

  3. iOS- UITableViewCell对象是怎么重用的 ?

    iOS设备的内存有限,如果用UITableView显示成千上万条数据, 就需要成千上万个UITableViewCell对象的话, 那将会耗尽iOS设备的内存.要解决该问题,需要重用UITableVie ...

  4. python 爬虫 糗百成人

    import urllib from time import sleep import requests from lxml import etree try: def all_links(url,p ...

  5. Jenkins系列-Jenkins通过Publish over SSH插件实现远程部署

    配置ssh免秘钥登录 安装Publish over SSH插件 插件使用官网:https://wiki.jenkins.io/display/JENKINS/Publish+Over+SSH+Plug ...

  6. 制作QQ微信支付宝三合一收款码

    转载:http://blog.mambaxin.com/article/56 发现很多博客都带了打赏功能,虽说打赏的人可能很少,但始终是一份心意,能让博主知道自己写的文章有用,能够帮助到人.所以,我也 ...

  7. [OS] 进程间通信--管道

    管道是单向的.先进先出的.无结构的.固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起.写进程在管道的尾端写入数据,读进程在管道的首端读出数据.数据读出后将从管道中移走,其它读进 ...

  8. Redis架构演变与redis-cluster群集读写方案

    导言 redis-cluster是近年来redis架构不断改进中的相对较好的redis高可用方案.本文涉及到近年来redis多实例架构的演变过程,包括普通主从架构(Master.slave可进行写读分 ...

  9. 【bzoj1717】[Usaco2006 Dec]Milk Patterns 产奶的模式 后缀数组+离散化

    题目描述 农夫John发现他的奶牛产奶的质量一直在变动.经过细致的调查,他发现:虽然他不能预见明天产奶的质量,但连续的若干天的质量有很多重叠.我们称之为一个“模式”. John的牛奶按质量可以被赋予一 ...

  10. Codeforces Gym 101142 C. CodeCoder vs TopForces(思维+图论)

    题意: 每个人有两个积分CC和TF 第i个人能战胜第j个人的条件满足下面两个条件中的一个即可 1.CCi > CCj 或 TFi > TFj 2.i能战胜k,k能战胜j. 题解: 先按CC ...