欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Redis我想入门——数据类型

程序员文章站 2022-09-07 13:02:31
每一个数据库都有自己的数据类型。同样子redis为我们提供了五种类型的数据——字符串、哈希、列表、集合、有序集合。我们知道关系型数据的数据存放型式是一张二维表。用行和列来表示数据之间的关系。redis是一个nosql数据库当然不可能在用什么二维表的形式来表示了。他所有的数据都是以key=value的 ......

每一个数据库都有自己的数据类型。同样子redis为我们提供了五种类型的数据——字符串、哈希、列表、集合、有序集合。我们知道关系型数据的数据存放型式是一张二维表。用行和列来表示数据之间的关系。redis是一个nosql数据库当然不可能在用什么二维表的形式来表示了。他所有的数据都是以key=value的形式来存放的。每一种数据类型都有数据结构和内部编码的概念。数据结构你们可以理解他们的存放时的结构。而内部编码就是数据结构的具体实现。但是一种数据结构可以对应多种内部编码的实现。接下来笔者就要去看看每一种数据类型相关的操作命令和数据结构,内部编码。

1.字符串类型的数据

字符串类型,笔者认为比较简单的类型。

数据结果:一串值

内部编码:一共有三种:int  embstr  raw

例子:

127.0.0.1:6379> set k1 1002
ok
127.0.0.1:6379> set k2 "i am aomi"
ok
127.0.0.1:6379> set k3 "i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi i am aomi "
ok
127.0.0.1:6379> object encoding k3
"raw"
127.0.0.1:6379> object encoding k2
"embstr"
127.0.0.1:6379> object encoding k1
"int"
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> get k2
"i am aomi"

笔者向redis时面存放了三个值。他这三个值对应的键为:k1、k2、k3。

  •  set:用于增加字串符的值。

语法:

set key value [ex seconds] [px milliseconds] [nx|xx]

  key:键名

  value:键对应的值

  ex:表示有效的时间。0表示永存,大于0表示在几秒内有效。

  px:表示有效时间。只是单位是毫秒。

  nx:表示不存在的时候才可以增加成功。

  xx:表示只有存在的时候才可以增加成功。

  • object encoing:用于查看当前键的内部编码。

语法:

object subcommand [arguments [arguments]]

  subcommand:这个有三个值 refcount(用于查看对象引用次数)、encoding(查看内部编码)、idletime(存在的时间)。

  • keys:用于查看当前数据库有多少键。

语法:

keys pattern

  pattern:*表示全部。*aaa表示查找以aaa结尾的。[a,b]123表示查看以a或是b,并且后面是123。相信不用笔者都说明了。

  •  get:用于获取指定键的值。

语法:

get key

  key:键的名称

学下语法之后,我们可以从上面看到字串符有三种内部编码了吧。如果你输入是一个数字的话,一般都是int。如果输入不是一个数字的话,是embstr。如果输入的字符串长度大于512的话。就会变成raw

笔者来一个设置有效时间的数据吧。

127.0.0.1:6379> set k5 v5 ex 10
ok
127.0.0.1:6379> ttl k5
(integer) 4
127.0.0.1:6379> ttl k5
(integer) -2

上面ttl用于查看当前键是的有效时间。

上面的都是一个一个增加有没有一次增加多个呢?当然是有的。

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
ok
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> 

事实上学习redis的命令是一件很简单的事情。笔者是一边看命令手册一边写命令的。所以大家也可以这样子。自己写过一遍基本上都不会忘记。如果有不懂的话,查看一下手册就可以了。至于手册网络上很多。建义可以去官网看看。

2.哈希类型的数据

这个数据类型算是这五种类型中最为复杂的。存放形式不用说key=value。只是这个value里面就不一样子。是一个field=value形式的数据值。

数据结构:key: value(field=value)。不知道笔者这样子表示你们看得懂多。

内部编码:一共有俩种。一种是ziplist,二种是hashtable。

列子:

127.0.0.1:6379> hset user:1 name aomi
(integer) 1
127.0.0.1:6379> hset user:1 age 32
(integer) 1
127.0.0.1:6379> hset user:1 sex 1
(integer) 1
127.0.0.1:6379> hset user:2 name nono
(integer) 1
127.0.0.1:6379> hset user:2 age 24
(integer) 1
127.0.0.1:6379> hset user:2 sex 1
(integer) 1
127.0.0.1:6379> hset user:2 desc "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
(integer) 1
127.0.0.1:6379> hget user:1 name
"aomi"
127.0.0.1:6379> hkeys user:1
1) "name"
2) "age"
3) "sex"
127.0.0.1:6379> hvals user:1
1) "aomi"
2) "32"
3) "1"
127.0.0.1:6379> hgetall user:1
1) "name"
2) "aomi"
3) "age"
4) "32"
5) "sex"
6) "1"
127.0.0.1:6379> object encoding user:1
"ziplist"
127.0.0.1:6379> object encoding user:2
"hashtable"
127.0.0.1:6379> 

笔者先向redis数据库增加俩个数据。分别为:user:1 和user:2。同时写了三个获得哈希信息的命令。分别为:hget 、hkeys、hvals、hgetall。接着显示出这个俩数据的内部编码。

  • hset:用于增加哈希

语法:

hset key field value

从语法我就可以看出数据结构大概是一个什么样子。这个java的类有一个像。key为类名,field为成员,value:为成员的值。事实上你可以看到笔者上面的例子就有一点像存放user类的实例一样子。

  key:键名称

  field:成员名

  value:成员的值

  •  hget:用于获得一个成员的值。

语法:

hget key field
  • hkeys:用于获得当前键下的所有成员

语法:

hkeys key
  • hvals:用于获得当前键下的所有值

语法:

hvals key 
  • hgetall:用于获得当前键下的所有成员和对应的所有值。

语法:

hgetall key

上面例子我们可以看到俩种内部编码。user:2的desc却很长。一定大于64个字节。什么意思。如果成员值的长度大于64个字节的话,内部编码都会转为hashtable。当然还有如果你的成员个数大于512的话,内部编码也会转为hashtable有话。

笔者想知如果user:2的desc成员删除。内部编号会不会为ziplist。同时大家看一下什么删除。

127.0.0.1:6379> hdel user:2 desc
(integer) 1
127.0.0.1:6379> object encoding user:2
"hashtable"
127.0.0.1:6379> hkeys user:2
1) "name"
2) "sex"
3) "age"
127.0.0.1:6379> hdel user:2
(error) err wrong number of arguments for 'hdel' command

最后一步出错了。笔者就想试一下删除整个键。你们看到出错了。要删除的话。还要用下的。

127.0.0.1:6379> del user:2
(integer) 1
127.0.0.1:6379> exists user:2
(integer) 0

这里有一个观念。hdel删除的是对应哈希里面的成员的。而要删除key是属于数据层的。

3.列表类型的数据

redis的列表有一点奇怪。在笔者第一接触的时候。被搞得有一点晕。你们可以这样子理解。现在有一个列表。他只有俩个地方可以进入。一个是左边的头,一个是右边的头。出去也只这俩个头。

数据结果:一个列表

内部编码:有三种:一种是ziplist,一个是linkedlist。最后一种是quicklist。

127.0.0.1:6379> lpush list1 a b c d e f
(integer) 6
127.0.0.1:6379> lrange list1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> 
  • lpush:将一个或多个值 从左边插入

语法:

lpush key value [value ...]

lpush就是从左边口进入。所以就 a进完 ,b在进,b进完了c进。以此类推。这个时候我们要以看到列表如下

 左边进入--> f-e-d-c-b-a
  • lrange:获得指定区间内的元素。

语法:

lrange key start stop

start表示从哪里开始,stop表示从哪里结果,如果stop=-1表示最后一个,-2的话表示倒数第二个,-3的话表示倒数第三个,依此类推。

现在我们就可以明白为什么上面是f-e-d-c-b-a。我们在来看看从右边插入会是什么样子。

127.0.0.1:6379> rpush list2 1 2 3 4 5 6 7
(integer) 7
127.0.0.1:6379> lrange list2 0 -1
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
127.0.0.1:6379> 

如果我们从右边的口进入的话,那么在列表里就是如下

1-2-3-4-5-6-7 <--右边进入

所以lrange显示就是1,2,3,4,5,6,7。

列表的内部是有序的并且可以重复。笔者插入一个相同信的看看

127.0.0.1:6379> lpush list3 a a b c d
(integer) 5
127.0.0.1:6379> lrange list3 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
5) "a"

