Redis:08---字符串对象

一、字符串对象概述

  • 字符串类型是Redis最基础的数据结构。首先键都是字符串类型,而且其他几种数据结构都是在字符串类型基础上构建的,所以字符串类型能为其他四种数据结构的学习奠定基础

  • 字符串就是一个由字节组成的序列

  • 如下图所示,字符串类型的值实际可以是:

    • 字符串(简单的字符串、复杂的字符串(例如JSON、XML))

    • 数字 (整数、浮点数)

    • 二进制(图片、音频、视频),但是值最大不能超过512MB

二、命令

设置值(SET、SETEX、SETNX)

  • set:设置值。参数如下:

    • ex seconds:为键设置秒级过期时间

    • px milliseconds:为键设置毫秒级过期时间

    • nx:键必须不存在,才可以设置成功,用于添加

    • xx:与nx相反,键必须存在,才可以设置成功,用于更新

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

  • setex、setnx:它们的作用和set命令的ex和nx选项是一样的

    • setex:设置键的时候同时设置过期时间

    • setnx:键必须不存在,才可以设置成功,否则出错

setex key seconds value
setnx key value

  • setnx和setxx在实际使用中有什么应用场景吗?

    • 以setnx命令为例子,由于 Redis的单线程命令处理机制,如果有多个客户端同时执行setnx key value, 根据setnx的特性只有一个客户端能设置成功,setnx可以作为分布式锁的一种实现方案,Redis官方给出了使用setnx实现分布式锁的方法:http://redis.io/topics/distlock

获取值(GET)

get key
  • 如果要获取的键不存在,则返回nil(空)

批量设置值(MSET)

mset key value [key value ...]
  • 例如下面依次设置4个键值对:

批量获取值(MGET)

  • 如果有些键不存在,那么它的值为nil(空)

mget key [key ...]
  • 例如下面获取键为a、b、c、d、e的值,其中e键不存在

批量操作的好处

  • 批量操作命令可以有效提高开发效率,假如没有mget这样的命令,要执行n次get命令需要耗时如下:

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

  • 使用mget命令后,要执行n次get命令操作只需要耗时:

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

  • Redis可以支撑每秒数万的读写操作,但是这指的是Redis服务端的处理能力,对于客户端来说,一次命令除了命令时间还是有网络时间,假设网络时间为1毫秒,命令时间为0.1毫秒(按照每秒处理1万条命令算),那么执行1000次get命令和1次mget命令的区别如下图所示,因为Redis的处理能力已经足够高,对于开发人员来说,网络可能会成为性能的瓶颈

  • 学会使用批量操作,有助于提高业务处理效率,但是要注意的是每次批 量操作所发送的命令数不是无节制的,如果数量过多可能造成Redis阻塞或 者网络拥塞。

字符串的自增命令和自减命令:

命令用例和描述
INCRINCR key-name 将键存储的值加上l
DECRDECR key-name 将键存储的值减去Ⅰ
INCRBYINCRBY key-name amount 将键存储的值加上整数amount
DECRBYDECRBY key-name amount 将键存储的值减去整数amount
INCRBYELOAT工NCRBYFLOAT key-name amount 将键存储的值加上浮点数amount,这个命令在Redis 2.6或以上的版本可用

概念:

    • 用户可以通过给定一个任意的数值,对存储着整数或者浮点数的字符串执行自增(increment)、自减操作(decrement)

    • 在需要的时候,Redis还会将整数转换为浮点数

    • 整数的取值范围和系统的长整数(long integer)的取值范围相同(32位系统中就是32位有符号整数;64位系统中就是64位有符号整数)

    • 而浮点数的取值范围和精度则与IEEE 754标准的双精度浮点数(double)相同

  • 返回值:

    • INCR:返回增加后键的值。返回值分为三种:

    • DECR:返回删除后键的值

    • INCRBY:返回增加后键的值

    • DECRBY:返回删除后键的值

    • INCRBYFLOAT:返回增加后键的值

  • 注意事项:

    • 如果对一个不存在的键或者一个保存了空串的键执行自增或者自减操作,那么Redis在执行操作时会将这个键的值作为0来处理

    • 如果所操作的字符串不是一个能被解释为整数或者浮点数的字符串,那么这些命令的操作将返回一个错误

  • 很多存储系统和编程语言内部使用CAS机制实现计数功能,会有一定的CPU开销,但在Redis中完全不存在这个问题,因为Redis是单线程架构,任 何命令到了Redis服务端都要顺序执行

  • 演示案例如下:

     STRLEN:获取字符串长度(备注:中文占3个字节)

