Redis从入门到精通(1):数据类型 - Go语言中文社区

Redis从入门到精通(1):数据类型


Redis简介

Redis由C语言编写,Redis是一个开源的、高性能的、基于内存的轻量级键值数据库。
Redis支持丰富的数据类型,例如string,list,set,sorted set,hash等。
Redis的功能丰富,内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能等等,可用作数据库,高速缓存和消息队列代理。
Redis数据库中的所有数据都存储在内存中,因此性能非常强大。
类似这种简介的我们就不再细说,具体发展史等可以自行百度。

Redis的数据类型

Redis强大的一个原因就是提供了丰富的数据类型,接下来我们一个个进行学习。

Redis的键管理

Redis的键尽量不要超过1024字节,因为如果过大,不仅消耗内存,而且会降低查找的效率。
键的命名最好是用"对象类型:对象id:对象属性"来命名一个键,例如user:1:friends来存储id为1的用户的好友列表
对于多个单词则使用.来分隔。

接下来我们来看几个常用的键命令

KEYS  pattern:获取符合规则的键名列表,pattern支持glob风格通配符形式。
例如:KEYS *,获得Redis中所有的键
符号含义
匹配一个字符
*匹配所有字符
[ ]匹配括号间的任一字符,例如[a-z]

KEYS命令需要遍历Redis中的所有键,当键的数量较多时会严重影响性能,不建议使用。

EXISTS  key:判断一个键是否存在,存在则返回整数类型1,否则返回0.
DEL key1 key2...:可以删除一个或多个键,返回值是删除的键的个数。
TYPE key:获取键值的数据类型

字符串类型(String)

字符串类型是Redis最基本的数据类型,他能够存储任何形式的字符串,你可以用其存储用户的信息、json化的对象甚至是一张图片。
字符串类型是其他四种类型的基础,其他数据类型从某种角度来说只是组织字符串的形式不同。
一个字符串类型的键允许存储的最大数据容量是512MB。

赋值命令:SET key  value,如果 key 已经持有其他值, SET 就覆写旧值, 无视类型
取值命令:GET key,当键不存在时会返回空。

在这里插入图片描述

Redis的所有命令都是原子操作。原子操作即不可拆分的意思,不会在执行的过程中被其他命令插入打断。

(1)INCR key:让当前的键值递增,并返回递增后的值。
      如果键 key 不存在, 那么它的值会先被初始化为 0 , 然后再执行 INCR 命令。
      如果键 key 储存的值不是整数, 那么 INCR 命令将提示错误。
      
(2)INCRBY key num:增加指定的整数,该命令与incr基本一样,只不过可以通过num参数指定每次增加的数值。

(3)DECR:让当前的键值递减,并返回递减后的值。

(4)DECRBY key num:该命令与DECR:基本一样,只不过可以通过num参数指定每次递减的数值。

(5)INCRBYFLOAT key num:增加指定的浮点数,该命令与数:INCRBY 基本一样,只不过可以通过num参数指定双精度浮点数。

(6)APPEND key value:向尾部追加值,APPEND的作用是向键值的末尾追加value,如果键不存在,则将键值设置为value。返回值是追加后字符串的总长度。

(7)STRLEN key:获取字符串长度,存在则返回键值的长度,如果不存在则返回0。

(8)MSET K1 V1 K2 V2...:同时设置多个键值

(9)MGET K1 K2...:同时获取多个键值

在这里插入图片描述

位图操作

一个字节由八个二进制位组成,redis为我们提供了一些命令可以直接对二进制位进行操作。
我们直接通过一个直观的例子来讲解

我们首先执行 set foo bar 
bar对应的ascii码为98 97  114,那么foo键相应的二进制位图为
    b         a          r
01100010  01100001   01110010

(1)GETBIT key  offset:该命令可以获得一个字符串类型键指定位置的二进制位的值(0或1,索引从0开始)
例如:GETBIT foo  6  结果为1
如果获取的索引超过了键值的二进制实际长度,则返回0。

