泉州城乡住房建设厅网站,wordpress插件销售,wordpress jq,网页制作教程教案文章目录 一、String字符串简介二、常见命令setgetmgetmsetsetnxincrincrbydecrdecrbyincrbyfloatappendgetrangesetrangestrlen 三、命令小结四、字符串内部编码五、String典型使用场景1. 缓存(Cache)功能2. 计数功能3. 共享会话#xff08;Session#xff09;4. 手机验证码… 文章目录 一、String字符串简介二、常见命令setgetmgetmsetsetnxincrincrbydecrdecrbyincrbyfloatappendgetrangesetrangestrlen 三、命令小结四、字符串内部编码五、String典型使用场景1. 缓存(Cache)功能2. 计数功能3. 共享会话Session4. 手机验证码 一、String字符串简介
字符串类型是 Redis 最基础的数据类型关于字符串需要特别注意: 首先 Redis 中所有的键的类型都是字符串类型而且其他几种数据结构也都是在字符串类似基础上构建的例如列表和集合的元素类型是字符串类型所以字符串类型能为其他4种数据结构的学习奠定基础。 其次如图 2-7所示字符串类型的值实际可以是字符串包含一般格式的字符串或者类似 JSON、XML格式的字符串;数字可以是整型或者浮点型;甚至是二进制流数据例如图片、音频、视频等。不过一个字符串的最大值不能超过 512 MB。
由于 Redis 内部存储字符串完全是按照二进制流的形式保存的所以 Redis 是不处理字符集编码问题的客户端传入的命令中使用的是什么字符集编码就存储什么字符集编码。 二、常见命令
set
SET
将 string 类型的 value 设置到 key 中。如果 key之前存在则覆盖无论原来的数据类型是什么。之前关于此 key 的 TTL 也全部失效。语法:
SET key value [expiration EX seconds|PX milliseconds] [NX|XX]命令有效版本:1.0.0 之后 时间复杂度:0(1) 选项: SET 命令支持多种选项来影响它的行为:EX seconds–使用秒作为单位设置 key 的过期时间。PX milliseconds–使用毫秒作为单位设置 key 的过期时间。NX-- 只在 key不存在时才进行设置即如果 key 之前已经存在设置不执行。XX-- 只在 key 存在时才进行设置即如果 key 之前不存在设置不执行。 注意:由于带选项的 SET命令可以被 SETNX、SETEX、PSETEX 等命令代替所以之后的版本中Redis 可能进行合并。 返回值: 如果设置成功返回 OK。如果由于 SET指定了 NX或者 XX但条件不满足SET不会执行并返回(nil)。 示例: get
GET
获取 key 对应的 value。如果 key 不存在返回nil。如果value的数据类型不是string会报错。语法
get key时间复杂度O(1)返回值key对应的value或者nil当key不存在。示例
mget
MGET
一次性获取多个 key 的值。如果对应的 key不存在或者对应的数据类型不是 string返回 nil。语法:
MGET key [key ...]命令有效版本:1.0.0 之后 时间复杂度: O(N)N 是 key数量 返回值: 对应 value 的列表 示例 mset
MSET
一次性设置多个 key 的值。语法:
MSET key value [key value ...]命令有效版本:1.0.1之后时间复杂度: O(N)N 是 key 数量返回值: 永远是 OK示例 多次get对比单次mget 如图2-8 所示使用 mget / mset 由于可以有效减少网络时间所以性能相较更高。假设网络耗时1毫秒命令执行时间耗时0.1毫秒则执行时间如表 2-2 所示。 以下是将您提供的信息整理成表格的形式
操作次数耗时毫秒计算方式get100011001000 * 1 1000 * 0.1mget11011 * 1 1000 * 0.1
学会使用批量操作可以有效提高业务处理效率但是要注意每次批量操作所发送的键的数量也不是无节制的否则可能造成单⼀命令执行时间过长导致Redis阻塞。
setnx
SETNX
设置 key-value 但只允许在 key 之前不存在的情况下。语法:
SETNX key value命令有效版本:1.0.0 之后时间复杂度: O(1)返回值: 1表示设置成功。0 表示没有设置。示例: SET、SET NX、SET XX 执行流程 incr
INCR
将 key 对应的 string表示的数字加一。如果 key不存在则视为 key对应的 value 是 0。如果 key对应的 string 不是一个整型或者范围超过了 64 位有符号整型则报错。语法:
INCR key命令有效版本: 1.0.0 之后时间复杂度:0(1)返回值: integer类型的加完后的数值。示例: incrby
INCRBY
将 key 对应的 string表示的数字加上对应的值。如果 key不存在则视为 key 对应的 value是 0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型则报错。语法:
INCRBY key decrement命令有效版本:1.0.0 之后时间复杂度: 0(1)返回值: integer类型的加完后的数值。示例: decr
DECR
将 key 对应的 string表示的数字减一。如果 key 不存在则视为 key对应的 value 是 0。如果 key对应的 string 不是一个整型或者范围超过了 64 位有符号整型则报错。语法:
DECR key命令有效版本:1.0.0 之后时间复杂度: 0(1)返回值: integer类型的减完后的数值示例: decrby
DECYBY
将 key 对应的 string表示的数字减去对应的值。如果 key不存在则视为 key 对应的 value是0。如果 key 对应的 string 不是一个整型或者范围超过了 64 位有符号整型则报错。语法:
DECRBY key decrement命令有效版本:1.0.0之后时间复杂度: 0(1)返回值: integer 类型的减完后的数值。示例:
incrbyfloat
INCRBYFLOAT
将 key 对应的 string 表示的浮点数加上对应的值。如果对应的值是负数则视为减去对应的值。如果key 不存在则视为 key 对应的 value 是 0。如果 key 对应的不是 string或者不是一个浮点数则报错。允许采用科学计数法表示浮点数。语法:
INCRBYFLOAT key increment命令有效版本:2.6.0 之后时间复杂度: 0(1)返回值: 加/减完后的数值。示例: append
APPEND
如果 key 已经存在并且是一个 string命令会将 value 追加到原有 string 的后边。如果 key 不存在则效果等同于 SET 命令。语法:
APPEND KEY VALUE命令有效版本:2.0.0 之后时间复杂度: 0(1).追加的字符串一般长度较短,可以视为 O(1)返回值: 追加完成之后 string 的长度。示例 getrange
GETRANGE
返回 key对应的 string的子串由 start和 end确定(左闭右闭)。可以使用负数表示倒数。-1代表倒数第一个字符-2 代表倒数第二个其他的与此类似。超过范围的偏移量会根据 string的长度调整成正确的值字符串下标从0开始。语法:
GETRANGE key start end命令有效版本:2.4.0 之后时间复杂度: O(N).N 为[start,end]区间的长度.由于 string 通常比较短,可以视为是 O(1)返回值: string类型的子串示例: setrange
SETRANGE
覆盖字符串的一部分从指定的偏移开始。偏移量超过字符个数填充的时候以\00填充语法:
SETRANGE key offset value命令有效版本:2.2.0 之后时间复杂度: O(N),N 为 value 的长度,由于一般给的 value 比较短,通常视为 O(1).返回值: 替换后的 string 的长度。示例: strlen
STRLEN
获取 key 对应的 string 的长度。当 key 存放的类似不是 string 时报错。语法:
STRLEN key命令有效版本:2.2.0 之后时间复杂度: 0(1)返回值: string的长度。或者当 key不存在时返回 0。示例: 三、命令小结
命令执行效果时间复杂度set key value [key value…]设置 key 的值是 valueO(k), k 是键个数get key获取 key 的值O(1)del key [key …]删除指定的 keyO(k), k 是键个数mset key value [key value …]批量设置指定的 key 和 valueO(k), k 是键个数mget key [key …]批量获取 key 的值O(k), k 是键个数incr key指定的 key 的值 1O(1)decr key指定的 key 的值 -1O(1)incrby key n指定的 key 的值 nO(1)decrby key n指定的 key 的值 -nO(1)incrbyfloat key n指定的 key 的值 n浮点数O(1)append key value指定的 key 的值追加 valueO(1)strlen key获取指定 key 的值的长度O(1)setrange key offset value覆盖指定 key 的从 offset 开始的部分值O(n)n 是字符串长度, 通常视为 O(1)getrange key start end获取指定 key 的从 start 到 end 的部分值O(n)n 是字符串长度, 通常视为 O(1)
四、字符串内部编码
字符串类型的内部编码有3种:
int:8个字节的长整型。embstr:小于等于 39 个字节的字符串。raw:大于 39 个字节的字符串。
Redis 会根据当前值的类型和长度动态决定使用哪种内部编码实现。 整型类型示例如下:
短字符串示例如下
长字符串示例如下
五、String典型使用场景
1. 缓存(Cache)功能
图 2-10 是比较典型的缓存使用场景其中 Redis 作为缓冲层MySQL作为存储层绝大部分请求的数据都是从 Redis 中获取。由于 Redis 具有支撑高并发的特性所以缓存通常能起到加速读写和降低后端压力的作用。
图 2-10 RedisMySQL 组成的缓存存储架构 下面的伪代码模拟了上图业务数据访问过程
业务是根据用户 uid 获取用户信息
UserInfo getUserInfo(long uid) {...
}首先从 Redis 获取用户信息我们假设用户信息保存在 “user:info:” 对应的键中
// 根据 uid 得到 Redis 的键
String key user:info: uid;
// 尝试从 Redis 中获取对应的值
String value Redis 执⾏命令get key;
// 如果缓存命中hit
if (value ! null) {
// 假设我们的⽤⼾信息按照 JSON 格式存储
UserInfo userInfo JSON 反序列化(value);
return userInfo;
}如果没有从 Redis 中得到用户信息及缓存 miss则进⼀步从 MySQL 中获取对应的信息随后写入缓存并返回
// 如果缓存未命中miss
if (value null) {
// 从数据库中根据 uid 获取⽤⼾信息
UserInfo userInfo MySQL 执⾏ SQLselect * from user_info where uid uid// 如果表中没有 uid 对应的⽤⼾信息
if (userInfo null) {
//响应 404
return null;
}// 将⽤⼾信息序列化成 JSON 格式
String value JSON 序列化(userInfo);// 写⼊缓存为了防⽌数据腐烂rot设置过期时间为 1 ⼩时3600 秒
Redis 执⾏命令set key value ex 3600// 返回⽤⼾信息
return userInfo;
}通过增加缓存功能在理想情况下每个用户信息一个小时期间只会有一次 MySQL查询极大地提升了查询效率也降低了 MySOL的访问数。 与 MVSOL等关系型数据库不同的是Redis 没有表、字段这种命名空间而且也没有对键名有强制要求(除了不能使用一些特殊字符)。但设计合理的键名有利于防止键冲突和项目的可维护性比较推荐的方式是使用业务名:对象名:唯一标识:属性作为键名。例如MySOL的数据库名为 vs用户表名为 user info那么对应的键可以使用vs:user_info:6379、“vs:user_info:6379:name来表示如果当前 Redis 只会被一个业务使用可以省略业务名vs:”。如果键名过程则可以使用团队内部都认同的缩写替代例如 user:6379:friends:messages:5217可以被u:6379m:5217代替。毕竟键名过长还是会导致 Redis 的性能明显下降的。 2. 计数功能
许多应用都会使用 Redis 作为计数的基础工具它可以实现快速计数、查询缓存的功能同时数据可以异步处理或者落地到其他数据源。如图 2-11所示例如视频网站的视频播放次数可以使用Redis 来完成:用户每播放一次视频相应的视频播放数就会自增 1。
// 在 Redis 中统计某视频的播放次数
long incrVideoCounter(long vid) {key video: vid;long count Redis 执⾏命令incr keyreturn counter;
}实际中要开发⼀个成熟、稳定的真实计数系统要⾯临的挑战远不止如此简单防作弊、按照不同维度计数、避免单点问题、数据持久化到底层数据源等。
3. 共享会话Session
如图 2-12 所示一个分布式 Web 服务将用户的 Session 信息(例如用户登录信息)保存在各自的服务器中但这样会造成一个问题:出于负载均衡的考虑分布式服务会将用户的访问请求均衡到不同的服务器上并且通常无法保证用户每次请求都会被均衡到同一台服务器上这样当用户刷新一次访问是可能会发现需要重新登录这个问题是用户无法容忍的。 为了解决这个问题可以使用 Redis 将用户的 Session 信息进行集中管理如图 2-13所示在这种模式下只要保证 Redis 是高可用和可扩展性的无论用户被均衡到哪台 Web 服务器上都集中从Redis 中查询、更新 Session 信息。
4. 手机验证码
很多应用出于安全考虑会在每次进行登录时让用户输入手机号并且配合给手机发送验证码然后让用户再次输入收到的验证码并进行验证从而确定是否是用户本人。为了短信接口不会频繁访问会限制用户每分钟获取验证码的频率例如一分钟不能超过5次如图2-14所示。 此功能可以用以下伪代码说明基本实现思路
String 发送验证码(phoneNumber) {key shortMsg:limit: phoneNumber;// 设置过期时间为 1 分钟60 秒// 使⽤ NX只在不存在 key 时才能设置成功bool r Redis 执⾏命令set key 1 ex 60 nxif (r false) {// 说明之前设置过该⼿机的验证码了long c Redis 执⾏命令incr keyif (c 5) {// 说明超过了⼀分钟 5 次的限制了// 限制发送return null;}}// 说明要么之前没有设置过⼿机的验证码要么次数没有超过 5 次String validationCode ⽣成随机的 6 位数的验证码();validationKey validation: phoneNumber;// 验证码 5 分钟300 秒内有效Redis 执⾏命令set validationKey validationCode ex 300;// 返回验证码随后通过⼿机短信发送给⽤⼾return validationCode;
}
// 验证⽤⼾输⼊的验证码是否正确
bool 验证验证码(phoneNumber, validationCode) {validationKey validation: phoneNumber;String value Redis 执⾏命令get validationKey;if (value null) {// 说明没有这个⼿机的验证码记录验证失败return false;}if (value validationCode) {return true;}else {return false;}
}