> 文档中心 > Redis字符串类型和哈希类型讲解

Redis字符串类型和哈希类型讲解


1、字符串

1.1 简介

字符串是Redis最基础的数据类型,其他的几种数据类型都是在字符串的基础上构建的。字符串类型的值实际上可以是字符串,数字,甚至可以是二进制的图片、音视频,但是其最大值为512M。

1.2 常用命令

(1)设置值

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

解析:

ex seconds : 为键设置秒级过期时间

px milliseconds: 为键设置毫秒级过期时间

nx:键必须不存在时才能设置成功,用于添加功能

xx:键必须存在才能设置成功,用于更新功能,与nx互斥存在。

除了set外,还提供了setex 和setnx两个命令,他们的作用和ex与nx的参数是一样的。

setex key secends valuesetnx key value 

示例

# test键不存在127.0.0.1:6379> exists test(integer) 0# set命令设置test键值为ttt127.0.0.1:6379> set test tttOK# setnx命令设置test,因为test键已经存在,所以设置失败,返回0127.0.0.1:6379> setnx test tt1(integer) 0#set xx 更新test值为qqq127.0.0.1:6379> set test qqq xx OK

根据setnx的特性,多个客户端使用该命令时,只有一个客户端才能成功,所以setnx可以作为分布式锁的一种实现方案。

(2)获取值

# 如果key存在,返回对应的value,如果key不存在,返回nilget key

(3)批量设置值

mset key value [key value ......]#示例:#通过mset一次性设置多个key-value对127.0.0.1:6379> mset a 1 b 2 c 3OK

(4)批量获取值

mget key [key ......]#示例:#通过mget获取 a、b、c的值127.0.0.1:6379> mget a b c1) "1"2) "2"3) "3"#如果某些键不存在的话,会按照key的顺序返回nil127.0.0.1:6379> mget a b c d1) "1"2) "2"3) "3"4) (nil)

(5)计数

incr key

incr命令用于对值做自增操作,返回结果有三种情况:

  • 值不是整数,返回错误
  • 值是整数,返回自增结果
  • 键不存在,新增键值对,按照值为0自增,返回结果为1

除了incr命令,还有decr(自减)、incrby(自增指定数字)、decrby(自减指定数字)、incrbyfloat(自增浮点数)

decr keyincrby key incrementdecrby key decrementincrbyfloat key incrememt

1.3 内部编码

我们平时用到的数据结构是redis对外提供的数据结构类型,实际上在redis底层,每种数据结构都有对应独特的内部编码,下面介绍String的内部编码。

字符串在redis底层有三种编码类型,Redis会根据当前值的类型和长度决定使用那种内部编码实现,三种类型如下:

  • int:8个字节的长整型
  • embstr:小于等于39个字节的字符串
  • raw:大于39个字节的字符串

示例:

#整型127.0.0.1:6379> set k 11111111OK127.0.0.1:6379> object encoding k"int"#短字符串127.0.0.1:6379> set x xxxxxxxxxxOK127.0.0.1:6379> object encoding x"embstr"#长字符串127.0.0.1:6379> set y "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"OK127.0.0.1:6379> object encoding y"raw"

1.4 使用场景

(1)缓存功能

使用Redis作为缓存服务器使用,由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。下图是比较常见的缓存使用场景,使用mysql作为存储层,使用Redis作为缓存层,绝大部分数据从redis中返回,能大大提高web服务的响应时间。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k3V5TWAw-1650784188758)(imgs/image-20220221155007574.png)]

(2)计数器

目前许多服务都使用redis作为计数器的实现工具,redis能够实现快速计数功能,并且可以查询缓存,同时数据也可以异步写入到其他数据源中,比如网站的访问次数完全可以使用redis进行计数,每多一次访问,就自增1。

(3)token(session)共享

token(session)共享也是redis的一大使用场景,在微服务或者分布式web服务中,实现token(session)共享是一个十分重要的功能。当前端发起请求后,可能会分发到不同的服务中,如果没有实现token(session)共享,用户刷新后,有可能就会发现需要重新登录了,这是无法容忍的。

为了解决这个问题,可以引入redis,把session(token)统一管理起来,只要保证redis服务的高可用,就可以在每次请求时,集中从redis中获取token(session)。

2、哈希

2.1 简介

在Redis中,哈希类型指的是键对应的值本身又是一个键值对结构,形如value={{field1,value1},…{fieldN,valueN}}。哈希类型中的映射关系叫做field-value,这里的value是指field对应的值,不是键对应的值,如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6lmR3Ech-1650784188760)(imgs/image-20220221161406588.png)]

