Redis的多种数据类型(含常用命令)

131 阅读15分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

上一篇Redis安装和配置(Windows和Linux)介绍了如何在Windows和Linux下安装redis以及简单上手实例

​Redis五种基本的数据类型有string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合),还有一些高级数据结构HyperLogLog、Geo、Bit

本系列采用的redis版本是redis-4.0.10,基于Linux系统。关于Redis命令只会例举最常用的,不会全部例举,重点是学会看文档自己应用,在实际应用中如果应用到更多命令可以到doc.redisfans.com/或者http://re…

String

redis是key-value型数据库,string 是 redis 最基本的类型,一个 key 对应一个 value。string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB

SET命令

**语法:**set key value [EX seconds] [PX milliseconds] [NX|XX]

**功能:**给一个key添加字符串类型的值,如果该key已经存在,值会被新值覆盖,不论是上面类型的key。set设置后的键,之前的生存时间会被丢弃。

**选项:**EX seconds(生存时间:秒)/PX milliseconds(生存时间:毫秒)/NX(仅在键不存在时设置)/XX(仅在键存在时设置)

GET命令

**语法:**get key **功能:**查询key的值

set和get命令演示如下:

    127.0.0.1:6379> set key value    OK    127.0.0.1:6379> get key    "value"      127.0.0.1:6379> set key value EX 1000    OK    127.0.0.1:6379> ttl key    (integer) 993   (剩余时间)    127.0.0.1:6379> set key value PX 2000000    OK    127.0.0.1:6379> ttl key    (integer) 1996    (剩余时间)    127.0.0.1:6379> set NotExistsKey value NX    OK    (Key不存在时设置NX参数设置成功)    127.0.0.1:6379> set NotExistsKey value NX    (nil)   (Key存在时设置NX参数设置失败,需用XX参数)

MSET命令

**语法:**mset key value [key value…]

**功能:**同时设置多个key,如果key存在会覆盖。MSET是原子的,所有键会同时设置成功或者失败。

MGET命令

**语法:**mget key [key…]

**功能:**查询所有key的值。列出所有键的值,绝不会执行失败,如果键是string类型,返回其值,如果键不存在或者不是string类型,返回nil

代码示例如下:

  127.0.0.1:6379> mset key1 value1 key2 value2  OK  127.0.0.1:6379> mget key1 key2  1) "value1"  2) "value2"

SETEX命令

**语法:**setex key seconds value

功能:

  1. 将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。如果 key 已经存在, SETEX 命令将覆写旧值。

  2. 不同之处是, SETEX 是一个**原子性(atomic)**操作,关联值和设置生存时间两个动作会在同一时间内完成,该命令在 Redis 用作缓存时,非常实用。

PSETEX命令

**语法:**psetex key milliseconds value

**功能:**这个命令和 SETEX 命令相似,但它以毫秒为单位设置 key 的生存时间,而不是像 SETEX 命令那样,以秒为单位。

SETNX命令

**语法:**SETNX key value

**功能:**将 key 的值设为 value ,当且仅当 key 不存在。若给定的 key 已经存在,则 SETNX 不做任何动作。SETNX 是『SET if Not eXists』(如果不存在,则 SET)的简写。

MSETNX命令

**语法:**MSETNX key value [key value…]

**功能:**同时设置多个key,如果一个key存在则设置失败,不考虑其他键是否存在。MSETNX是原子的,所有键会同时设置成功或者失败。

Hash

Redis hash 是一个键值(key-value)对集合,是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。每个 hash 可以存储 232 -1 键值对(40多亿)

HSET命令

**语法:**HSET hash field value

功能:将哈希表 hash 中域 field 的值设置为 value 。如果给定的哈希表并不存在, 那么一个新的哈希表将被创建并执行 HSET 操作。如果域 field 已经存在于哈希表中, 那么它的旧值将被新值 value 覆盖。

HGET命令

**语法:**HGET hash field

**功能:**HGET 命令在默认情况下返回给定域的值。如果给定域不存在于哈希表中, 又或者给定的哈希表并不存在, 那么命令返回 nil 。

代码示如下:

  127.0.0.1:6379> hset xiaoming year 18  (integer) 1  127.0.0.1:6379> hget xiaoming year  "18"  127.0.0.1:6379> hset xiaoming school yingcai  (integer) 1  127.0.0.1:6379> hget xiaoming school  "yingcai"

HSETNX命令

**语法:**HSETNX hash field value

