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

前言

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

其他文章

  • 深入剖析Redis系列(一) - Redis入门简介与主从搭建

  • 深入剖析Redis系列(二) - Redis哨兵模式与高可用集群

  • 深入剖析Redis系列(三) - Redis集群模式搭建与原理详解

  • 深入剖析Redis系列(四) - Redis数据结构与全局命令概述

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

  • 深入剖析Redis系列(六) - Redis数据结构之哈希

  • 深入剖析Redis系列(七) - Redis数据结构之列表

  • 深入剖析Redis系列(八) - 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次命令时间

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

参考

《Redis 开发与运维》


欢迎关注技术公众号: 零壹技术栈

本帐号将持续分享后端技术干货,包括虚拟机基础,多线程编程,高性能框架,异步、缓存和消息中间件,分布式和微服务,架构学习和进阶等学习资料和文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.tpcf.cn/news/281944.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全新升级的AOP框架Dora.Interception[6]: 框架设计和实现原理

本系列前面的五篇文章主要介绍Dora.Interception的编程模式以及对它的扩展定制&#xff0c;现在我们来聊聊它的设计和实现原理。目录一、调用链抽象二、基于约定的拦截器定义三、基于调用上下文的依赖注入容器四、拦截器的提供五、调用链的构建六、方法拦截的实现原理七、依赖注…

activemq 安全连接

一、定义用户组1.1 simpleAuthenticationPlugin通过在activemq.xml中配置用户组<plugins> <simpleAuthenticationPlugin> <users> <authenticationUser username"admin" password"password" groups"admins,publishers,consumer…

React Native在Android当中实践(五)——常见问题

React Native在Android当中实践&#xff08;一&#xff09;——背景介绍 React Native在Android当中实践&#xff08;二&#xff09;——搭建开发环境 React Native在Android当中实践&#xff08;三&#xff09;——集成到Android项目当中 React Native在Android当中实践&#…

完成登录与注册页面的前端

完成登录与注册页面的HTMLCSSJS&#xff0c;其中的输入项检查包括&#xff1a; 用户名6-12位 首字母不能是数字 只能包含字母和数字 密码6-12位 注册页两次密码是否一致 JS&#xff1a; function fnLogin() {var uSer document.getElementById("user");var pAss do…

mysql505复位密码_mysql5 如何复位根用户密码[官方文档]

如何复位根用户密码如果你从未为MySQL设置根用户密码&#xff0c;服务器在以根用户身份进行连接时不需要密码。但是&#xff0c;建议你为每个账户设置密码如果你以前设置了根用户密码&#xff0c;但却忘记了该密码&#xff0c;可设置新的密码。下述步骤是针对Windows平台的。在…

WPF效果第二百零一篇之实现合并单元格

早一段时间又一次出差青海省西宁市;回来又是总结又是各种琐事,也没顾得上去分享点东西;大周末的就在家分享一下,这二天再次基于ListBox实现的合并单元格的效果:1、ListBox嵌套ListBox的前台布局:<ListBox ItemsSource"{Binding LCPListData}" x:Name"Manufac…

转载 maven 详解 http://www.cnblogs.com/binyue/p/4729134.html

--声明规范 <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!--声…

ASP.NET Core中使用EasyCaching作为缓存抽象层

简介做后端开发&#xff0c;缓存应该是天天在用&#xff0c;很多时候我们的做法是写个帮助类&#xff0c;然后用到的时候调用一下。这种只适合简单层次的应用&#xff1b;一旦涉及到接口实现调整之类的&#xff0c;这种强耦合的做法很不合适。有些其他的功能又要去重复造轮子。…

mysql qps如何查看_mysql状态查看 QPS/TPS/缓存命中率查看

运行中的mysql状态查看对正在运行的mysql进行监控&#xff0c;其中一个方式就是查看mysql运行状态。(1)QPS(每秒Query量)QPS Questions(or Queries) / uptimemysql > show global status like Question%;mysql > show global status like uptime%;(2)TPS(每秒事务量…

visual studio开启多核编译方法

