【redis】02string类型和hash类型
Redis的数据类型
Redis主要分为五个数据类型,一个是string,最简单的一个数据类型,hash,list,
还有set集合,还有zset有序集合,这是咱们redis的五种基础类型,
接下来看一下咱们最简单的数据类型,string类型,string类型呢,是咱们redis最简单的数据类型,
一个key呢只对应一个数据类型,string类型是二进制安全的,
redis的string呢可以包含任何数据,比如咱们jpg图片,可以把他打散成一个二进制存进来吧,
或者是序列化的对象同样可以,咱们php怎么把对象序列化呢,是不是用一个函数啊,serialize
用这样一个函数可以把一个对象序列化,序列化之后就可以存入到咱们redis的string类型里面,
那么咱们string类应该怎么操作呢,string类型有个 Set
他是设置key对应的值为string类型的value,
如果大家学过memcached的话,对这个方法一定不模式,对某个键的某一个值,
例如:我们添加一个name=lijie的键值对儿,
这首先是什么进入客户端吧,用set方面对咱们的name设置一个值,焦作lijie,
redis 127.0.01:6379> set name lijie
OK
#./redis-cli 进入客户端,
发现redis没有启动,用redis-server命令启动服务
#./redis-server /usr/local/redis/etc/redis.conf 执行这个时候再来查看咱们的端口
# netstat -tupl | grep 6379 好发现启动了~
大家看到了吗,这个时候6379是不是有端口占用啊,是不是咱们的redis-server这个进程占用着,
说明他已经启动成功,这个时候咱们在进入客户端,进入客户端我们说过上一节课我也给大家讲过,
用咱们的redis-cli吧,这个时候就进入到了咱们的redis客户端,
大家看一下redis客户端呢,进入来以后比较奇怪,
redis 127.0.01:6379>
他首先是一个redis 然后呢,是本机的ip地址,然后冒号对应端口, 最后尖括号,
set name lijie 回车
OK
大家可以看到,这里提示一个OK,代表设置name键,值为lijie,设置成功,
好,那怎么来获取name呢,有set咱们是不是就应该有get啊,大家想也可以想到,
get name 回车
“lijie”
获取到的就是咱们刚才set的name的值吧,set就是对咱们的key,进行一个对应的value,
相对比较简单一些, 这是string类型的set方法,那我在设置name呢,
set name lampbrother
OK
我这个时候再
get name
"lampbrother"
值是不是会覆盖,对把,说明这个name是同一个name,
说明咱们在redis里面同一个键只允许有一个,
一个key对应一个value,Redis的string可以包含任何的数据类型,
我设置了一次name为lijie,然后我又设置了一次把name设置为lampbrother,
如果咱们不想让他覆盖怎么办,咱们用一个方法叫做,setnx
设置key对应的值为string类型的value,如果key已经存在,则返回0,
nx是not exist的意思,
他代表什么意思,如果不存在则插入,则设置吧,如果这个键已经存在呢,不更新吧,
咱们刚才是不是覆盖更新啦,
setnx name lijie
(integer) 0
大家可以看到这里返回一个整型0,并且呢,这个设置不成功,
咱们这个时候再来
get name
"lampbrother"
是不是还是lampbrother没有更改成lijie吧,
所以说咱们的sernx呢会判断咱们的name键是否存在,如果存在则返回一个0,并且,
不设置不更新,如果不存在呢,则设置一个新值,
setnx age 20
(integer) 1
大家可以看到我age键是不是没有设置过啊,这个时候呢,咱们setnx age就会返回为1
这个时候再,
get age
"20"
是不是20返回一个额20
setnx age 40
(integer) 0
是不是返回为0啊,因为我刚才设置过age啦,咱们再来get一下
get age
"20"
是不是还是20啊,没有更新吧,这就是咱们的setnx,
nx记住代表的是not exist什么意思呢,不存在,
还有一个是setex
设置key对应的值为string类型的value,并制定此键值对应的有效期,
这个ex是指定咱们这个键的有效期,
setex haircolor 10 red回车
OK
我们一直get haircolor
“red”然后一直get,终有一次出现以下结果:
(nil)
我设置haircolor的值为red并且占地in个他的有效期为10秒,
他在10秒以内我get haircolor的时候可以获取到值,获取到的就是我设置的这个值,
但是超过10秒以后我再get的时候,这个时候返回一个空,
在redis里面返回一个空就是nil,表示空,
因为我在设置过后的10秒钟这个键会消失,会失效,
然后用
setnx haircolor red
(integer) 1
说明这个键haircolor已经没有啦,这个时候我设置成功了,我nx是不是判断not exist啊,
对吧,说明这个值已经没有啦,
get haircolor
"red"
大家看是不是可以获取到这个值, 我以后不管怎么获取都会有这个值,
因为我没有设置他的有效期吧,没有设置他的有效期代表他永久有效,
咱们接下来看一下string还有什么类型的方法,
如何设置制定key值为value的子字符串呢,
比如,我们设置讲lijie的126邮箱替换为gmail邮箱,
比如说我现在get name结果为
"lijie@126.com"
好我现在要换成谁,要换成咱们的gmail.com怎么来替换呢,
首先咱们可以用一个方法叫做setrange
setrange name 6 gmail.com
(integer) 15
6代表下标,
"lijie@gmail.com"第一个字符为0,从第六个字符开始替换,
替换成咱们的gmail.com,可以吧,替换完以后他会给你返回一个字符串的长度,
前面为六个后面为9个总共加起来是15个字符,这里回个你返回一个15个字符,
get mane
"lijie@gmail.com"
然后再get的时候,大家会看到,是不是替换成功啦,
set email lijie@lampbrother.net
OK
setrange email 6 li-jie.me
(integer) 21
最终返回21个字符,然后get一下,
get email
"lijie@li-jie.meer.net"
会出现这样一个效果,会出现剩余的东西,也就是说咱们的setrange
如果说我替换的字符串,没有咱们的原字符串长,他会把替换的字符串,到咱们原先的
字符串前面的几个字符都会替换掉,但是后面的字符不会替换,不会删除,也就是如咱们
现在所看到的,是不是这块的内容没有替换掉啊
因为 li-jie.me 这个长度肯定没有lampbrother.me长吧,也就是说他只替换一部分,一直到
er.net前面,对吧,这是咱们的setrange方法,
如果咱们要一次性设置多个值呢,咱们可以使用mset,m代表批量设置,
一次性设置多个key的值,成功返回ok表示所有的值都设置了,
失败的话返回0表示没有任何被设置。如果返回0,所有的值都不成功,
mset key1 lijie1 key2 lijie2 key3 27
OK
行吧,
get key1
"lijie1"
get key2
"lijie2"
两个都设置成功了,因为返回了OK,那么咱们get就可以拿出来,
get key4
(nil)
因为我没有设置key4
这是咱们的mset
那么有mset就应该有msetnx
一次性设置多个key的值,成功返回ok表示所有的值都设置了,
失败返回0表示没有任何只被设置了,但是不会覆盖已经存在的key,
nx同样代表咱们的not exist
咱们刚才是不是有key1, key2, key3啦,
msetnx key4 lampbrother key5 lijie@lampbrother.net key3 20
(integer) 0
看下是返回OK,还是返回0,
大家看到了吗,是不是返回0啊,因为我的key3是不是有存在啊,他不会覆盖吧,
那么这个时候咱们在看以下key4 key5有没有
get key4
(nil)
为空,
get key5
(nil)
也为空,
如果说我有一个键没有设置成功,其他键都不会设置成功,这是咱们的msetnx
同样mset也是一样的啊,
那么我从新设置一下
msetnx key4 lampbrother key5 lijie@lampbrother.net key6 20
(integer) 1
key4,5,6本身是不存在的吧,不存在咱们msetnx是不是会设置成功啊,
是不是返回一个1
get key4
"lampbrother"
get key5
"lijie@lampbrother.net"
get key6
"20"
也就是说咱们的msetnx跟咱们的mset原理其实是一样的,只不过他是批量设置,
get咱们不说了,是不是获取一个值,
那么getset呢,
表示设置key的值,并返回key的旧值,
getset key6 30
"20"
看一下这里是不是返回20啊,
20代表key6的旧值为20那新值为多少呢,咱们get一下key6
get key6
"30"
那么getset什么意思呢,就是获取旧值,并且设置新值,
获取一个key6的旧值,并且获取key6为30的新值,这是咱们的getset。
那么除了这些方法还有什么方法呢,
还有咱们的getrange
咱们刚刚是不是有个setrange啊,setrange是不是设置一个子字符串啊,
那么getrange顾名思义是不是获取子子字符串吧,
get email
"lijie@li-jie.meer.net"
刚刚后面的这块东西是不是没有替换掉啊,那么咱们现在给他获取一下,
getrange email 0 4
"lijie"
是不是lijie这五个字符啊,
getrange email 0 5
“lijie@”
0到5呢是不是加上咱们的@啦啊,
有mset就没有mget吧,
mset是批量设置,那么mget呢,是不是批量获取啊,
mget key1 key2 key3 key4 key5 key6 key7
1) "lijie"
2) "lampbrother"
3) "27"
4) "lampbrother.net"
5) "lijie@lampbrother.net"
6) "30"
7) (nil)
他都给你批量返回,key7我什么都没有设置过是不是返回为空啊,
mset是设置,mget是和她对立的是获取,
那么string类型的操作还咱们的递增,
incr代表什么,代表对某一个值来进行递增,那我现在key6的值是多少30吧,
可以使用一个Incr对咱们的key6
incr key6
(integer) 31
大家看返回的一个值代表什么,代表你设置之后的值, 自增以后的值为,31,
incr key6
(integer) 32
好我再来一次,是不是没执行一次自增一次啊,
那如果我不想让他每一次递增一次啊,比如说我现在34我想让他直接加6加到40怎么加啊,
咱们有另外一个方法叫做incrby,同incr类似,加指定值,
key不存在的时候会设置key,并且认为原来的value为0
incr key7
(integer) 1
咱们下载key7不存在,incr key7他会自增一次
也就是说你用这个incr这个方法咱们可以设置某一个键啊,
同样的incrby也有同样的功能,incrby跟咱们的incr有什么不同的区别呢,
它可以以指定的数来进行增加,
incrby key6 5
(integer) 39
刚才是不是34,咱们自增之后是不是39,
incrby代表我以5来对key6进行自增,
incrby key6 -5
(integer) 34
如果想让他们合作咱们直接自增-5即可,
是不是又变成34啦,
get key6
"34"
是不是又变成34啦, 对吧,
咱们是不是可以设置为正为加,负为减啊,一样的啊,
同样的咱们的string类型呢,还有其他两个方法,
是decr和decrby,他是跟咱们的incr和咱们的incrby是对立的啊,
decr和decrby如果你传一个正数为自减,如果你传一个负数为自增,
decr key6
(integer) 36
decrby key -3
(integer) 39
减一个-3是不是代表加一个3,36是不是变成39啦,如果我把它改为正,是不是直接
减三啊,
decrby key6 3
(integer) 36
变成36啦,所以说咱们的decr跟咱们的decrby与咱们的incr跟incrby你只需要会两种
基本上就可以满足咱们的需求,对吧,
咱们的string类型呢,还有一个重要的方法叫做append
是给制定的key的字符串,追加value,返回新字符串值的长度。
我get name
"lampbrother"
append name .net
(integer) 15
最终返回lampbrother.net这个字符串的长度为15,
get name
"lampbrother.net"
等于说是给咱们的name加了一个.net的字符串,
给他拼接了一个.net的字符串,然后最终返回的是加上.net后的长度为15,
最后string类型还有一个strlen方法,
就是对咱们的字符串查看长度的吧,strlen可以对咱们键查看长度,
刚才我的name键是15个长度吧,咱们来看一下
strlen name
(integer) 15
是不是返回15,是一样的啊,这个方法相对简单一些,
这是一个string类型的一个介绍,及他说有的方法,
string类型是咱们的redis最简单的一个类型吧,
接下来咱们来看redis的第二种数据类型hash数据类型,
那么hash数据类型跟咱们的string数据类型有什么区别,咱们来看一下
Redis的hash是一个string类型的field和value的映射表,
字段和值的映射表,hash可以看作是一个映射表, 他的添加和删除都是O(1)(平均)
hash特别适用于咱们存储对象,相较于将对象的每个字段存成单个string类型,
我们刚才是不是说了string类型可以存储咱们的对象序列化吧,相较于这种方法,
咱们将一个对象存储到hash类型中呢,会占用更小的内存, 并且可以更方便的存储整个对象。
首先设置一个键,用h打头叫hset,代表设置一个hash表,
hset
代表设置hash field为指定值,并且如果key不存在,则先创建,
hset myhash field1 Hello
myhash我们定义的hash表的名字,field1是哈希表一个字段的名字,
Hello是哈希表对应字段的值,可以咱们用来存用户是不是比较方便啊,
hset user:001 name lijie
(integer) 1
user:001代表001号用户,那么我们怎么来获取呢,有hset就应该有hget吧,
hget user:001 name
"lijie"
获取user:001 里面的name字段,是不是返回lijie,是我刚才设置的user:001的name字段吧,
大家可以吧user:001看作是一张表,然后对user:001里面的name设置为lijie,
然后对user:001里面的name呢获取呢,直接获取出lijie,用咱们的hget跟hset
这是咱们哈希表的一个设置,这样来存用户会比较方便哦一些,
还有一个方法是hsetnx跟咱们的setnx方法大同小异,
只不过他是对咱们的哈希表来进行设置把,
hsetnx myhash field "Hello"
(integer) 1
第一次设置的时候返回一个1代表返回成功,
咱们还记得setnx吧,如果你第二次设置的时候,同一个键是不是返回0,
代表设置不成功吧,同样的咱们的hsetnx也一样的,
hsetnx myhash field "Hello"
(integer) 0
hsetnx user:002 name lamp
(integer) 1
hget user:002 name
"lamp"
hsetnx user:002 name lampbrother
(integer) 0
返回为0代表此时咱们设置不成功,这个时候咱们再来get一下,
hget user:002 name
“lamp”
看设置成功了没有,没有设置成功吧,还是咱们刚才的lamp吧,
说明咱们的hsetnx跟咱们的setnx是一样的,
set是不是有mset啊,
那么hset也有hmset,也是批量设置,
hmset myhash field1 "Hello" field2 world
OK
hmset user:003 name lijie age 20 sex 1
OK
这个时候呢,咱们看到返回一个OK,代表咱们对user:003这个哈希表,
里面对谁,对咱们的name,对咱们的age,对咱们的sex均设置成功,
hget user:003 name
"lijie"
hget user:003 age
"20"
hget user:003 sex
"1"
说明批量设置成功,
接下来看下还有什么hget这不用说了吧,获取咱们哈希表里面的某一个字段,
hmget呢是获取里面的所有键吧,
hmget user:003 name age sex
1) "lijie"
2) "20"
3) "1"
大家看这样子是不是批量返回啊,这是咱们的hmget
那么还有咱们的hincrby跟咱们的incrby是一个意思,
对咱们的某一个键进行自增,
hincrby user:003 age 5
(integer) 25
hget user:003 age
"25"
我再获取一下是不是返回25,最终返回25,跟咱们的incr是相似的,
这是咱们的hincrby
那么咱们的哈希里面还有一个方法焦作hexists,
测试制定的field是否存在,
代表你这个哈希表里面的字段是否存在,
hexists user:003 age
(integer) 1
age一定是存在的吧,看返回一个1,
hexists user:001 sex
(integer) 0
user:001里面是没有sex的,来看一下是不是返回一个0
这是是来判断咱们哈希表里面的某一个字段,是否存在的方法,
除此以外呢,咱们的哈希还有一个方法叫做hlen,
返回指定的哈希的field的数量,
返回哈希里面键的数量,
hlen user:001
(integer) 1
hlen usr:003
(integer) 3
hlen返回你的哈希表里面存在的所有的字段的数量,
这是咱们的hlen的方法,
那我可以给哈希设置一个字段,那我能不能删除啊,
hdel 删除指定哈希的一个field字段,
那怎么删除呢,
hget user:003 age
"25"
发现这个age字段是存在的,假如我们现在想要把这个age删除掉,
hdel user:003 age
(integer) 1
返回一个1代表删除成功,这个时候再来查看
hget user:003 age
(nil)
咱们是不是把年龄字段给删除掉了,也就是说此字段为“保密”
还有一个hkeys方法,
返回哈希表里面说有的field
hkeys user:001
1) "name"
hkeys user:003
1) "name"
2) "sex"
hkeys代表返回咱们哈希表里面说有的字段,
是不是跟咱们php里面array_case这个函数是不是一样的,
array_keys是不是返回咱们数组里面的所有键啊,
有array_keys是不是就有array_value啊,
相应的也有hvals代表返回此哈希表里面的所有的value
hvals user:001
1) "lijie"
hvals user:002
1) "lamp"
hvals user:003
1) "lijie"
2) "1"
返回所有字段的对应值,
最后咱们来看一个哈希的另一个方法hgetall
获取某个哈希中全部的field及value,这样子是不是不容易乱啊,
如果用刚才的hvals获取出来的全部是vals,你不知道他们的字段是什么,
hkeys你只知道他的字段,你不知道他的值吧,这样用起来是不是不太方便啊,
那么咱们可以用一个方法叫做hgetall
hgetall user:003
1) "name"
2) "lijie"
3) "sex"
4) "1"
大家可以清晰的看出来name为lijie,sex为1。这样子用起来方便一些。
这就是哈希类型的简单介绍以及他的所有的方法。
hexist,hlen ,hdel ,hkeys,hvals,hgetall是咱们的string类型没有的,
hincrby myhash age -8
哈希表里面设置首先第一个参数是什么,第一个参数为哈希表的名称,
第二个参数为哈希表里面的字段,第三个字段为哈希表所对应字段的值,