Redis数据类型(list\hash)

Redis数据类型(list\hash)_第1张图片

 "we had our heads in the clouds"


String类型

        字符串类型是Redis最基础的数据类型,关于字符串需要特别注意的是:
● Redis中所有的键类型都是字符串类型.⽽且其他⼏种数据结构也都是在字符串类似基础上构建的,例如列表和集合的元素类型是字符串类型。

● 字符串类型的值实际可以是字符串,包含⼀般格式的字符串或者类似JSON、XML格式的字符串,数字;可以是整型或者浮点型;甚⾄是⼆进制流数据(视频、音频),但是其总大小不得超过512MB。

Redis数据类型(list\hash)_第2张图片

(1) SET | MSET        

SET命令

Redis数据类型(list\hash)_第3张图片

● NX: 如果key不存在,才设置;如果key存在,则不设置返回(nil).

● XX: 如果key存在,进行更新;如果key不存在,则不设置返回(nil).

● PX: 使⽤毫秒作为单位设置key的过期时间.

● EX: 使⽤秒作为单位设置key的过期时间.

        在redis文档中的语法格式说明:  "[]" 相当于一个独立的单元,其中的所有参数都是可选项。"[]"之间可以同时存在。"|"表示多个选项中,只能出现一个的意思。

Redis数据类型(list\hash)_第4张图片        

 注:  如果key存在,让新的value去覆盖旧的value的同时,可能会改变原来的数据类型,原来key的ttl也会失效。

        其中SETNX | SETTX | SETPX都是SET命令带上“[]"里的效果,所以会用一个SET命令仅够用了。

Redis数据类型(list\hash)_第5张图片

        ⼀次性设置多个key的值. 

Redis数据类型(list\hash)_第6张图片

(2) GET | MGET 

        Redis数据类型(list\hash)_第7张图片

        获取key对应的value。如果key不存在,返回nil。如果value的数据类型不是string,会报错 。 Redis数据类型(list\hash)_第8张图片 

Redis数据类型(list\hash)_第9张图片        ⼀次性获取多个key的值。如果对应的key不存在或者对应的数据类型不是string,返回nil。
Redis数据类型(list\hash)_第10张图片          

多次getvs单次mget:       Redis数据类型(list\hash)_第11张图片

        我们先使用 "keys *" 将缓存在redis中的数据打印出来,现在我们需要得到这些keys的value是什么。        Redis数据类型(list\hash)_第12张图片        这两种查询方法有什么区别呢?是不是都是一样呢?

Redis数据类型(list\hash)_第13张图片        redis作为网络服务器,任何一条请求、命令都是需要通过网络设备进行发送的,当你发送多条命令,意味着多次网络IO,相反如果你能使用一次网络IO就将你需要的结果拿到,效率一定是更快的。               

(3) 计数命令

INCR:

Redis数据类型(list\hash)_第14张图片        将key对应的string表⽰的数字加⼀。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型。

        Redis中的String支持数字,这也就意味着String更容易支持 运算符操作。

Redis数据类型(list\hash)_第15张图片

INCRBY:

Redis数据类型(list\hash)_第16张图片        将key对应的string表⽰的数字加上对应的值,如果key不存在,则视为key对应的value是0果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。

        INCRBY的使用同INCR是一样的,只不过你可以指定增加多少。
Redis数据类型(list\hash)_第17张图片
       

DECR\DECRBY:

        将key对应的string表⽰的数字减⼀。如果key不存在,则视为key对应的value是0。如果key对应的string不是⼀个整型或者范围超过了64位有符号整型,则报错。

Redis数据类型(list\hash)_第18张图片
 

INCRBYFLOAT:

