Redis原来不止五种类型啊(含常用命令)
来源:左耳君(ID:qaqzuoer)
作者: 湿兄
Redis五种基本的数据类型有string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合),还有一些高级数据结构HyperLogLog、Geo、Bit
本系列采用的redis版本是redis-4.0.10,基于Linux系统。关于Redis命令只会例举最常用的,不会全部例举,重点是学会看文档自己应用,在实际应用中如果应用到更多命令可以到http://doc.redisfans.com/或者http://redisdoc.com/string/set.html查阅使用
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
功能:
将值 value 关联到 key ,并将 key 的生存时间设为 seconds (以秒为单位)。如果 key 已经存在, SETEX 命令将覆写旧值。
不同之处是, 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是原子的,所有键会同时设置成功或者失败。
HashRedis 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可以接受多个元素作为输入,并给出输入元素的基数估算值:
- 基数:集合中不同元素的数量。比如 {‘apple’, ‘banana’, ‘cherry’, ‘banana’, ‘apple’} 的基数就是 3 。
- 估算值:算法给出的基数并不是精确的,而是一个带有 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