浅谈redis数据结构之字符串
1. 前言
在上一篇的文章:浅谈redis数据结构,对redis中的数据结构(字符串,列表,hash,集合,有序集合)做了简单的介绍,本篇就是针对字符串做详细的描述。
2. 字符串(string)
字符串类型是Redis最基础的数据结构。字符串类型的值实际可以是字符串(简单和复杂的字符串,例如:JSON、XML)、数字(整数、浮点数),甚至是二进制(图片、音频、视频),但是值最大不能超过512MB。Redis中关于字符串的命令如下所示:
2.1 常用命令
命令 | 说明 |
set key value [ex seconds] [px milliseconds] [nx|xx] | 设置值。ex seconds:为键设置秒级过期时间;px milliseconds:为键设置毫秒级过期时间;nx:键必须不存在,才可以设置成功,用于添加;xx:与nx相反,键必须存在,才可以设置成功,用于更新。 |
setex key seconds value | 设定键的值,并指定此键值对应的 有效时间。 |
setnx key value | 键必须不存在,才可以设置成功。如果键已经存在,返回0。 |
get key | 获取值,如果要获取的 键不存在,则返回 nil(空)。 |
mset key value [key value ...] | 批量设置值 |
mget key [key ...] | 批量获取值 |
incr key | 计数 |
2.2 不常用命令
命令 | 说明 |
append key value | 追加值 |
strlen key | 字符串长度 |
getset key value | 设置并返回原值 |
setrange key offeset value | 设置指定位置的字符 |
getrange key start end | 获取部分字符串 |
在这些命令中,其中批量操作的命令,是可以有效地提高开发效率地。我们做个简单的对比:
- 不采用批量操作
如下图所示:
没有mget这样的命令,要执行n次get命令的过程和耗时:n次get时间 = n次网络时间 + n次命令时间。
- 采用批量操作
如下图所示:
使用mget命令后,执行n次get命令的过程和耗时:n次get时间 = 1次网络时间 + n次命令时间。
Redis可以支撑每秒数万的读写操作,但这指的是Redis服务端的处理能力,对于客户端来说,一次命令除了命令时间还是有网络时间。假设网络时间为1毫秒,命令时间为0.1毫秒(按照每秒处理 1 万条命令算),那么执行1000次get命令和1次mget命令的区别如表所示:
操作 | 时间 |
1000次get操作 | 1000 * 1 + 1000 * 0.1 = 11000ms = 1.1s |
1次mget操作 | 1 * 1 + 1000 * 0.1 = 0.101s |
2.3 时间复杂度及内部编码
字符串类型的内部编码有3种:
- int,8个字节的长整型
- embstr,小于等于39个字节的字符串
- raw,大于39个字节的字符串
Redis会根据当前值的类型和长度决定使用哪种内部编码实现。
3. 应用场景
- 缓存
上图是一种比较典型的缓存使用场景,其中Redis作为缓存层,MySQL作为存储层,绝大部分请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。
- 计数
许多应用都会使用Redis作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步落地到其他数据源。一般来说,视频播放数系统,就是使用Redis作为视频播放数计数的基础组件,用户每播放一次视频,相应的视频播放数就会自增1。
- 共享Session
一个分布式Web服务将用户的Session信息(例如:用户登录信息)保存在各自的服务器中。这样会造成一个问题,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问可能会发现需要重新登录,这个问题是用户无法容忍的。如下图所示:
为了解决这个问题,可以使用Redis将用户的Session进行集中管理。在这种模式下,只要保证Redis是高可用和扩展性的,每次用户更新或者查询登录信息都直接从Redis中集中获取。如下图所示:
- 限速
很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用户每分钟获取验证码的频率。
4. 后续
下一篇文章,我们研究下redis中列表数据结构:浅谈redis数据结构之列表。