(2)SETBIT key offset value:可以设置字符串类型键指定位置的二进制位值。返回值是该位置的旧值。
如果要设置的位置超过了键值的二进制位长度,该命令会自动将中间的二进制位设置为0.
同理设置一个不存在的键的指定二进制位时会自动将其前面的位设置为0.

(3)BITCOUNT key [start] [end]:可以获得字符串类型键中二进制位为1的个数。可以通过参数来限制范围,索引从0开始。

(4)BITOP operation destkey key1 key2...:可以对多个字符串类型键进行位运算,并将结果存储在destkey指定的键中。
operation支持的操作有OR AND XOR NOT

BITPOS key 0|1 [start] [end]:获得指定键的第一个位值是0或1的位置,索引从0开始。
start和end参数可以指定查询的起始字节和结束字节,注意这里的单位是字节。
例如: BITPOS foo 1 1 2  即查询ar字节之间第一个二进制位为1的偏移量,返回值为9,返回结果的偏移量是从头开始的,与起始字节无关。

有一个有趣的现象,如果不设置结束字节并且键值的所有二进制位都是1,则当要查询二进制位为0的偏移量时,返回结果会是键值长度的下一个字节的偏移量。这是因为redis会认为键值长度后的所有二进制位都为0.

String的实际应用

1)文章访问量统计
博客很常用的一个功能就是统计文章的访问量,我们可以为每篇文章使用一个post:文章id:page.view的键来记录文章的访问量,每次访问时用incr来递增。

散列类型(Hash)

hash是一个String类型的field和value的映射表。散列类型适合存储对象。
一个散列类型键可以包含2^32-1个字段。

(1)HSET key  field value:给字段赋值。 例如 HSET car  price 500

(2)HGET key field:获取字段值。 例如 HGET car price

当HSET执行的是插入操作时(即之前字段不存在)会返回1,当执行的是更新操作时会返回0。当键不存在时,还会自动建立。

(3)HMSET key field1 value1 field2 value2...:同时设置多个字段 例如 HMSET car  name "bmw" price 5000

(4)HMGET key field1 field2:获取多个字段的值

(5)HGETALL key:获取键中的所有字段和字段值

(6)HEXISTS key field:判断字段是否存在。存在返回1,不存在返回0,键不存在也会返回0.

(7)HSETNX key field value:HSETNX命令与HSET类似,区别在于如果字段已经存在,HSETNX命令将不再执行任何操作。

(8)HINCRBY key field  num:使字段值增加指定的整数。散列没有HINCR指令。
例如:HINCRBY person score 60.person键不存在,HINCRBY命令会自动建立并默认score字段在执行命令之前的值为0,返回值为增值后的字段值。

(9)HDEL key field1 field2...:删除一个或多个字段,返回值是删除的字段个数

(10)HKEYS key:只获取字段名

(11)HVALS key:只获取字段值

(12)HLEN   key:获取字段数量

在这里插入图片描述
在这里插入图片描述
Hash的实际应用

(1)存储博客文章。
可以将文章的标题,作者,标签分别放入不同的字段中。

列表类型(List)

列表类型可以存储一个有序的字符串列表,常用的操作是向列表两端添加元素。
列表类型内部是使用双向链表实现的,所以向列表两端添加元素的时间复杂度为O(1).使用链表的代价是通过索引访问元素比较慢。
借助列表类型,Redis还可以作为队列使用。
一个列表类型键最多可以容纳2^32-1个元素。

(1)LPUSH key value1,value2...:向列表左边增加元素,返回值为增加元素后列表的长度

(2)RPUSH key value1,value2..:向列表右边增加元素,返回值为增加元素后列表的长度

(3)LPOP key:从列表左边弹出一个元素。这个命令执行两部操作,第一步是将列表左边的元素从列表中移除,第二步返回被移除的元素值。