strlen key

 

  • GETSET:设置并返回原值。

  • getset和set一样会设置值,但是不同的是,它同时会返回键原来的值

getset key value

  • 下面给出了其他一些演示案例:

  • 注意SETRANGE的用法:

  • 下图是字符串类型命令的时间复杂度:

  • 命令

    时间复杂度

    set key value

    o(l)

    get key

    o(1)

    del key [key ...]

    o(k),k是键的个数

    mset key value [ key value ...]

    O(k),t是键的个致

    mget key [key ...]

    o(),I是键的个致

    incr key

    o1)

    decr key

    o(1)

    incrby key increment

    o(1)

    decrby key decrement

    o(1)

    incrbyfloat key increment

    o(1)

    append key value

    o(1)

    strlen key

    o(1)

    setrange key offset value

    o(1)

    getrange key start end

    oo),n是宁符串长度,由于获取字符串非常快,所以

    如果字符非不是很长,可以视阿为O(1)

三、内部编码

  • 字符串类型的内部编码有3种:

    • int:8个字节的长整型

    • embstr:小于等于39个字节的字符串

    • raw:大于39个字节的字符串

演示说明

  • Redis会根据当前值的类型和长度决定使用哪种内部编码实现

  • 整数类型示例如下:

  • 短字符串示例如下:

  • 长字符串示例如下:

四、典型使用场景

①缓存功能

  • 下图是比较典型的缓存使用场景,其中Redis作为缓存层,MySQL作为存储层,绝大部分请求的数据都是从Redis中获取。由于Redis具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用

  • 下面伪代码模拟了上图的访问过程:

//1.该函数用于获取用户的基础信息UserInfo getUserInfo(long id){...}//2.首先从Redis获取用户信息:// 定义键userRedisKey = "user:info:" + id;// 从Redis获取值value = redis.get(userRedisKey);if (value != null) {// 将值进行反序列化为UserInfo并返回结果userInfo = deserialize(value);return userInfo;}//3.如果没有从Redis获取到用户信息,需要从MySQL中进行获取,并将结果回写到Redis,添加1小时(3600秒)过期时间://从MySQL获取用户信息userInfo = mysql.get(id);// 将userInfo序列化,并存入Redisredis.setex(userRedisKey, 3600, serialize(userInfo));// 返回结果return userInfo
  • 整个功能的伪代码如下:

UserInfo getUserInfo(long id){userRedisKey = "user:info:" + idvalue = 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;}
  • 应用场景1:缓存热门图片

set redis-log.jpg redis-log-data
  • 应用场景2:存储文章。当用户想在博客中撰写一篇新文章的时候,程序就需要把文章的标题、内容、作者、发表时间等多 项信息存储起来,并在用户阅读文章的时候取出来这些信息。可以使用 mset mget msetnx 命令来进行

  • 开发提示:

    • 与MySQL等关系型数据库不同的是,Redis没有命令空间,而且也没有对键名有强制要求(除了不能使用一些特殊字符)

    • 但设计合理的键名,有利于防止键冲突和项目的可维护性,比较推荐的方式是使用“业务名:对象 名:id:[属性]”作为键名(也可以不是分号)

    • 例如MySQL的数据库名为 vs,用户表名为user,那么对应的键可以用"vs:user:1","vs:user:1:name"来表示,如果当前Redis只被一个业务使用,甚至可以去掉“vs:”。如 果键名比较长,例如“user:{uid}:friends:messages:{mid}”,可以在能描 述键含义的前提下适当减少键的长度,例如变为“u:{uid}:fr:m:{mid}”,从而减少由于键过长的内存浪费

②计数

  • 许多应用都会使用Redis作为计数的基础工具,它可以实现快速计数、 查询缓存的功能,同时数据可以异步落地到其他数据源

  • 应用场景1:文章长度计数功能、文章摘要、文章计数

    • 文章长度:STRLEN article:10086:content

    • 文章摘要:GETRANGE article:10086:content 0 5

    • 文章阅读计数:INCRBY article:10086:count

  • 应用场景2:例如笔者所在团队的视频播放数系统就是使用Redis作为视频播放数计数的基础组件,用户每播放一次视频,相应的视频播放数就会自增1。代码如下所示

long incrVideoCounter(long id) {
key = "video:playCount:" + id;
return redis.incr(key);
}
  • 开发提示:实际上一个真实的计数系统要考虑的问题会很多:防作弊、按照不同维度计数,数据持久化到底层数据源等