**功能:**当且仅当域 field 尚未存在于哈希表的情况下, 将它的值设置为 value 。如果给定域已经存在于哈希表当中, 那么命令将放弃执行设置操作。如果哈希表 hash 不存在, 那么一个新的哈希表将被创建并执行 HSETNX 命令。

代码示例如下:

  127.0.0.1:6379> hsetnx xiaoming school haihe  (integer) 0  127.0.0.1:6379> hget xiaoming school  "yingcai"  127.0.0.1:6379> hsetnx xiaoming sex 1  (integer) 1  127.0.0.1:6379> hget xiaoming sex  "1"

HMSET命令

**语法:**HMSET key field value [field value …]

**功能:**同时将多个 field-value (域-值)对设置到哈希表 key 中。此命令会覆盖哈希表中已存在的域。如果 key 不存在,一个空哈希表被创建并执行 HMSET 操作。

HMGET命令

**语法:**HMGET key field [field …]

**功能:**返回哈希表 key 中,一个或多个给定域的值。如果给定的域不存在于哈希表,那么返回一个 nil 值。因为不存在的 key 被当作一个空哈希表来处理,所以对一个不存在的 key 进行 HMGET 操作将返回一个只带有 nil 值的表。

代码示例如下:

  127.0.0.1:6379> hmset cxk name shuai year 18 sex 1  OK  127.0.0.1:6379> hmget cxk name year sex  1) "shuai"  2) "18"  3) "1"

List

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边),可以简单的理解为双向链表,但是List底层的存储是由两种数据结构压缩列表ziplist和双向链表linkedlist实现的,因为双向链表占用的内存比压缩列表要多, 所以当创建新的列表键时, 列表会优先考虑使用压缩列表, 并且在有需要的时候, 才从压缩列表实现转换到双向链表实现

LPUSH命令

**语法:**LPUSH key value [value …]

功能:将一个或多个值 value 插入到列表 key 的表头,如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表头。对空列表 mylist 执行命令 LPUSH mylist a b c ,列表的值将是 c b a ,这等同于原子性地执行 LPUSH mylist a 、 LPUSH mylist b 和 LPUSH mylist c 三个命令。如果 key 不存在,一个空列表会被创建并执行 LPUSH 操作。

LPOP命令

**语法:**LPOP key

**功能:**移除并返回列表 key 的头元素,列表的头元素。当 key 不存在时,返回 nil 。

RPUSH命令

**语法:**RPUSH key value [value …]

功能:将一个或多个值 value 插入到列表 key 的表尾(最右边)。如果有多个 value 值,那么各个 value 值按从左到右的顺序依次插入到表尾。比如对一个空列表 mylist 执行 RPUSH mylist a b c ,得出的结果列表为 a b c ,等同于执行命令 RPUSH mylist a 、 RPUSH mylist b 、 RPUSH mylist c 。如果 key 不存在,一个空列表会被创建并执行 RPUSH 操作。当 key 存在但不是列表类型时,返回一个错误。

RPOP命令

**语法:**RPOP key

**功能:**移除并返回列表 key 的尾元素。列表的尾元素。当 key 不存在时,返回 nil 。

代码示例如下:

  127.0.0.1:6379> lpush lst1 LValue1  (integer) 1  127.0.0.1:6379> lpush lst1 LValue2 LValue3  (integer) 3  127.0.0.1:6379> lpop lst1  "LValue3"  127.0.0.1:6379> rpop lst1  "LValue1"

Set

Redis的Set是string类型的无序集合,不包含重复元素。和列表一样,在执行插入和删除和判断是否存在某元素时,效率是很高的。

集合最大的优势在于可以进行交集并集差集操作。Set可包含的最大元素数量是4294967295。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)

SADD命令

**语法:**SADD key member [member …]

**功能:**将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。假如 key 不存在,则创建一个只包含 member 元素作成员的集合。当 key 不是集合类型时,返回一个错误。在Redis2.4版本以前, SADD 只接受单个 member 值。

SPOP命令

**语法:**SPOP key

**功能:**移除并返回集合中的一个随机元素。

SRANDMEMBER命令

**语法:**SSRANDMEMBER key [count]

**功能:**如果命令执行时,只提供了 key 参数,那么返回集合中的一个随机元素。从 Redis 2.6 版本开始。

SRANDMEMBER 命令接受可选的 count 参数,如果 count 为正数,且小于集合基数,那么命令返回一个包含 count 个元素的数组,数组中的元素各不相同。如果 count 大于等于集合基数,那么返回整个集合。如果 count 为负数,那么命令返回一个数组,数组中的元素可能会重复出现多次,而数组的长度为 count 的绝对值。