(4)RPOP key:从列表右边弹出一个元素。
通过上面四个命令可以使用列表类型来模拟栈和队列的操作。

(5)LLEN key:获取列表中元素的个数,当键不存在时返回0.

(6)LRANGE key  start end:获取列表的某一片段。LRANGE命令将返回索引从start到end之间的所有元素(包含两端的元素)。Redis的列表起始索引为0.
LRANGE命令不会像LPOP删除元素。
LRANGE同时也支持负索引,表示从右边开始计算序数,如"-1"表示最右边第一个元素。显然:LRANGE numbers 0 -1能够获取列表中的所有元素。
如果start>end,则返回空列表。
如果end大于实际的索引范围,则会返回到列表最右边的元素。

(7)LREM key count value:LREM命令会删除列表中前count个值为value的元素,返回值时实际删除的元素个数。
根据count值的不同,LREM命令的执行方式会略有差异。
	(1)当count>0时,LREM命令会从列表左边开始删除前count个值为value的元素。
	(2)当count<0时,LREM命令会从列表右边开始删除前|count|个值为value的元素。
	(3)当count=0时,会删除所有值为value的元素。

(8)LINDEX key index:LINDEX用来返回指定索引的元素,索引从0开始。如果index时负数则表示从右边开始的索引,最右边元素的索引为-1.

(9)LSET key index value:将索引为index的元素赋值为value。

(10)LTRIM key start end:LTRIM命令可以删除指定索引范围之外的所有元素
LTRIM命令常和LPUSH一起使用来限制列表元素数量,比如我们只希望保留最新的100条日志,则先调用LPUSH放入最新日志,再LTRIM log 0 99来限制数量。

(11)LINSERT key BEFORE|AFTER  pivot value: LINSERT命令首先会在列表中从左到右查找值为pivot的元素,然后根据第二个参数BEFORE|AFTER来决定将value插入到该元素的前面或者是后面。
LINSERT返回值是插入元素后列表的元素个数。

(12)RPOPLPUSH  source destination :将元素从一个列表转到另一个列表。从名字来看,RPOPLPUSH先执行RPOP命令再执行LPUSH命令。
RPOPLPUSH命令会先从source列表类型键的右边弹出一个元素,然后将其加入到destination列表类型键的左边,并返回这个元素的值。

当把列表类型作为队列使用时,RPOPLPUSH命令可以很直观的在多个队列中传递数据。
当source和destination相同时,RPOPLPUSH命令会不断地将队尾的元素移到队首,利用可以特性我们可以实现一个网站监控系统,使用队列放入我们需要监控的网站地址,然后不断的循环测试网址可用性。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

集合类型(Set)

集合中的每个元素都是不同的,且没有顺序,唯一且无需。一个集合类型的键可以存储2^32-1个字符串。
集合类型的常用操作是向集合中加入或删除元素,判断某个元素是否存在等。
集合类型在Redis内部是使用值为空的hash表来实现的。所以这些操作的时间复杂度都为O(1).
多个集合类型键之间还可以进行并集、交集和差集运算。

(1)SADD key  member1,member2...:向集合中添加一个或多个元素。如果键不存在则自动创建。返回值是成功加入的元素数量。

(2)SREM key  member1,member2...:从集合中删除一个或多个元素,并返回删除成功的个数。

(3)SMEMBERS key:获取集合中的所有元素。

(4)SISMEMBER key member:判断一个元素是否在集合中。是一个时间复杂度为O(1)的操作。当值存在时返回1,当值或键不存在时返回0。

集合间运算
(5)SDIFF key1,key2...:该命令用来对多个集合执行差集运算。集合A和集合B的差集表示为A-B,代表所有属于A且不属于B的元素构成的集合。

例如:
        SADD seta 1 2 3
        SADD setb 2 3 4
        SDIFF seta setb  结果为1
        SDIFF setb seta  结果为4

当传入多个键时,先计算前两个的差集,然后将结果与后面的键进行计算。


