内容简介:字符串类型是除了
字符串类型是 Redis
最基础的数据结构。 字符串类型 的值实际可以是 字符串 ( 简单 和 复杂 的字符串,例如 JSON
、 XML
)、 数字 (整数、浮点数),甚至是 二进制 (图片、音频、视频),但是值最大不能超过 512MB
。
正文
1. 相关命令
1.1. 常见命令
1.1.1. 设置值
set key value [ex seconds] [px milliseconds] [nx|xx]
set
命令有几个选项:
- ex seconds :为 键 设置 秒级过期时间 。
- px milliseconds :为 键 设置 毫秒级过期时间 。
- nx :键必须 不存在 ,才可以设置成功,用于 添加 。
- xx :与
nx
相反,键必须 存在 ,才可以设置成功,用于 更新 。
除了 set
选项, Redis
还提供了 setex
和 setnx
两个命令:
setex key seconds value setnx key value
- setex :设定键的值,并指定此键值对应的 有效时间 。
127.0.0.1:6379> setex key1 5 value1 OK 127.0.0.1:6379> get key1 "value1" 127.0.0.1:6379> get key1 (nil) 复制代码
- setnx :键必须 不存在 ,才可以设置成功。如果键已经存在,返回
0
。
127.0.0.1:6379> set key2 value1 OK 127.0.0.1:6379> setnx key2 value2 (integer) 1 127.0.0.1:6379> get key2 "value1" 复制代码
1.1.2. 获取值
get key
如果要获取的 键不存在 ,则返回 nil
( 空 )。
127.0.0.1:6379> get not_exist_key (nil) 复制代码
1.1.3. 批量设置值
mset key value [key value ...]
下面操作通过 mset
命令一次性设置 4
个 键值对 :
127.0.0.1:6379> mset a 1 b 2 c 3 d 4 OK 复制代码
1.1.4. 批量获取值
mget key [key ...]
通过下面操作 批量获取 键 a
、 b
、 c
、 d
的值:
127.0.0.1:6379> mget a b c d 1) "1" 2) "2" 3) "3" 4) "4" 复制代码
批量操作命令,可以有效提高 开发效率 ,假如没有 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 = 1100ms = 1.1s |
1次mget操作 | 1 * 1 + 1000 * 0.1 = 101ms = 0.101s |
1.1.5. 计数
incr key
incr
命令用于对值做 自增操作 ,返回结果分为三种情况:
- 值不是 整数 ,返回 错误 。
- 值是 整数 ,返回 自增 后的结果。
- 键不存在,按照值为
0
自增 ,返回结果为1
。
127.0.0.1:6379> exists key (integer) 0 127.0.0.1:6379> incr key (integer) 1 复制代码
除了 incr
命令, Redis
还提供了 decr
( 自减 )、 incrby
( 自增指定数字 )、 decrby
( 自减指定数字 )、 incrbyfloat
( 自增浮点数 )等命令操作:
decr key incrby key increment decrby key decrement incrbyfloat key increment
很多 存储系统 和 编程语言 内部使用 CAS
机制实现 计数功能 ,会有一定的 CPU
开销。但在 Redis
中完全不存在这个问题,因为 Redis
是 单线程架构 ,任何命令到了 Redis
服务端 都要 顺序执行 。
1.2. 不常用命令
1.2.1. 追加值
append key value
append
可以向 字符串尾部 追加值。
127.0.0.1:6379> get key "redis" 127.0.0.1:6379> append key world (integer) 10 127.0.0.1:6379> get key "redisworld" 复制代码
1.2.2. 字符串长度
strlen key
比如说,当前值为 redisworld
,所以返回值为 10
:
127.0.0.1:6379> get key "redisworld" 127.0.0.1:6379> strlen key (integer) 10 复制代码
1.2.3. 设置并返回原值
getset key value
getset
和 set
一样会 设置值 ,但是不同的是,它同时会返回 键原来的值 ,例如:
127.0.0.1:6379> getset hello world (nil) 127.0.0.1:6379> getset hello redis "world" 复制代码
1.2.4. 设置指定位置的字符
setrange key offeset value
下面操作将值由 pest
变为了 best
:
127.0.0.1:6379> set redis pest OK 127.0.0.1:6379> setrange redis 0 b (integer) 4 127.0.0.1:6379> get redis "best" 复制代码
1.2.5. 获取部分字符串
getrange key start end
start
和 end
分别是 开始 和 结束 的 偏移量 , 偏移量 从 0
开始计算,例如获取值 best
的 前两个字符 的命令如下:
127.0.0.1:6379> getrange redis 0 1 "be" 复制代码
最后给出 字符串 类型命令的 时间复杂度 说明:
2. 内部编码
字符串类型的 内部编码 有 3
种:
-
int:
8
个字节的 长整型 。 -
embstr: 小于等于
39
个字节的字符串。 -
raw: 大于
39
个字节的字符串。
Redis
会根据当前值的 类型 和 长度 决定使用哪种 内部编码实现 。
- 整数类型
127.0.0.1:6379> set key 8653 OK 127.0.0.1:6379> object encoding key "int" 复制代码
- 短字符串
#小于等于39个字节的字符串:embstr 127.0.0.1:6379> set key "hello,world" OK 127.0.0.1:6379> object encoding key "embstr" 复制代码
- 长字符串
#大于39个字节的字符串:raw 127.0.0.1:6379> set key "one string greater than 39 byte........." OK 127.0.0.1:6379> object encoding key "raw" 127.0.0.1:6379> strlen key (integer) 40 复制代码
3. 典型使用场景
3.1. 缓存功能
下面是一种比较典型的 缓存 使用场景,其中 Redis
作为 缓存层 , MySQL
作为 存储层 ,绝大部分请求的数据都是从 Redis
中获取。由于 Redis
具有支撑 高并发 的特性,所以缓存通常能起到 加速读写 和 降低后端压力 的作用。
整个功能的伪代码如下:
public UserInfo getUserInfo(long id) { String userRedisKey = "user:info:" + id; String value = redis.get(userRedisKey); UserInfo userInfo; if (value != null) { userInfo = deserialize(value); } else { userInfo = mysql.get(id); if (userInfo != null) { redis.setex(userRedisKey, 3600, serialize(userInfo)); } return userInfo; } } 复制代码
3.2. 计数
许多应用都会使用 Redis
作为 计数 的基础工具,它可以实现 快速计数 、 查询缓存 的功能,同时数据可以 异步落地 到其他 数据源 。一般来说,视频播放数系统,就是使用 Redis
作为 视频播放数计数 的基础组件,用户每播放一次视频,相应的视频播放数就会自增 1
。
public long incrVideoCounter (long id) { String key = "video:playCount:" + id; return redis.incr(key); } 复制代码
实际上,一个真实的 计数系统 要考虑的问题会很多: 防作弊 、按照 不同维度 计数, 数据持久化 到 底层数据源 等。
3.3. 共享Session
一个 分布式 Web
服务将用户的 Session
信息(例如 用户登录信息 )保存在 各自 的服务器中。这样会造成一个问题,出于 负载均衡 的考虑, 分布式服务 会将用户的访问 均衡 到不同服务器上,用户 刷新一次访问 可能会发现需要 重新登录 ,这个问题是用户无法容忍的。
为了解决这个问题,可以使用 Redis
将用户的 Session
进行 集中管理 。在这种模式下,只要保证 Redis
是 高可用 和 扩展性的 ,每次用户 更新 或者 查询 登录信息都直接从 Redis
中集中获取。
3.4. 限速
很多应用出于安全的考虑,会在每次进行登录时,让用户输入 手机验证码 ,从而确定是否是用户本人。但是为了 短信接口 不被 频繁访问 ,会 限制 用户每分钟获取 验证码 的频率。例如一分钟不能超过 5
次,如图所示:
此功能可以使用 Redis
来实现,伪代码如下:
String phoneNum = "138xxxxxxxx"; String key = "shortMsg:limit:" + phoneNum; // SET key value EX 60 NX boolean isExists = redis.set(key, 1, "EX 60", "NX"); if (isExists != null || redis.incr(key) <= 5) { // 通过 } else { // 限速 } 复制代码
上述就是利用 Redis
实现了 限速功能 ,例如 一些网站 限制一个 IP
地址不能在 一秒钟之内 访问超过 n
次也可以采用 类似 的思路。
小结
本文简单的介绍了 Redis
的 字符串数据结构 的 基本命令 , 内部编码 和 相关应用场景 。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【C++11】字符串与常用数据结构
- 动画学数据结构:轻松掌握数组和字符串
- 数据结构 2 字符串 数组、二叉树以及二叉树的遍历
- 查找一个字符串中最长不含重复字符的子字符串,计算该最长子字符串的长度
- (三)C语言之字符串与字符串函数
- 算法笔记字符串处理问题H:编排字符串(2064)
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。