String类型

前言

之所以介绍是因为基本数据类型是系统中一切操作的基础,就像物理世界中的原子,高楼大厦中的砖瓦。当咱们整明白了这些基本数据类型,使用层面就是挑选和组合的问题了。本文小结下Redis中数据结构和使用场景,如果你有更骚气的挑选和组合方式,欢迎在评论区留下你的痕迹。

一、必要性

个人已知的存储系统,无论是磁盘,内存又或是CPU内部的缓存,在逻辑层面其实都是一种Key-Value的访问模式。也就是给定一个Key(可能是磁盘地址,内存地址,缓存地址),返回一个value(本质上是个字节数组)。所以,Redis作为一种缓存实现方式, 肯定要实现K-V存储。毕竟这玩意是最简单的缓存使用方式,写入和独读出。

二、怎么实现的

1. 基础结构

咱们想直接基于C的字符串实现就好了,实际却是一个叫SDS的字符串。这玩意儿长这个样子
String类型_第1张图片

字段名称 字段内容
free 字符串剩余空间大小,如果为0说明buf中没有空闲位置, 否则buf中还有free个字节剩余
len 字符串长度
buf 实际存储的字节数组,考虑到字符串的动态变化

2. 结构特点

a. 空间预分配

创建字符串时,buf的实际长度通常比存储的字符串长度要长。这样更新时候可以减少数组的扩容成本。

空间大小 预分配数量(表中1M表示数量1024 * 1024)
len < 1M 多分配len个字节,此时free=len,实际能支持的最大长度为 len * 2 + 1
len >= 1M 多分配1M个字节,此时free=1M, 实际能支持的最大长度为 len + 1M + 1

b. 空间惰性回收

如果字符串长度被裁剪,Redis也不会马上对空间进行回收,毕竟以后还有可能会变长。这样经过一段之后,所有的字符串都达到了最大长度,基本不需要做额外的空间分配。

c. 二进制安全

首先,我们得知道字符串本身是一堆的字符组成的,而字符最后是由一个个字节标识的。由于一个字节只有8位,至多表示255个字符。然世界上又如此多的语言,仅中文有10万个字符,于是就出现了UTF-8/UTF-16等扩展编码。因此,一个可显示的字符串的信息包括字节和对应的编解码方式。

其次,Redis作为一个存储系统,不关心编解码方式,只关心实际的字节序列。此时如果严重依赖C语言中的’\0’结尾可能存在误判,比如字符串中就包含一个’\0’字符,有了len字段直接从buf[0]读取到buf[len-1]即可,也就是只关心数组序列不关心编码。这就是二进制安全。

d. C字符串兼容

个人认为有了len可以不要那个’\0’, 但毕竟通过C语言实现,兼容下减少些别扭。所以增加了’\0’, 以保持兼容,至少在直接基于C语言开发和调试的时候,体验会很爽。当然,实际情况确实兼容了,但作者没说他是否为了方便开发和调试。

三、Redis特色

到这里,你已经知道字符串在Redis内部除了metadata信息外就是一波字节序列,那能不能直接对字节做操作呢?显然是可以的。其实这算是一个颗粒度问题,字符级,字节级和位级。这里想强调的是字节级和位级。

级别 操作
字节级 将存储的字节内容当做一个整数, 比如incr 做+1操作, 当然此时会尝试做数据类型转换。如果长度特别长可能会失败。
位级 将存储的字节作为一个bitmap,操作其中的某个位

更多的操作详情,还得参考Redis官方文档,这里只是探讨下Redis支持这些操作背后的事情。

四. 使用场景

场景 说明
简单缓存 将读多写少数据缓存其中, 比如一篇博客,降低数据源压力
存在性问题 作为bitmap记录是否xx, 比如记录用户是否登录,如果记录了多天的登录统计数据还可做用户行为分析
不严格统计问题 记录总数,比如一篇博客的点赞数,评论数,转发数

总结

以上就是今天要分享的全部内容,本文介绍了Redis中的String类型,以及由此延伸出的字节级和位级操作,最后总结了下常见的使用场景。鉴于本人水平有限,如有遗漏还请不吝赐教,感谢你的阅读。

你可能感兴趣的:(Redis,redis)