(6)SINTER key1,key2...:该命令用来对多个集合执行交集运算。集合A与集合B的交集表示为A∩B,代表所有属于A又属于B的元素构成的集合。

(7)SUNION key1,key2...:用来对多个集合执行并集运算。集合A和集合B的并集表示为A∪B,代表所有属于A或属于B的元素构成的集合。

(8)SCARD key:获取集合中的元素个数。

(9)SDIFFSTORE、SINTERSTORE、SUNIONSTORE  destination key1 key2..:这三个命令和上面的一样,唯一不同的就是不会直接返回运算结果,而是将结果存储在destination键中。

(10)SRANDMEMBER key [count]: SRANDMEMBER命令用来随机从集合中获取一个元素。还可以传递count参数来一次随机获取多个元素。
根据count的正负不同,表现也不同
	(1):当count为整数时,SRANDMEMBER会随机从集合中获取count个不重复的元素,如果count大于集合长度,则返回集合所有元素。
	(2):当count为负数时,SRANDMEMBER会随机从集合中获取|count|个元素,这些元素可能会相同。

(11)SPOP key:从集合中弹出一个元素。由于集合类型的元素是无序的,所以该命令会随机选取一个元素弹出。

在这里插入图片描述

有序集合类型(Sorted Set)

在集合类型的基础上有序集合类型为每个元素都关联了一个分数,这使得我们不仅可以完成插入、删除等集合类型的操作,还能够获得分数最高或最低的前n个元素、获取指定分数范围内的元素。
虽然集合中的每个元素都是不同的,但是它们的分数可以相同。

有序集合和列表的共同点:

		(1).有序  
		(2).都可以获得某个范围内的元素

不同点:

		(1).列表是通过链表实现的,获取靠近两端的数据速度极快,当数据增多后,访问中间数据的速度会变慢,所以更适合做“新鲜事”等功能。
        (2).有序集合类型是通过散列表和跳跃表实现的,即使读取中间的数据也会很快(时间复杂度为O(logn))
        (3).有序集合比列表更耗费内存
        (4).列表中不能简单的调整某个元素的位置,有序集合可以(通过更改这个元素的分数)**
(1)ZADD key score1 member1  score2 member2...:向有序集合中添加一个或多个元素和该元素的分数。
如果该元素已经存在则会用新的分数替换原有的分数。
返回新加入到集合中的元素个数(不包含之前已经存在的元素)。
分数还支持双精度浮点数。

(2)ZSCORE key  member:获取元素的分数

(3)ZRANGE key start end [WITHSCORES]:按照元素分数从小到大的顺序返回索引从start到end之间的所有元素(包含两端的元素)。
索引从0开始,负数代表从右向前查找(-1代表最后一个元素)。
如果需要同时获取分数的话可以在ZRANGE的尾部加上WITHSCORES参数。如果两个元素的分数相同,则会按照字典顺序排序。
ZREVRANGE和ZRANGE一样,唯一不同是按照元素分数从大到小的顺序给出结果。