2.2 常用命令

(1)设置值

hset key field value

设置值时,如果设置成功,返回1,反之会返回0。此外Redis提供了hsetnx的命令,它的作用同setnx命令一样,只是作用域由键变成了field。

示例:

127.0.0.1:6379> hset user name candy(integer) 1

(2)获取值

hget key field

如果键或field不存在的话,返回nil。

示例

127.0.0.1:6379> hget user name"candy"

(3)删除field

hdel key field [field ......]

hdel会删除一个或多个field,返回结果为成功删除field的个数。

示例:

127.0.0.1:6379> hdel user name(integer) 1127.0.0.1:6379> hdel user city(integer) 0

(4)计算field个数

hlen key

示例:

127.0.0.1:6379> hset user name tim(integer) 1127.0.0.1:6379> hlen user(integer) 1127.0.0.1:6379> hset user city beijing(integer) 1127.0.0.1:6379> hlen user(integer) 2

(5) 批量设置field-value

hmset key field value [field value ......]

hmset需要的参数是key和多对field-value。

示例:

127.0.0.1:6379> hmset user age 12 set boyOK

(6)批量获取field

hmget key field [field ......]

hmget需要的参数是key和多个field

示例:

127.0.0.1:6379> hmget user name age city set1) "tim"2) "12"3) "beijing"4) "boy"

(7) 判断field是否存在

hexists key field

hexists返回结果为1时说明包含field,否则返回为0

127.0.0.1:6379> hexists user name(integer) 1127.0.0.1:6379> hexists user xxx(integer) 0

(8) 获取所有field

hkeys key

该命令返回的是键对应的所有field。

示例:

127.0.0.1:6379> hkeys user1) "name"2) "city"3) "age"4) "sex"5) "set"

(9)获取所有的values

hvals key

(10)获取所有的field-value

hgetall key

(11)计算value的字符串长度

hstrlen key field

2.3 内部编码

哈希类型内部编码有两种:

  • ziplist(压缩列表)

当哈希类型元素个数小于hash-max-ziplist-entries配置(默认512),同时所有值都小于hash-max-ziplist-value配置(默认64字节)时,Redis会使用ziplist作为哈希的内部实现,ziplist可以使用更加紧凑的结构实现多个元素的连续存储,所以在节省内存方面比hashtable更加优秀。

  • hashtable(哈希表)

当hash类型无法满足ziplist的条件时,Redis就会使用hashtable作为哈希的内部实现,因为此时ziplist的读写效率会下降。

示例:

# (1)当field个数比较少,并且没有大的value时,内部编码为ziplist127.0.0.1:6379> hmset hk f1 v1 f2 v2 f3 v3OK127.0.0.1:6379> object encoding hk"ziplist"# (2) 当value值大于64时,内部编码就会变成hashtable127.0.0.1:6379> hmset hk f4 "ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"OK127.0.0.1:6379> object encoding hk"hashtable"# (3)当field的个数超过512个时,内部编码也会变成hashtable......

2.4 使用场景

缓存关系型数据库的信息。

以用户基本信息为例,相比使用字符串序列化后缓存用户信息,哈希类型变的更加直观,并且在更新操作上变的更加便捷,可以将每个用户的id定义为键或键后缀,多对field-value对应每个用户的字段信息。

关系型数据库与哈希类型的区别:

  • 关系型数据库是完全结构化的数据,而hash是稀疏的,哈希类型每个键可以有完全不同的field,但是关系型数据库一旦添加新的字段,都需要为字段进行赋值。
  • 关系型数据库可以做复杂的关联查询,Redis如果完成复杂的关系型查询,会十分困难。

3、对象类型数据的缓存

3.1 原生字符串

使用原生字符串缓存信息,每个属性一个键。示例如下:

set user.name tomset user.city beijing

优点:简单直观,每个属性都能单独操作

缺点: 占用键过多,使用内存过多,同时信息内聚性太差。

3.2 序列化字符串

将对象信息先进行序列化操作,然后把序列化后的字符串用一个key保存。

优点:简单易用,合理规划对象的序列化,可以提高内存的使用效率

缺点:序列化和反序列化需要一定的资源,同时每次更新都需要把全部数据取出来进行操作。

3.3 哈希类型

每个对象属性使用一对field-value,但使用一个key进行存储

优点:简单直观,使用合理可以减少内存空间的使用

缺点:需要控制哈希在ziplist和hashtable两种内部编码的转换,hashtable会占用更多内存。