Redis数据类型(list\hash)_第19张图片

        将key对应的string表⽰的浮点数加上对应的值。如果对应的值是负数,则视为减去对应的值。如果key不存在,则视为key对应的value是0。如果key对应的不是string,或者不是⼀个浮点数,则报错。允许采⽤科学计数法表⽰浮点数。 Redis数据类型(list\hash)_第20张图片

        针对这个浮点数版本, redis没有提供负数版本,但是通过控制"+-"也可以实现减法版本。 因为redis在处理命令的时候,是单线程模型,虽然多个客户端可能同时对一个key进行INCR,但也不会引发线程安全问题。

(4) 其他命令字符串命令

        前面的一些命令似乎和字符串关系不大,本小结的一些命令会让这个value字符串类型更像字符一样使用。

APPEND:

Redis数据类型(list\hash)_第21张图片

        如果key已经存在并且是⼀个string,命令会将value追加到原有string的后边。如果key不存在,则效果等同于SET命令。

Redis数据类型(list\hash)_第22张图片
 

redis中的字节与字符:

Redis数据类型(list\hash)_第23张图片

        我们重启redis-cli客户端,并携带选项--raw。Redis数据类型(list\hash)_第24张图片 

GETRANGE:        Redis数据类型(list\hash)_第25张图片

        返回key对应的string的⼦串,由start和end确定(左闭右闭)。可以使⽤负数表⽰倒数。-1代表倒数第⼀个字符,-2代表倒数第⼆个,其他的与此类似。超过范围的偏移量会根据string的⻓度调整成正确的值。        Redis数据类型(list\hash)_第26张图片

         

SETRANGE:

Redis数据类型(list\hash)_第27张图片

        覆盖字符串的⼀部分,从指定的偏移开始。

Redis数据类型(list\hash)_第28张图片 

STRLEN: 

Redis数据类型(list\hash)_第29张图片

        获取key对应的string的⻓度。当key存放的类似不是string时,报错.

 

String命令小结:

命令 执行效果 时间复杂度
set key value 设置key的值value O(1)
get key 获取key的value O(1)
del key [key ...] 删除指定的key O(k),k为键个数
mset key value [key value..] 批量设置多个key和value O(N)
mget key 批量获取多个key O(N)
incr\incrby +b key 指定key+1\+n O(1)
decrby key n  指定key-1 O(1)
incrbyfloat key n 指定key +- n O(1)
strlen key 获取字符串类型key的长度 O(n),字符长度
setrange key offset value 从offset的位置用value覆盖key O(n),n是字符串长度
getrange key start end 指定获取key的value 从start到end O(n),n为字符串长度

String 内部编码

        字符串类型的内部编码有3种:
• int:64位/8字节的正数。
• embstr:⼩于等于39个字节的字符串,压缩字符串适合存储短字符串。
• raw:⼤于39个字节的字符串。普通字符串,只是一个单纯的字节数组。 
        我们可以通过这个命令,查看一个key对应的数据value的内部编码:

Redis数据类型(list\hash)_第30张图片 

        Redis数据类型(list\hash)_第31张图片        这里到底是超过多少字节就由embstr 转为 raw这个限度是可以进行配置的。

Redis数据类型(list\hash)_第32张图片        因为redis存储小数,本质上仍然是用字符串来存储的,这就和单纯存储整数相差挺大的。当小数参与到算术运算时,一定要做的步骤是,将字符串转换为小数数值,得到结果后又将该小数转换为字符串。 

 

String应用场景

① 缓存Cache功能:

        我们可以看如下的一个典型场景:

Redis数据类型(list\hash)_第33张图片

        其中redis作为缓冲层,Mysql作为主要存储层,绝大部分请求数据会通过redis缓存拿到结果。因为redis具有⽀撑⾼并发的特性,缓存常能起到加速读写和降低后端压⼒的作⽤。

        随着访问量的增加,redis一定会遇到缓存被打满的情况,redis提供了一系列措施来解决redis面对的存储空间变小的,例如 给key设置过期策略,定期、惰性删除以及当redis内存不足时,使用的淘汰策略。