SISMEMBER命令

**语法:**SISMEMBER key member

**功能:**判断 member 元素是否集合 key 的成员。

示例代码如下:

  127.0.0.1:6379> sadd myset va1 va2 va3 va2  (integer) 3  127.0.0.1:6379> srandmember myset 4  1) "va1"  2) "va3"  3) "va2"  127.0.0.1:6379> sismember myset va1  (integer) 1

ZSet

有序集合,Redis zset 和 set 一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。zset的成员是唯一的,但分数(score)却可以重复。sorted set是插入有序的,即自动排序。

ZADD命令

**语法:**ZADD key score member [[score member] [score member] …]

**功能:**判断 member 元素是否集合 key 的成员。

ZSCORE命令

**语法:**ZSCORE key member

**功能:**返回有序集 key 中,成员 member 的 score 值。如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。

ZRANGE命令

**语法:**ZRANGE key start stop [WITHSCORES]

**功能:**返回有序集 key 中,指定区间内的成员。其中成员的位置按 score 值递增(从小到大)来排序。具有相同 score 值的成员按字典序 lexicographical order来排列。如果需要成员按 score 值递减(从大到小)来排列,可以使用 ZREVRANGE命令,语法相同;

下标参数 start 和 stop 都以 0 为底,也就是说,以 0 表示有序集第一个成员,以 1 表示有序集第二个成员,以此类推。你也可以使用负数下标,以 -1 表示最后一个成员, -2 表示倒数第二个成员,以此类推。

ZCARD命令

**语法:**ZCARD key

**功能:**返回有序集 key 的基数。当 key 存在且是有序集类型时,返回有序集的基数。当 key 不存在时,返回 0 。

代码示例如下:

  127.0.0.1:6379> zadd myset2 100 ming  (integer) 1  127.0.0.1:6379> zadd myset2 200 uzi  (integer) 1  127.0.0.1:6379> zadd myset2 300 hu  (integer) 1  127.0.0.1:6379> zscore myset2 uzi  "200"  127.0.0.1:6379> zrange myset2 0 3 WITHSCORES  1) "ming"  2) "100"  3) "uzi"  4) "200"  5) "hu"  6) "300"  127.0.0.1:6379> zcard myset2  (integer) 3

HyperLogLog

HyperLogLog可以接受多个元素作为输入,并给出输入元素的基数估算****值

  1. 基数:集合中不同元素的数量。比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 的基数就是 3 。

  2. 估算值:算法给出的基数并不是精确的,而是一个带有 0.81% 标准错误(standard error)的近似值。

HyperLogLog 的优点是,**即使输入元素的数量或者体积非常非常大,计算基数所需的空间总是固定的、并且是很小的。**在 Redis 里面,每个 HyperLogLog 键只需要花费 12 KB 内存,就可以计算接近 2^64 个不同元素的基数。

这和计算基数时,元素越多耗费内存就越多的集合形成 鲜明对比。但是,因为 HyperLogLog 只会根据输入元素来计算基数,而不会储存输入元素本身,所以HyperLogLog 不能像集合那样,返回输入的各个元素。

PFADD命令

**语法:**PFADD key element [element …]

**功能:**将任意数量的元素添加到指定的 HyperLogLog 里面。作为这个命令的副作用, HyperLogLog 内部可能会被更新, 以便反映一个不同的唯一元素估计数量(也即是集合的基数)。

PFCOUNT命令

**语法:**PFCOUNT key [key …]

**功能:**当命令作用于单个键时, 返回储存在给定键的 HyperLogLog 的近似基数, 如果键不存在, 那么返回 0 。当命令作用于多个键时, 返回所有给定 HyperLogLog 的并集的近似基数, 这个近似基数是通过将所有给定 HyperLogLog 合并至一个临时 HyperLogLog 来计算得出的。

代码示例如下:

  127.0.0.1:6379> pfadd dbs "redis" "mongodb" "mysql" "oracle"  (integer) 1  127.0.0.1:6379> pfcount dbs  (integer) 4  127.0.0.1:6379> pfadd dbs "redis"  (integer) 0  127.0.0.1:6379> pfcount dbs  (integer) 4  127.0.0.1:6379> pfadd "rabbitmq"  (integer) 1  127.0.0.1:6379> pfadd  dbs "rabbitmq"  (integer) 1  127.0.0.1:6379> pfcount dbs  (integer) 5