上面都是入,没有出。现在笔者要做一出的操作。如下

127.0.0.1:6379> lrange list1 0 -1
1) "f"
2) "e"
3) "d"
4) "c"
5) "b"
6) "a"
127.0.0.1:6379> lpop list1 
"f"
127.0.0.1:6379> lrange list1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379> 

我们发现用lpop的命令之后。相对应的值也会被取出。如上面的“f”就是被取出来了。笔者最后看一下列表只有:e-d-c-b-a了。原来应该是f-e-d-c-b-a。说明lpop是左边出的。同样子rpop是从右边出的。

127.0.0.1:6379> rpop list1
"a"
127.0.0.1:6379> lrange list1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
127.0.0.1:6379> 

接下让我们看一下他的内部编码。

127.0.0.1:6379> lpush list4 a "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" 
(integer) 4
127.0.0.1:6379> object encoding list4
"quicklist"
127.0.0.1:6379> lrange list4 0 -1
1) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"
2) "a"
3) "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
4) "a"
127.0.0.1:6379> 

笔者用了很长的值,内部编码还是quicklist。quicklist是3.2版本之后出现的。他接结ziplist和linkedlist俩都优点而生的。相关的你们可以去查看官网。

redis提供列表的功能事实上是可以当队列和栈来用的。先进先出。那么你就要用到lpush和rpop 或是rpush 和lpop。从左边进,从右边出。后进先出就是栈了。那么就lpush和lpop或是rpush和rpop了。

4.集合类型的数据

他是一个无序的,同时他不能有重复。

数据结果:你可以理解为一个箱子。东西随便放。但不能重复。

内部编码:他有俩种:一是intset,一种hashtable.

例子

127.0.0.1:6379> sadd set1 a a b c d e f 
(integer) 6
127.0.0.1:6379> smembers set1
1) "a"
2) "d"
3) "c"
4) "f"
5) "b"
6) "e"
127.0.0.1:6379> object encoding set1
"hashtable"
127.0.0.1:6379> sadd set2 a b "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
(integer) 3
127.0.0.1:6379> object encoding set2
"hashtable"
127.0.0.1:6379> object encoding set1
"hashtable"
127.0.0.1:6379> sadd set3 1 2 3 4 5 6 7 8 9
(integer) 9
127.0.0.1:6379> smembers set3
1) "1"
2) "2"
3) "3"
4) "4"
5) "5"
6) "6"
7) "7"
8) "8"
9) "9"
127.0.0.1:6379> object encoding set3
"intset"
127.0.0.1:6379> 

笔者增加了三个集合类型的数据。set1一般没有什么特别的。set2里面有一个值长度很长。set3都是整数。

  • sadd:用于增加一个集合。

语法:

sadd key member [member ...]

笔者就不说明了。member就是相对应的成员值。

  •  smembers用于显示里面的成员

语法:

smembers key

笔者分别显示出三个的内部编码。发现只有当集合里面全部是整数的时候,内部编码是intset。其他都是hashtable。

5.有序集合类型的数据

你们可以这样子里面集合类型是无序的。为了让他有序,把集合类型的数据结构里面加入值来表示他的顺序。

数据结构:同样子的箱子。只是在放入这个箱子的东西。必须贴上相关的数字标签。

内部编码:有俩种:一种是ziplist,一种是skiplist。

127.0.0.1:6379> zadd stu 80 math 60 english 70 chinese
(integer) 3
127.0.0.1:6379> zcard stu
(integer) 3
127.0.0.1:6379> zrange stu 0 -1
1) "english"
2) "chinese"
3) "math"
127.0.0.1:6379> zrange stu 0 -1 withscores
1) "english"
2) "60"
3) "chinese"
4) "70"
5) "math"
6) "80"
127.0.0.1:6379> zadd stu2 80 "aoooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo"
(integer) 1
127.0.0.1:6379> object encoding stu
"ziplist"
127.0.0.1:6379> object encoding stu2
"skiplist"
127.0.0.1:6379> 

有没有感觉就是一个报表。比如学习的成绩之类的数据体现。80分 数学。60分 语文。那么前面是不是一定要是一个数字呢?笔者做了一下实验。

127.0.0.1:6379> zadd stu3 "godd" "aomi" 80 en
(error) err value is not a valid float 

看到了果然要一个数字。同时我们可以到他的俩种内部编码。