② 计数器Counter:

        做自媒体的博主,十分在意的就是用户浏览量。许多应⽤都会使⽤Redis作为计数的基础⼯具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。       Redis数据类型(list\hash)_第34张图片

 

③ 会话Session:

什么是session?        

        Session:在计算机中,尤其是在网络应用中,称为“会话控制”。Session对象存储特定用户会话所需的属性及配置信息。

        在一个分布式Web中,如果服务器将⽤⼾的Session信息保存在各⾃的服务器中,这样做就会导致一个问题:由于负载均衡器的缘故,分布式服务会将⽤⼾的访问请求均衡到不同的服务器上,也就是你的第一次请求和第二次请求可能被打在了不同的服务器上。很显然,接收你第二次请求的服务器不应该知道你是已经登录过了的,或者你历史访问的信息。        Redis数据类型(list\hash)_第35张图片

         以上介绍了使⽤Redis的字符串数据类型可以使⽤的⼏个场景,当然其适⽤场景远不⽌于此,开发⼈员可以结合字符串类型的特点以及提供的命令,充分发挥⾃⼰的想象⼒,在⾃⼰的业务中去找到合适的场景去使⽤Redis的字符串类型。
 


Hash类型

        ⼏乎所有的主流编程语⾔都提供了哈希(hash)类型,它们的叫法可能是哈希、字典、关联数
组、映射。在Redis中,哈希类型是指值(value)本⾝⼜是⼀个键值对结构。

字符串 vs 哈希结构:

Redis数据类型(list\hash)_第36张图片

(1) HSET\HGET

Redis数据类型(list\hash)_第37张图片 

        设置hash中指定的字段(field)的值(value)。

Redis数据类型(list\hash)_第38张图片        获取hash中指定字段的值。 

Redis数据类型(list\hash)_第39张图片 Redis数据类型(list\hash)_第40张图片

 

(2) HDEL\HEXISTS

Redis数据类型(list\hash)_第41张图片

        删除hash类型中指定的字段。
Redis数据类型(list\hash)_第42张图片        判断hash中是否有指定的字段。

Redis数据类型(list\hash)_第43张图片 

(3) HKEYS\HVALS

Redis数据类型(list\hash)_第44张图片        获取指定key中hash的所有字段。这个先根据key,找到对应的hash(O(1)),然后再遍历整个hash。

Redis数据类型(list\hash)_第45张图片

Redis数据类型(list\hash)_第46张图片

        获取hash中的所有的值。
Redis数据类型(list\hash)_第47张图片        这个两个操作同 “keys * " 大同小异,实际中在我们不知道field和value的情况下,不用为上策。

(4) HGETALL\HMGET

Redis数据类型(list\hash)_第48张图片

        获取hash中的所有字段以及对应的值。
Redis数据类型(list\hash)_第49张图片 

Redis数据类型(list\hash)_第50张图片

                ⼀次获取hash中多个字段的值。

Redis数据类型(list\hash)_第51张图片
        因为HSET已经可以设置多个field 、value 所以虽然有HMSET但是可以被替代了。

(5) HLEN 

Redis数据类型(list\hash)_第52张图片

        获取hash中的所有字段的个数。

Redis数据类型(list\hash)_第53张图片

(6) HSETNX\HINCRBYFLOAT\HINCRBY

Redis数据类型(list\hash)_第54张图片

        在字段不存在的情况下,设置hash中的字段和值。

Redis数据类型(list\hash)_第55张图片 

 Redis数据类型(list\hash)_第56张图片

Redis数据类型(list\hash)_第57张图片 

        HINCRBY的浮点数版本,将hash中字段对应的数值添加指定的值。
Redis数据类型(list\hash)_第58张图片 

Hash命令小结:

命令 执行效果 时间复杂度
hset key field value 设置值 O(1)
hget key field  获取值 O(1)
hdel key field [field...] 删除field O(n),n是field的个数
hlen key 计算field个数 O(1)
hgetall key 获取所有的field-value O(n),n是field的个数
hmget field[field...] 批量获取value O(n),n是field的个数
hmset field value [field value....] 批量设置值 O(n),n是field的个数
hexists key field  判断field是否存在 O(1)
hkeys\vals key 获取所有的key\value O(n),n是field的个数
hsetnx key field value filed不存在才成功 O(1)
hincrby key field n 对应的value+n O(1)
hincrbyfloat key field n 浮点数版本 O(1)
hstrlen key field 计算value的字符串长度 O(1)

Hash内部编码:

        哈希的内部编码有两种:

• ziplist(压缩列表)当哈希类型元素个数⼩于hash-max-ziplist-entries配置(默认512个)、
同时所有值都⼩于hash-max-ziplist-value配置(默认64字节)时,Redis会使⽤ziplist作为哈
希的内部实现,ziplist使⽤更加紧凑的结构实现多个元素的连续存储,所以在节省内存⽅⾯⽐
hashtable更加优秀。

• hashtable(哈希表)当哈希类型⽆法满⾜ziplist的条件时,Redis会使⽤hashtable作为哈希
的内部实现,因为此时ziplist的读写效率会下降,⽽hashtable的读写时间复杂度为O(1)。
 

如何理解压缩?        Redis数据类型(list\hash)_第59张图片

        ziplist也是同理,因为一个普通的哈希表,如果存储少量的值,存在一定的空间浪费,这显然对redis这类极其看重空间的组件来说是不能容忍的。但,ziplist付出的代价是,进行读写元素时速度还是很慢,这种效果随着插入的元素增多而愈发明显。

 

Hash应用场景:

① 关系型表数据转换

关系型数据库表
uid name age city
1 LeBron James 38 LosAngels
2 Anthony Davis 30 LosAngels


映射关系表⽰⽤⼾信息:        

Redis数据类型(list\hash)_第60张图片

        但是需要注意的是哈希类型和关系型数据库有两点不同之处:

uid name age city gender favor
1 James 38 LosAngel sports
2 Davis 30 LosAngel sports

Redis数据类型(list\hash)_第61张图片● 哈希类型是稀疏的,⽽关系型数据库是完全结构化的.

● 关系数据库可以做复杂的关系查询,⽽Redis去模拟关系型复杂查询.

② 缓存⽅式对⽐

● 原⽣字符串类型⸺使⽤字符串类型,每个属性⼀个键

# 这里的field中的value 是字符串
set user:1:name James
set user:1:age 38
set user:1:city LosAngel

优点:实现简单,针对个别属性变更也很灵活。
缺点:占⽤过多的键,内存占⽤量较⼤,同时⽤⼾信息在Redis中⽐较分散,缺少内聚性,所以这种⽅案基本没有实⽤性。

 ● 序列化字符串类型,例如JSON格式 

set user:1 经过序列化后的⽤⼾对象字符串

优点:针对总是以整体作为操作的信息⽐较合适,编程也简单。同时,如果序列化⽅案选择合适,内存的使⽤效率很⾼。
缺点:本⾝序列化和反序列需要⼀定开销,同时如果总是操作个别属性则⾮常不灵活。

        当我们需要修改Json中的某些值时,需要将Json中保存的所有值先反序列化成字符串,操作field,再重写完成后序列化成Json,再写回去。

● 哈希类型

hmset user:1 name James age 38 city LosAngel

优点:简单、直观、灵活。尤其是针对信息的局部变更或者获取操作。

缺点:需要控制哈希在ziplist和hashtable两种内部编码的转换,可能会造成内存的较⼤消耗。


本篇到此结束,感谢你的阅读。

祝你好运,向阳而生~ 

Redis数据类型(list\hash)_第62张图片 

你可能感兴趣的:(redis,redis,哈希算法,数据库)