文章目录
- 1.redis中的string - 字符串
- 2.string命令讲解
- 2.1set
- 2.1.1flush+all = flushall 即冲洗(删除)所有key value 数据
- 2.2get
- 2.3mset
- 2.4mget
- 2.5setnx setex psetex
- 2.6incr incrby decr decrby incrbyfloat
- 2.7append
- 2.8setrange
- 2.9getrange
- 2.10strlen
- 2.11string命令小结
- 3.string编码方式
- 4.string应用场景
- 4.1缓存功能
- 4.2计数功能
- 4.3共享会话(Session)
- 4.4手机验证码
- 5.string业务
大家好,我是晓星航。今天为大家带来的是 redis中string字符串 相关的讲解!😀
1.redis中的string - 字符串
Redis 中的字符串,直接就是按照二进制数据的方式存储的(不会做任何的编码转换,存的是啥,取出来就还是啥)
不仅仅可以存储文本数据 整数 普通的文本字符串 JSON xml 二进制数据(图片, 视频,音频…)
音频视频 体积可能会比较大
Redis 对于 string 类型,限制了大小最大是 512M
Redis 单线程模型,希望进行的操作都能比较快速
2.string命令讲解
2.1set
语法:
SET key value [expiration EX seconds | PX milliseconds] [NX|XX]
EX 设置 key 过期事件
set key value ex 10
相当于
set key value + expire key 10 两个语句的结合版(redis中使用一个命令操作两个过程可以节省资源,提高效率)
NX
如果 key 不存在,才设置。
如果 key 存在,则不设置(返回 nil)
XX
如果 key 存在,才设置。(相当于更新 key 的value)
如果 key 不存在,则不设置(返回nil)
key已存在,更新key中的value
key不存在,不设置,返回nil
如果 key 不存在, 创建新的键值对
如果 key 存在, 则是让新的 value 覆盖旧的 value.可能会改变原来的数据类型
原来这个 key 的 ttl(生存时间)也会失效
删库操作(类似mysql里的drop database):FLUSHALL
- 可以把 redis 上所有的键值对都带走
2.1.1flush+all = flushall 即冲洗(删除)所有key value 数据
2.2get
语法:
GET key
返回值:key对应的value值
返回key2对应的值123
对于 GET 来说,只是支持,字符串类型的value。如果是 value 是其他类型,使用 GET 获取就会出错!
这里key3本质底层是使用quicklist(快速列表)的类型来排序的。
2.3mset
一次操作多组键值对。
语法:
mset key value [key value ...]
时间复杂度:O(N) N是key数量
返回值:永远是OK
2.4mget
一次操作多组键值对。
语法:
mget key [key ...]
时间复杂度:O(N) N是key数量
返回值:对应的 value 的列表
2.5setnx setex psetex
SETNX(检查原库中是否已经含有key,如果key不存在就设置。存在返回nil不设置。):
可以看到setnx和2.1中讲述的NX命令一样,只不过这里我们将set和nx写在一起了。
NX的含义见上图
SETEX(设置过期时间 单位是秒):
可以看到setex和2.1中讲述的EX命令一样,只不过这里我们将set和ex写在一起了。
EX的含义见上图。
并且这里在我们输入setex命令后,xshell客户端也提示了后面对应要写的信息分别为key键值对,时间,value值
PSETEX(设置过期时间 单位是毫秒):
这里的5000是5000毫秒即5s。查询返回的-2表示此时key3不存在。
并且这里在我们输入setex命令后,xshell客户端也提示了后面对应要写的信息分别为key键值对,时间,value值
针对 set 的一些常见用法,进行了缩写
之所以这样搞,就是为了让操作更符合人的直觉,(使用者的门槛就越低,要背的东西
就越少)
符合人的直觉 编程语言中, 很多的关键词, 都是和自然语言相关的
2.6incr incrby decr decrby incrbyfloat
incr:
针对整数value加1.
整数成功自增1.
只能针对于整数进行加1.(小数,字符都不能操作)
incr 操作的 key 如果不存在,就会把这个 key 的value 当作 0 来使用。
incrby:
针对整数value加n.
整数成功加9(此时n为9).
只能针对于整数进行加n.(小数,字符都不能操作)
incrby 操作的 key 如果不存在,就会把这个 key 的value 当作 0 来使用。
decr:
针对整数value减1.
整数成功自减1.
只能针对于整数进行减1.(小数,字符都不能操作)
decr 操作的 key 如果不存在,就会把这个 key 的value 当作 0 来使用。
decrby:
针对整数value减n.
整数成功自减n.
只能针对于整数进行减n.(小数,字符都不能操作)
decrby 操作的 key 如果不存在,就会把这个 key 的value 当作 0 来使用。
incrbyfloat:
把 key 对应的 value 进行 ±运算.运算的操作数可以是浮点数.
整数成功自加2.5(n此时为2.5).
可以看到我们使用incrbyfloat对key1进行加n操作时,无论是加整数还是加浮点数都是可以实现的。
但是对于字符还是不可以加。
incrbyfloat 操作的 key 如果不存在,就会把这个 key 的value 当作 0 来使用。
注意:我们redis操作中没有decrbyfloat命令,如果想减的话,只能通过使用命令incrbyfloat加上负数的形式来实现。
此时使用的就是incrbyfloat命令来加一个负数实现减法操作。
上述操作的时间复杂度,都是 O(1)
由于 redis 处理命令的时候,是单线程模型,多个客户端同时针对同一个 key 进行 incr 操作,不会引起"线程安全"问题
2.7append
如果 key 已经存在并且是一个string,命令会将 value 追加到原有 string 的后面。如果 key 不存在,则效果等同于 set 命令。
语法:
append key value
时间复杂度:O(1)
返回值:拼接的字符串字节长度。
上图可以看到我们使用append命令将hello后拼接了world,使他变为了helloworld。
如果我们append的key不存在时,那么redis会默认key的value为空直接在上面拼接字符串。
如果我们拼接 “你好” 两个字,我们返回值为6个字节,并且我们用get得到的值为十六进制表示的汉字"你好"。
那么我们想看到key3以汉字 “你好” 的形式展现怎么办呢?
答:退出客户端,然后在启动客户端时后面加上 --raw
即可
退出客户端:ctrl + d
redis-cli --raw
此时我们key3中你好便是用中文字符的形式展现的了。
2.8setrange
语法:
setrange key offset value
这里的offset时偏移量(从第几个字节,开始替换)
这里我们就将key3的value值durant从第1个位置开始替换字符为四个o。
如果我们针对一个不存在的key在1个位置去设置一个偏移量并插入一小段字符串会出现什么效果呢?
凭空生成了一个字节,这个字节里的内容就是 0x00,banananice 就被追加到 0x00 的后面了
setrange 针对 不存在的 key 也是可以操作的.不过会把 offset 之前的内容填充成
0x00
2.9getrange
在c++和Java中叫法:
返回key对应的string的字串,由start和end确定(左闭右闭),即闭区间。可以使用负数表示倒数。0代表第一个字符,1代表第二个字符,-1代表倒数第一个字符,-2代表倒数第二个,其他的与此类似。超过范围的偏移量会根据string的长度调整成正确的值。
语法:
getrange key start end
时间复杂度:O(N)
返回值:string 类型的字串
redis的下标支持负数。
0代表第一个字符,-1代表最后一个字符。
如果此时使用getrange查询汉字会发生什么呢(一个汉字为3个字符)?
如果字符串中保存的是汉字,此时进行子串切分,很可能切出来的就不是完整
的汉字了,上述的代码,是强行切出了中间的四个字节,随便这么一切,切出的结果在 utf8 码表上不知道能査出啥了
2.10strlen
strlen获取字符串长度。单位是字节。
strlen key
时间复杂度:O(1)
返回值:string的长度。当key不存在时,返回0。单位是字节。
这里的key2内容为 “你好”,strlen返回值为6,因此redis中string使用的是utf8编码的。
一个汉字通常是 3 个字节(编码方式是 utf8)
Java 里头咋一个 2 字节的 char 就能表示汉字呢?
2.11string命令小结
3.string编码方式
string有三个编码方式:
1.int 64 位/8字节 的整数
2.embstr 压缩字符串.适用于表示比较短的字符串。
3.raw 普通字符串.适用于表示更长的字符串.只是单纯的持有字节数组
上述的编码方式在图片中可以很好的体现
小数则是使用字符串来存
意味着每次进行算术运算,都需要把字符串转成小数,进行运算,结果再转回字符串保存
4.string应用场景
4.1缓存功能
Redis + Mysql 组成的缓存存储架构
下图是比较典型的缓存使用场景,其中Redis作为缓冲层,MySQL作为存储层,绝大部分请求的数据都是从 Redis 中获取。由于 Redis 具有支撑高并发的特性,所以缓存通常能起到加速读写和降低后端压力的作用。
整体的思路:
应用服务器访问数据的时候,先査询 Redis.如果 Redis 上数据存在了,就直接从 Redis 取数据交给应用服务器,不继续访问数据库了。
如果 Redis 上数据不存在,再读取 MySQL. 把读到的结果,返回给应用服务器。同时,把这个数据也写入到 Redis 中。
刚才上述描述的过程相当于是把最近使用到的数据作为热点数据.(暗含了一层假设: 某个数据一旦被用到了,那么很可能在最近这段时间就被反复用到)
上述策略,存在一个明显的问题:
随着时间的推移,肯定是会有越来越多的 key 在 redis 上访问不到,从而从 mysql 读取并写入 redis 了,此时 redis 中的数据不是就越来越多嘛?
答:1.在把数据写给 redis 的同时,给这个 key 设置一个过期时间。
2.Redis 也在内存不足的时候,提供了 淘汰策略。
4.2计数功能
许多应用都会使用 Redis 作为计数的基础工具,它可以实现快速计数、查询缓存的功能,同时数据可以异步处理或者落地到其他数据源。如图2-11所示,例如视频网站的视频播放次数可以使用Redis 来完成:用户每播放一次视频,相应的视频播放数就会自增 1。
记录视频播放次数:
实际中要开发一个成熟、稳定的真实计数系统,要面临的挑战远不止如此简单:防作弊、按照不同维度计数、避免单点问题、数据持久化到底层数据源等。
4.3共享会话(Session)
Session:在WEB开发中,服务器可以为每个用户浏览器创建一个会话对象(session对象),注意:一个浏览器独占一个session对象(默认情况下)。因此,在需要保存用户数据时,服务器程序可以把用户数据写到用户浏览器独占的session中,当用户使用浏览器访问其它程序时,其它程序可以从用户的session中取出该用户的数据,为用户服务。
Session和Cookie的主要区别:
举个例子:
客户a 去酒店订房间想日后聚餐使用,于是找了 经理a 订房间。但是到了那天之后,经理a 放假了,此时是经理b上班,那么此时 客户a 找 经理b 要房间 经理b 就会去房间 订购本 上查一下是否 客户a 今天订了房间。那么这里的 订购本 就相当于 session。
上图为cookie方式,需要客户端自己本地存储。
这里为session方式,我们将信息传给服务器存储一份,然后以cookie方式返回给客户端。
4.4手机验证码
很多应用出于安全考虑,会在每次进行登录时,让用户输入手机号并且配合给手机发送验证码,然后让用户再次输入收到的验证码并进行验证,从而确定是否是用户本人。为了短信接口不会频繁访问,会限制用户每分钟获取验证码的频率,例如一分钟不能超过5次
1.生成验证码
用户输入一下手机号 点击获取验证码
这里生成验证码我们需要加限制:
1分钟之内,最多获取 5 次验证码 或者 每次获取验证码必须间隔 30 秒
作用:主要是怕用户频繁获取验证码,导致服务器压力过大。
2.检查验证码
把短信收到的验证码这一串数,提交到系统中 系统进行验证验证码是否正确
5.string业务
业务:业务其实就是一个公司/一个产品,是如何解决一个/一系列问题的解决问题的过程,就可以称为是"业务
不同的公司,不同的产品,有不同的业务
不同的业务就需要不同的技术作为支撑
例如12306买火车票的业务:
众所周知我们中国有一个传统的节日-春节
在春节这天,中国各地会有大量的人口移动,因此带来的业务量是非常巨大以及复杂的,虽然在12306刚上线期间引入了非常多的技术用来提高访问速度和可用性。但是在放票的时候,整体的压力还是很大,还是很容易出问题。
之后为了缓解抢票压力过大,于是提出了一个新的方案:分时段放票。
本来是一次放所有票
现在是分 5 次,每次放五分之一
这样就相当于把瞬间的压力降低到原来的 五分之一了
全国那么多车次,分 100 次放票 也很容易能做到
即相当于把流量分流了,使得服务器瞬间的压力缩小了。
间隔 30 秒
作用:主要是怕用户频繁获取验证码,导致服务器压力过大。
2.检查验证码
把短信收到的验证码这一串数,提交到系统中 系统进行验证验证码是否正确
感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