(4) ZRANGEBYSCORE key min max [WITHSCORES][LIMIT offset count]:按照元素分数从小到大的顺序返回分数在min和max之间的元素(包含min和max)。
如果希望范围不包含端点值,则可以在分数上加上"(".例如:ZRANGEBYSCORE  num  80 (100 ,返回80到100分的数据,包含80,不包含100.
min和max支持无穷大,-inf和+inf表示负无穷和正无穷。
WITHSCORES参数和ZRANGE一样。
LIMIT offset count 参数是在获取元素列表的基础上向后偏移offset个元素,然后获取前count个元素。
例如:ZRANGEBYSCORE score 60 +inf LIMIT 1 3  获取分数高于60分的从第二个人开始的三个人。

(5) ZREVRANGEBYSCORE命令是按照元素分数从大到小的顺序给出结果的,而且它的min和max参数的顺序和ZRANGEBYSCORE是相反的。
例如:ZREVRANGEBYSCORE score 100 0 limit 0 3  获取分数低于100的前三个人。

(6) ZINCRBY key number member:给某个元素member增加number分。返回值是更改后的分数。number可以是负数表示减分。
如果指定的元素不存在,Redis在执行命令前会先建立它并将它的分数赋值为0再执行操作。

(7) ZCARD key:获取集合中元素的数量

(8) ZCOUNT key min max:获得指定分数范围内的元素个数

(9) ZREM key member1 member2...:删除一个或多个元素。返回值是成功删除的元素数量。

(10) ZREMRANGEBYRANK key  start end:按照元素分数从小到大的顺序(即索引0表示最小的值)删除在指定排名范围内的所有元素,并返回删除的元素数量。
例子:	 ZADD test 1 a  2 b 3 c 4 d 5e
         ZREMRANGEBYRANK test 0 2  //值为 d e


(11) ZREMRANGEBYSCORE  key min max:删除指定分数范围内的所有元素。返回值是删除的元素数量。

(12) ZRANK key member:该命令会按照元素分数从小到大的顺序获得指定元素的排名。(从0开始,分数最小的排名为0)
ZREVRANK和上面的一样,区别是分数最大的排名为0.

(13) ZINTERSTORE destination numkeys key [key1..]  [WEIGHTS weight1 weight2...]  [AGGREGATE  SUM|MIN|MAX]
该命令用来计算多个有序集合的交集并将结果存储在destination键中(同样以有序集合类型存储),返回值为destination键中的元素个数。
destination键中元素的分数是由AGGREGATE参数决定的。
	(1)当AGGREGATE是SUM时(默认值),destination键中元素的分数时每个参与计算的集合中该元素分数的和。
	例如:
		ZADD  sortedSet1  1 a  2b
		ZADD  sortedSet2  10 a  20 b
		ZINTERSTORE sortedResult 2  sortedSet1  sortedSet2  //最后sortedResult 集合中的a为11  b为22

	(2)当AGGREGATE是MIN时,destination键中元素的分数时每个参与计算的集合中该元素分数的最小值。
	例如:ZINTERSTORE sortedResult 2  sortedSet1  sortedSet2 AGGREGATE MIN
	(3)当AGGREGATE是MAX时,destination键中元素的分数时每个参与计算的集合中该元素分数的最大值。

(14) ZINTERSTORE 还可以通过WEIGHTS参数设置每个集合的权重,每个集合在参与计算时元素的元素会被乘上该集合的权重。
例如:ZINTERSCORE sortedResult 2  sortedSet1  sortedSet2 WEIGHTS 1 0.1  //最后的结果时 a 2  b 4

(15) ZUNIONSTORE的作用是计算集合间的并集,和上面的用法一模一样。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

HyperLogLog类型

在日常的各种数据处理场景中,“唯一计数”是一项常见的任务。
虽然我们可以使用集合来进行唯一计数,但是当数据量增大到上千万时,就需要考虑内存消耗和性能下降问题。
如果我们不需要获取数据集的内容,而只是想得到不同值的个数,那么可以使用HyperLogLog数据类型来优化。

(1) PFADD key  member1 member2....:向key中添加一个或多个元素
(2) PFCOUNT key1 key2...:获取key中的元素数目

例子:
	PFADD runoobkey "redis"
	PFADD runoobkey "mongodb"
	PFCOUNT runoobkey  //值为2


如果我们想要展示每家饭店在一个星期中的访客数,然后按照每周流行来进行排名怎么办?
我们可以每家酒店每天生成一个HyperLogLog,然后用PFMERGE命令将每周七天的数据合并成一个。

(3) PFMERGE  destkey key1 key2...:将多个HyperLogLog合并到destkey键中。合并后的destkey里面的数量是通过对所有 给定 HyperLogLog 进行并集计算得出的。

在这里插入图片描述

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/c99463904/article/details/87730765
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