PFMERGE命令

**语法:**PFMERGE destkey sourcekey [sourcekey …]

**功能:**将多个 HyperLogLog **合并(merge)**为一个 HyperLogLog , 合并后的 HyperLogLog 的基数接近于所有输入 HyperLogLog 的可见集合(observed set)的并集。

合并得出的 HyperLogLog 会被储存在 destkey 键里面, 如果该键并不存在, 那么命令在执行之前, 会先为该键创建一个空的 HyperLogLog 。

代码示例如下:

  127.0.0.1:6379> pfadd language "Java" "C++" "Python"   (integer) 1  127.0.0.1:6379> pfcount language  (integer) 3  127.0.0.1:6379> pfmerge dbs language   OK  127.0.0.1:6379> pfcount dbs  (integer) 8

Geo

GEO,Geographic,地理信息的缩写。该类型,就是元素的2维坐标,在地图上就是经纬度。redis基于该类型,提供了经纬度设置,查询,范围查询,距离查询,经纬度Hash等常见操作。

通过 help @geo 可以看到全部的操作支持,当然也可以通过修改geo看别的类型的命令,类似help @list。

   GEOADD,添加成员的经纬度信息   GEODIST,计算成员间距离   GEORADIUS 基于经纬度坐标的范围查询   GEORADIUSBYMEMBER 基于成员位置范围查询   GEOPOS,获取成员经纬度   GEOHASH 计算经纬度Hash

GEOADD命令

**语法:**GEOADD key longitude latitude member [longitude latitude member …]

**功能:**将给定的空间元素(纬度、经度、名字)添加到指定的键里面。这些数据会以有序集合的形式被储存在键里面, 从而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 这样的命令可以在之后通过位置查询取得这些元素。

GEOADD 命令以标准的 x,y 格式接受参数, 所以用户必须先输入经度, 然后再输入纬度。GEOADD 能够记录的坐标是有限的:非常接近两极的区域是无法被索引的。

精确的坐标限制由 EPSG:900913 / EPSG:3785 / OSGEO:41001 等坐标系统定义, 具体如下:有效的经度介于 -180 度至 180 度之间。有效的纬度介于 -85.05112878 度至 85.05112878 度之间。

  redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"  (integer) 2  redis> GEODIST Sicily Palermo Catania  "166274.15156960039"  redis> GEORADIUS Sicily 15 37 100 km  1) "Catania"  redis> GEORADIUS Sicily 15 37 200 km  1) "Palermo"  2) "Catania"

位图Bit

位图不是一个真实的数据类型,而是定义在字符串类型上的面向位的操作的集合。由于字符串类型是二进制安全的二进制大对象,并且最大长度是 512MB,适合于设置 2^32个不同的位。

位操作分为两组:常量时间单个位的操作,像设置一个位为 1 或者 0,或者获取该位的值。对一组位的操作,例如计算指定范围位的置位数量。

位图操作是用来操作比特位的,其优点是节省内存空间。为什么可以节省内存空间呢?

假如我们需要存储100万个用户的登录状态,使用位图的话最少只需要100万个比特位(比特位1表示登录,比特位0表示未登录)就可以存储了,而如果以字符串的形式存储,比如说以userId为key,是否登录(字符串“1”表示登录,字符串“0”表示未登录)为value进行存储的话,就需要存储100万个字符串了,相比之下使用位图存储占用的空间要小得多,这就是位图存储的优势。

SETBIT命令

**语法:**SETBIT key offset value

**功能:**对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。位的设置或清除取决于 value 参数,可以是 0 也可以是 1 。当 key 不存在时,自动生成一个新的字符串值。字符串会进行伸展(grown)以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。offset 参数必须大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之内)。

GETBIT命令

**语法:**GETBIT key offset

**功能:**对 key 所储存的字符串值,获取指定偏移量上的位(bit)。当 offset 比字符串值的长度大,或者 key 不存在时,返回 0 。

代码示例如下:

  127.0.0.1:6379> setbit mybit 100 1  (integer) 0  127.0.0.1:6379> getbit mybit 100  (integer) 1  127.0.0.1:6379> getbit mybit 10    (integer) 0  # bit 默认被初始化为 0

絮叨叨

你知道的越多,你不知道的也越多。

建议:命令行记住常用的即可,多练习几次就记住了,没必要去全部记住命令行,使用到的时候去查询即可

觉得不错的可以给来个关注,也欢迎可爱帅气的你推荐给你的朋友,转发和点赞是可以给船长多打打气~~