Redis数据结构——hash

目录

hash命令

hset

hget

hexists

hdel

hkeys

hvals

hgetall

hmget 

hsetnx 

hincrby /hincrbyfloat

hstrlen 

 哈希命令总结

哈希内部编码方式


redis自身已经是键值对结构了,redis自身的键值对就是通过哈希的方式来组织的,把key这一层组织完成之后,到了value这一层,value的其中一种类型还可以再是哈希,如同套娃一般。

value里哈希的key值就不叫key了而是filed,当我们提到key就是外面的那一层,提到filed就是value里哈希的key。

hash命令

hset

hset可以同样可以设置多组键值对。

语法:

hset  key field value [field value...]

 返回值:设置成功的键值对filed-value的个数。

hset设置一组键值对

 hset设置多组键值对

上面给key设置了f1 111,此处是给key又添加了三个键值对,也就是说此时key里存了4个键值对。

我们设置了之后要获取出来看看吧,就需要使用hget方法获取。

hget

通过key查一下哈希,在通过field查到value。

语法:

hget key field

 返回值:返回field的value,如果不存在返回nil。

不管是key不存在还是filed不存在,都会返回nil。

第一条语句是filed不存在,第二条语句是key不存在。

hexists

判定filed是否存在 。

语法:

hexists key filed

返回值:1表示存在,0表示不存在。

hdel

删除哈希中指定的字段。del删除的是keyhdel删除的是field。一次可以删除多个。

hdel key field [field]

返回值:本次操作删除的字段个数。

如果用del的话,是把整个哈希都删了。 

hkeys

获取到哈希中的所有filed。

语法:

hkeys key

这个操作会遍历哈希,根据key找到哈希,然后再遍历哈希 ,此时时间复杂度是O(N)的。这个N是哈希元素个数,如果哈希非常大,很可能导致redis服务器被阻塞住,因此要谨慎使用。

hkeys获取到的是所有的filed。

hvals

获取到哈希中的value。

语法:

hvals key

hvals的时间复杂度也是O(N),N是哈希元素个数,如果哈希非常大,也很可能导致redis服务器被阻塞住。

hgetall

获取hash中的所有字段。hgetall相当于是hvals和hkeys的结合体,可以获取到所有的filed和value

语法:

hgetall key

hgetall的风险还是很大的,多数情况下我们不需要查找所有的field,可能只需要查询其中几个field,此时就需要使用下面的命令。

hmget 

类似于之前的mget,可以一次查询多个field。

语法:

hmget key field [field...]

这里结果中value的顺序和查询中filed的顺序是一一对应的。 

 hlen

获取到哈希的元素个数,不需要便利,为啥不需要便利呢?用一个变量存一下就可以。

语法:

hlen key

key有3组键值对,因此hlen key的返回值就是3。

hsetnx 

不存在的时候才能设置成功,如果存在,则失败。这里的不存在指的是filed不存在。

语法:

hsetnx key field value

我们先设置一个f5 555,此时f5不存在,设置成功,此时在尝试设置f5的value是666,此时f5已经存在就返回0失败了,此时用fget查询f5时,结果还是555。

hincrby /hincrbyfloat

 hash这里的value,也可以当做数字来处理,使用hincrby就可以加减整数,hincrbyfloat就可以加减整数,使用频率不算很高,因此redis没有提供类似于incr decr...

hincrby

hincrby对value进行加n,这个n也可以是负数。

语法:

hincrby key field n

我们可以对f1的value进行+10。 

hincrbyfloat

对value进行+n,这个n可以是浮点数,同样n也可以是负数。

使用方法和hincrby是一样的。

hstrlen 

计算field对应value长度。

语法:

hstrlen key field

 哈希命令总结

命令执行效果时间复杂度
hset key filed value设置值O(1)
hget key field获取值O(1)
hdel key field [field...]删除fieldO(1)
hlen key计算field个数O(1)
hgetall key获取所有的field-valueO(K)
hmget key field [field...]批量获取field-valueO(K)
hexists key field判断field是否存在O(1)
hkeys key获取所有的fieldO(K)
hvals key获取所有的valueO(K)
hsetnx  key field value设置值,但必须field不存在时才可以设置成功O(1)
hincrby key field n对应field的value + nO(1)
hincrbyfloat key field n对应field的value + nO(1)
hstrlen key field计算field的value长度O(1)

哈希内部编码方式

哈希内部编码方式有两种:

  • ziplist:压缩列表
  • hashtable:哈希表

压缩

压缩我们挺常见到的,比如我们会把一个大文件压缩成rar、zip\gzip、7z等压缩文件,其实就是对数据执行了一些具体的压缩算法。

压缩的本质是对数据进行重新编码,不同的数据有不同的特点,结合这些特点,进行巧妙的设计,重新编码后可以缩小体积。