③共享Session

  • 如下图所示,一个分布式Web服务将用户的Session信息(例如用户登录信息)保存在各自服务器中,这样会造成一个问题,出于负载均衡的考虑,分布式服务会将用户的访问均衡到不同服务器上,用户刷新一次访问可能会发现需要重新登录,这个问题是用户无法容忍的

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

④限速器

  • 应用场景1:很多应用出于安全的考虑,会在每次进行登录时,让用户输入手机验证 码,从而确定是否是用户本人。但是为了短信接口不被频繁访问,会限制用 户每分钟获取验证码的频率,例如一分钟不能超过5次,如下图所示

  • 此功能可以使用Redis来实现,下面的伪代码给出了基本实现思路:

phoneNum = "138xxxxxxxx";key = "shortMsg:limit:" + phoneNum;//SET key value EX 60 NXisExists = redis.set(key,1,"EX 60","NX");if(isExists != null || redis.incr(key) <=5){// 通过}else{// 限速}
  • 应用场景2:防止用户的账号遭到暴力破解,如果同个账号连续好几次输入错误的密码,则限制账号的登录,只 能等 30 分钟后再次登录,比如设置 3 次

    • 1)SET max:execute:times 3

    • 2)密码出错时 DECR max:execute:times

    • 3)当 max:execute:times 的值小于 0 时则禁止登录,并可以设置 SETEX login:error:darren 1800 "Incorrect password",然后使用 TTL login:error:darren 1800 检测对应剩余的时间

  • 应用场景3:例如一些网站为了防止网页内容被网络爬虫疯狂抓取,限制一个IP地址在固定的时间段内能够访问的页面数量.

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

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

相关文章

(十八)深入浅出TCPIP之epoll的一些思考

Epoll基本介绍在linux的网络编程中&#xff0c;很长的时间都在使用select来做事件触发。在linux新的内核中&#xff0c;有了一种替换它的机制&#xff0c;就是epoll。相比于 select&#xff0c;epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。因为在内核中的select…

C++:16---强制类型转换和类型转换

旧式的强制类型转换 在早期C/C++中,显式地进行强制类型的转换有以下两种形式:type (expr) ; //函数形式的强制类型转换(type) expr; //C语言风格的强制类型转换比如: char c = 12; int b = (int)c; float f = float(b); C++的新式强制类型转换…

Nginx不停机优雅升级

最近线上运行的游戏越来越多,云服务商也给我推送提示系统升级,漏洞补丁升级,也有nginx更新的。 有一些比较关键性的系统补丁需要立即更新处理,有一些可以换一换不用升级,但此nginx升级的需求比较迫切,但更新可能需要重启nginx。 这将会影响到我们这样的一个登录业务逻辑…

leetcode186. 翻转字符串里的单词 II

给定一个字符串&#xff0c;逐个翻转字符串中的每个单词。 示例&#xff1a; 输入: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l…

Nginx大规模并发原理

Nginx在主流硬件上的并发数为十万,网络处理方面的领先地位,归功于突破性的事件驱动架构。 Nginx在每颗内核上创建一个工作进程,有效利用硬件资源。 在单个工作进程中交替处理多个连接,应对突如其来的网络流量。 Nginx资源管理 Nginx使用状态机管理流量。 非阻塞事件…

Nginx 配置TCP负载均衡

Nginx从1.9.0版本开始,新增加了一个stream模块,用来实现四层协议的转发、代理或者负载均衡等鉴于Nginx在负载均衡和web service上的成功,和Nginx良好的框架,stream模块前景一片光明。 Nginx的stream模块默认不会自带安装,需要编译安装的时候手动添加上这个模块,不过我的系…

leetcode162. 寻找峰值 变种二分见过吗

峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums&#xff0c;其中 nums[i] ≠ nums[i1]&#xff0c;找到峰值元素并返回其索引。 数组可能包含多个峰值&#xff0c;在这种情况下&#xff0c;返回任何一个峰值所在位置即可。 你可以假设 nums[-1] nums[n] -…

(十九)TCPIP面试宝典-进入大厂必备总结(上)

TCP 作为传输层的协议,是一个IT工程师素养的体现,也是面试中经常被问到的知识点。在此,我将 TCP 核心的一些问题梳理了一下,希望能帮到各位。 实际上这篇文章相当于是复习之前的网络基础部分。只不过这篇文章的提问方式更灵活,也是让读者们懂得变通,更熟悉TCP。 TCP 和 U…

C++:17---sizeof运算符

功能:以字节位单位,返回一个表达式或一个数据类型所占的字节数返回值类型:是size_t类型sizeof有无括号:sizeof不加括号,后面不可以直接跟数据类型sizeof加括号,后面既可以跟表达式也可以跟数据类型注意事项对引用类型执行sizeof运算得到被引用对象所占空间的大小对指针执…