先按http://blog.csdn.net/acaiwlj/article/details/50240625的方法进行了VS多线程的启动。 原本以为按以下步骤设置就OK了&#xff0c;但是编译中无意间发些了一个warning&#xff1a;“/Gm”与多处理不兼容&#xff1b;忽略 /MP 开关&#xff01;&#xff01;&#xff01;&am…

聊聊storm nimbus的LeaderElector

为什么80%的码农都做不了架构师&#xff1f;>>> 序 本文主要研究一下storm nimbus的LeaderElector Nimbus org/apache/storm/daemon/nimbus/Nimbus.java public static void main(String[] args) throws Exception {Utils.setupDefaultUncaughtExceptionHandler();…

Android框架式编程之BufferKnife

BufferKnife作为框架式编程的重要组成部分&#xff0c;使用BufferKnife能够极大的精简View层面的代码量&#xff0c;并为MVP/MVC方式提供辅助。 一、配置 compile com.jakewharton:butterknife:(insert latest version) annotationProcessor com.jakewharton:butterknife-compi…

如果我去深圳,你会见我吗

▲图/ 深圳夜景初次见易小姐&#xff0c;还是21年的春节回老家的时候。想来20年因为疫情没有回家&#xff0c;家母几次三番电话里头表达的思念以及建议一些不靠谱的回家计划&#xff0c;着实有些不忍&#xff0c;确实有似“儿行千里母担忧”之理&#xff0c;索性拿着年假和加班…

CodeForces - 1059D(二分+误差)

链接&#xff1a;CodeForces - 1059D 题意&#xff1a;给出笛卡尔坐标系上 n 个点&#xff0c;求与 x 轴相切且覆盖了所有给出点的圆的最小半径。 题解&#xff1a;二分半径即可。判断&#xff1a;假设当前二分到的半径是 R &#xff0c;因为要和 x 轴相切&#xff0c;所以圆心…

pureref 平移用不了_关于参考图管理神器 PureRef 的一些快捷键

PureRef 的一些快捷键 软件下载&#xff1a;点击这里控制(配合左键)窗口内鼠标左键     框选窗口边鼠标左键     调整窗口大小鼠标中键 或 按住Alt     移动画布鼠标滚轮 或 按住Z     缩放画布按住S     查看目标位置颜色信息(可复制16进制颜色…

Windows 10 版本信息

Windows 10 版本信息 原文 https://technet.microsoft.com/zh-cn/windows/release-info Windows 10 版本信息 Microsoft 已更新其服务模型。 半年频道每年发布两次功能更新&#xff0c;时间大概在 3 月和 9 月&#xff0c;每个版本的服务时间线为 18 个月。 从 Windows 10 版本…

开源轻量的 .NET 监控工具 - 看门狗

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具或组件&#xff0c;希望对您有用&#xff01;简介WatchDog 是一个使用 C# 开发的开源的轻量监控工具&#xff0c;它可以记录和查看 ASP.Net Core Web 和 WebApi 的实时消息、事件、…

python读取oracle数据库性能_用python对oracle进行简单性能测试

一、概述dba在工作中避不开的两个问题&#xff0c;sql使用绑定变量到底会有多少的性能提升&#xff1f;数据库的审计功能如果打开对数据库的性能会产生多大的影响&#xff1f;最近恰好都碰到了&#xff0c;索性做个实验。sql使用绑定变量对性能的影响开通数据库审计功能对性能的…

BZOJ 3231: [Sdoi2008]递归数列 (JZYZOJ 1353) 矩阵快速幂

http://www.lydsy.com/JudgeOnline/problem.php?id3231和斐波那契一个道理在最后加一个求和即可1 #include<cstdio>2 #include<cstring>3 #include<iostream>4 //using namespace std;5 const int maxn10010;6 const double eps1e-8;7 long long modn;8 lon…

马斯克的火箭上天了,SpaceX开源项目也登上了热榜!

python知识手册SpaceX于美国东部时间5月30日下午3&#xff1a;22分将两位美国宇航员送往国际空间站&#xff0c;虽然这只是Demo任务&#xff0c;但SpaceX已经以其卓越工程优势、低廉的发射成本赢得了全球航天产业的信赖。同时也是除美俄中这些航天国家队以外&#xff0c;唯一独…