比如"abbcccddddeeeee"这样的字符串,重新编码表示为:1a2b3c4d5e。

再比如一个文件,内容是"abcd00000000......",abcd后面有99个0,重新编码后就成为abcd0[99]。

当然上述是比较粗糙的编码方式,压缩算法都是精妙设计的。

何时使用hashtable何时使用ziplist

ziplist也是同理,内部的数据都是精心设计过的,表示一个普通的哈希表可能会浪费一定的空间,哈希表首先是个数组,有些位置上有元素有些位置上没元素,可能就会浪费一些空间。

当然ziplist也会付出一些代价,它进行读写元素,速度是比较慢的,当然元素少的话,慢的并不明显,如果元素太多,就会慢的雪中送碳。

因此,如果元素少,则会使用ziplist表示,元素个数比较多,使用hashtable来表示。

其次,如果value的值长度比较短,使用ziplist,如果某个value太长,则会转换成hashtable。

因此如果要使用ziplist必须元素少并且value长度短。

配置文件

在redis的配置文件中有hash-max-ziplist-entries配置选项,这个选项默认是512,也就是说如果元素个数小于512时使用ziplist,大于则使用hashtable。

还有一个hash-max-ziplist-value配置选项,默认是64字节,如果所有元素的值都是小于64字节则使用ziplist,否则使用hashtable。

这个配置文件在 /etc/redis/目录下,可以通过配置文件手动的调整hash-max-ziplist-entries和hash-max-ziplist-value的默认大小。

### Redis 支持的数据结构类型及用法 #### String 类型 String 是 Redis 中最基础的数据类型,用于表示简单的键值对。每个键关联的是一个字符串形式的值,尽管这个值可以代表多种实际数据类型,如整数、浮点数或是二进制流等[^2]。值得注意的一点是,虽然这些不同种类的信息被当作字符串来处理,但在某些情况下仍然可以直接对其进行数值运算操作。 对于 string 类型来说,其内部实现能够高效地支持大尺寸的内容存储,单个 value 的大小上限可达 512 MB[^4]。这使得它非常适合用来保存诸如网页缓存、会话状态以及其他任何形式的大块文本或二进制资料片段。 ```python # Python 示例:设置并获取string类型的key-value import redis r = redis.Redis(host='localhost', port=6379, db=0) r.set('name', 'Alice') # 设置名为"name"的key,value为"Alice" print(r.get('name')) # 获取该key对应的value ``` #### Hashes (哈希表) 类型 Hash 结构允许将多个字段及其相应的值组合成单一记录,并通过唯一的 key 来访问整个集合。这种特性特别适合模拟面向对象编程中的实体模型——例如,在 Java 应用程序里创建的对象实例就可以很方便地映射到 Redis hash 上面去;其中对象的名字作为外部 key 而各个成员变量则成为内部 field 和 value 对[^5]。 ```bash HSET user:1000 username "Bob" age 28 city "Beijing" HRGETALL user:1000 ``` 以上命令展示了如何向 `user:1000` 这样的hash中添加三个field(`username`, `age`, `city`) 及各自对应的values. #### List 列表类型 Lists 提供了一个有序序列容器的功能,可以从两端快速插入/删除元素而不会影响其他位置上的项目排列顺序。因此当涉及到队列机制设计时(比如消息传递系统),lists 就显得非常有用处了. ```bash LPUSH mylist "first item" RPUSH mylist "last item" LRANGE mylist 0 -1 ``` 这段脚本先是从左边把 `"first item"` 加入到了 list 名叫 `mylist` 当中,接着又从右边追加了一条新纪录进去最后再打印出了全部内容。 #### Set 集合类型 Sets 存储无序且不允许重复项存在的元素集。由于 sets 自动排除掉所有试图加入已存在成员的操作请求,所以经常应用于唯一性验证场合下,像社交网络里的好友关系管理就是很好的例子之一[^1]. ```bash SADD unique_emails "alice@example.com" SISMEMBER unique_emails "bob@example.com" SMEMBERS unique_emails ``` 上述指令实现了往 set `unique_emails` 添加邮箱地址的动作同时也查询某个特定邮件是否已经存在于当前set内还有查看所有的email members。 #### Sorted Sets 排序集合类型 Sorted sets 不仅继承了普通sets的特点即保持成员间互异性之外还额外引入了分数概念从而让每一条记录都能按照指定权重来进行全局排序。这样一来就很容易构建排行榜之类的业务逻辑了. ```bash ZADD leaderboard 150 playerA ZADD leaderboard 200 playerB ZRANGEBYSCORE leaderboard -inf +inf WITHSCORES ``` 这里定义了一个叫做leaderboard的sorted set 并分别给两个玩家赋予不同的得分之后按分值高低显示排名情况连同具体分数一同呈现出来。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值