Redis:10---List对象

一、列表对象概述列表类型是用来存储多个有序的字符串&#xff0c;一个列表最多可以存储多个元素。列表是一种比较灵活的数据结构&#xff0c;它可以充当栈和队列的角色&#xff0c;在实际开发上有很多应用场景特点&#xff1a;一个列表可以存储多个字符串&#xff0c;相同元素…

Redis:09---Hash对象

一、哈希对象简介几乎所有的编程语言都提供了哈希&#xff08;hash&#xff09;类型&#xff0c;它们的叫法可能是哈希、字典、关联数组哈希又称散列在Redis中&#xff0c;哈希类型是指键值本身又是一个键值对结构&#xff0c;形如value{{field1&#xff0c;value1}&#xff0c…

leetcode329. 矩阵中的最长递增路径

给定一个整数矩阵&#xff0c;找出最长递增路径的长度。 对于每个单元格&#xff0c;你可以往上&#xff0c;下&#xff0c;左&#xff0c;右四个方向移动。 你不能在对角线方向上移动或移动到边界外&#xff08;即不允许环绕&#xff09;。 示例 1: 输入: nums [ [9,9,…

Query Ajax 实例 ($.ajax、$.post、$.get)

Jquery在异步提交方面封装的很好&#xff0c;直接用AJAX非常麻烦&#xff0c;Jquery大大简化了我们的操作&#xff0c;不用考虑浏览器的诧异了。 推荐一篇不错的jQuery Ajax 实例文章&#xff0c;忘记了可以去看看&#xff0c;地址为&#xff1a;http://www.cnblogs.com/yeer/a…

C++:18---const关键字(附常量指针、指针常量、常量指针常量)

一、const变量的一些基本特点 ①const修饰的变量不能被修改const int a=10; a=20;//错误②因为const修饰的变量不能被修改,所以必须被初始化int a=10; const int b=a; //正确 const int c=10; //正确③const修饰的变量可以赋值给其他值const int a=10; int b=a;//正确④可以有…

leetcode330. 按要求补齐数组 顶级难度玄学贪心

给定一个已排序的正整数数组 nums&#xff0c;和一个正整数 n 。从 [1, n] 区间内选取任意个数字补充到 nums 中&#xff0c;使得 [1, n] 区间内的任何数字都可以用 nums 中某几个数字的和来表示。请输出满足上述要求的最少需要补充的数字个数。 示例 1: 输入: nums [1,3], …

(二十)TCPIP面试宝典-进入大厂必备总结(中)

TCP 作为传输层的协议,是一个IT工程师素养的体现,也是面试中经常被问到的知识点。在此,我将 TCP 核心的一些问题梳理了一下,希望能帮到各位。 实际上这篇文章相当于是复习之前的网络基础部分。只不过这篇文章的提问方式更灵活,也是让读者们懂得变通,更熟悉TCP。 前两篇文…

(二十一)TCPIP面试宝典-进入大厂必备总结(下)

TCP 作为传输层的协议,是一个IT工程师素养的体现,也是面试中经常被问到的知识点。在此,我将 TCP 核心的一些问题梳理了一下,希望能帮到各位。 实际上这篇文章相当于是复习之前的网络基础部分。只不过这篇文章的提问方式更灵活,也是让读者们懂得变通,更熟悉TCP。 上一篇文…

C:03---运算符优先级

二话不说先看运算符的优先级表: 一、逗号运算符 格式:整个逗号表达式的值返回的结果是最后一个表达式的值使用起来,最好加上括号来返回最后一个表达式的值。否则逗号表达式的意义将失效(见下面演示案例)(表达式1, 表达式2, 表达式3....); #include <stdio.h> int ma…

(二十二)深入浅出TCPIP之实战篇—用c++开发一个http服务器

在当前的网络编程专栏前十几篇文章里&#xff0c;我已经说明了TCPIP常用的一些原理&#xff0c;那么接下来我将逐步进入到实战编程阶段&#xff1a;本篇文章我将带大家用C做一个http服务器。既然想实现一个http服务器&#xff0c;首先必须要熟悉的就是http协议知识&#xff0c;…

leetcode161. 相隔为 1 的编辑距离

给定两个字符串 s 和 t&#xff0c;判断他们的编辑距离是否为 1。 注意&#xff1a; 满足编辑距离等于 1 有三种可能的情形&#xff1a; 往 s 中插入一个字符得到 t 从 s 中删除一个字符得到 t 在 s 中替换一个字符得到 t 示例 1&#xff1a; 输入: s "ab", t …