深入剖析Redis系列(五) - Redis数据结构之字符串

栏目: 数据库 · 发布时间: 8年前

内容简介:字符串类型是除了

字符串类型是 Redis 最基础的数据结构。 字符串类型 的值实际可以是 字符串 ( 简单 和 复杂 的字符串,例如 JSON 、 XML )、 数字 (整数、浮点数),甚至是 二进制 (图片、音频、视频),但是值最大不能超过 512MB 。

深入剖析 <a href='https://www.codercto.com/topics/18994.html'>Redis</a> 系列(五) - Redis数据结构之字符串

正文

1. 相关命令

1.1. 常见命令

1.1.1. 设置值

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

set 命令有几个选项:

  1. ex seconds :为 键 设置 秒级过期时间 。
  2. px milliseconds :为 键 设置 毫秒级过期时间 。
  3. nx :键必须 不存在 ,才可以设置成功,用于 添加 。
  4. 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次命令时间

深入剖析Redis系列(五) - Redis数据结构之字符串

使用 mget 命令后,执行 n 次 get 命令的过程和 耗时 如下:

n次get时间 = 1次网络时间 + n次命令时间

深入剖析Redis系列(五) - Redis数据结构之字符串

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"
复制代码

最后给出 字符串 类型命令的 时间复杂度 说明:

深入剖析Redis系列(五) - Redis数据结构之字符串

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 具有支撑 高并发 的特性,所以缓存通常能起到 加速读写 和 降低后端压力 的作用。

深入剖析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系列(五) - Redis数据结构之字符串

为了解决这个问题,可以使用 Redis 将用户的 Session 进行 集中管理 。在这种模式下,只要保证 Redis 是 高可用 和 扩展性的 ,每次用户 更新 或者 查询 登录信息都直接从 Redis 中集中获取。

深入剖析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 的 字符串数据结构 的 基本命令 , 内部编码 和 相关应用场景 。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

参数化建筑设计

参数化建筑设计

高云河、白云生 / 华中科技大学出版社 / 2016-8-1 / 69.80

《参数化建筑设计》以案例的形式讲解参数化建筑设计的具体方法,其中包含犀牛(Rhino)和Grasshopper的应用。本书不单单是一本计算机软件教材,书中教会读者的是参数化建筑设计的思路,希望通过完成一个个案例使读者融会贯通,在今后的设计工作中能够熟练使用,辅助自身完成建筑设计。全书共有10个案例,循序渐进,由浅入深,几乎涵盖了参数化建筑设计所要使用的所有功能和方法。一起来看看 《参数化建筑设计》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码