Redis 字符串(string)

Redis 字符串(string)

字符串(string)是Redis最基本的键值对类型,这种类型的键值对会在数据库中把单独的一个键和单独的一个值关联起来,被关联的键和值既可以是普通的文字数据,也可以图片、视频、音频、压缩文件等更为复杂的二进制数据。

字符串相关操作

SET:为字符串键设置值
SET key value

在默认情况下,对一个已经设置了值的字符串键执行SET命令将导致键的旧值被新值覆盖。

例如:

redis> SET song_title "Get Wild"
	OK
redis> SET song_title "Running to Horizon"
	OK

在第二条SET命令执行完毕之后,song_title键的值将从原来的Get Wild变为Running to Horizon。

可以通过想SET命令提供可选的NX选项或者XX选项来指示SET命令是否要覆盖一个已经存在的值:

SET key value [NX | XX]

NX:只会在键没有值的情况下执行设置操作,如果键已经存在,那么SET命令将放弃执行设置操作,并返回控制nil表示设置失败。

XX:只会在键已经有值的情况下执行设置操作,如果给定的键并没有值,那么SET命令将放弃执行设置操作,并返回空值表示设置失败。如果对一个已经有值的键执行带有XX选项的SET命令,那么命令将使用新值覆盖已有的旧值。

GET:获取字符串的值
GET key

GET命令接受一个字符串键作为参数,然后返回与该键相关联的值。

如果给的的字符串键在数据库中并没有与之相关联的值,那么GET命令将返回一个控制nil。

Redis数据库要求所有的键必须拥有与之相关联的值,所以如果一个键有值,那么我们就是这个键存在于数据库;相关,如果一个键没有值,那么我们就是这个键不存在与数据库。

GETSET:获取旧值并设置新值

GETSET命令就行GET命令和SET命令的组合版本,GETSET首先获取字符串键目前已有的值,接着为键设置新值,最后把之前获取到的旧值返回给用户:

GETSET key new_value

如果被这是的键并不存在于数据库,那么GETSET命令将返回空值作为键的旧值。

示例:缓存

对数据进行缓存是Redis最常见的用法之一,因为缓存操作是指把数据存储在内存而不是硬盘上,而访问内存远比访问硬盘的速度快得多,所以用户可以通过把需要快速访问的数据存储在Redis中来提升应用程序的速度。

示例:锁

锁是一种同步机制,用于保证一项资源在任何时候只能被一个进程使用,如果有其他进程想要使用相同的资源,那么就必须等待,直到在使用资源的进程放弃使用权为止。

一个锁的实现通常会有获取(acquire)和释放(release)这两种操作:

  • 获取操作用于获取资源的独占使用权。在任何时候,最多只能有一个进程取得锁,我们把成功取得锁的这个进程称为锁的持有者。在锁已经被持有的情况下,所有尝试再次获取锁的操作都会失败。

  • 释放操作用于放弃资源的独占使用权,一般由锁的持有者调用。在锁被释放之后,其他进程就可以再次尝试获取这个锁了。

使用字符串键实现锁,针对锁的获取操作和释放操作分别通过设置字符串键和删除字符串键来完成。

获取锁:

SET lock value NX

NX选项的值确保了代表锁的字符串键只会在没有值的情况下被设置:

  • 如果给定的字符串键没有值,那么说明锁尚未被获取,SET命令将执行设置操作。
  • 如果给定的字符串键已经有值了,那么说明锁已经被获取,SET命令将放弃执行设置操作。

释放锁:

DEL lock

释放锁使用DEL命令,这个命令接受一个或多个数据库键作为参数,尝试删除这些键以及与之关联的值,并返回成功删除的键的数量作为结构。

在使用DEL命令删除代表锁的字符串键之后,字符串键将重新回到没有值的状态,这时用户就可以再次调用SET lock NX方法去获取锁。

锁的获取和释放需要注意:

  • 锁的释放操作需要验证进程的身份。如果锁被持有者以外的其他进程释放,那么系统中可能会同时出现多个锁,导致锁的唯一性被破坏。
  • 锁的获取设置最大加锁时间。如果持有锁的进程因为故障或者编程错误而没有在退出之前主动释放锁,那么锁就会一直处于已被获取的状态,导致其他进程永远无法取得锁。
MSET:一次为多个字符串键设置值

与SET命令和GETSET名字只能设置单个字符串键不同,MSET命令可以一次为多个字符串键设置值:

MSET key value [key value ...]

如果给定的字符串键已经有相关联的值,那么MSET命令也会直接使用新值去覆盖已有的旧值。

MSET命令除了可以让用户更为方便的执行多个设置操作之外,还能有效的提高程序的效率:执行多条SET命令需要客户端和服务器之间进行多次网络通信,并因此耗费大量的时间;而使用一条MSET命令去代替多条SET命令只需要一次网络通信,从而有效的减少程序执行多个设置的操作时的时间。

MGET:一次获取多个字符串键的值

MGET命令就是一个多建版本的GET命令,MGET接受一个或多个字符串键作为参数,并返回这些字符串键的值:

MGET key [key ...]

MGET命令返回一个列表作为结果,这个列表按照用户执行命令时给定键的顺序排列各个键的值。与GET命令一样,MGET命令在碰到不存在的键时也会返回空值nil。

与MSET命令类似,MGET命令也可以将执行多个获取操作所需的网络通信次数从原来的N次降低至只需一次,从而有效的提高程序的运行效率。

MSETNX:只在键不存在的情况下,一次为多个字符串键设置值
MSETNX key value [key value ...]

MSETNX与MSET的主要区别在于,MSETNX只会在所有给定键都不存在的情况下对键进行设置,而不会想MSET那样直接覆盖已有的值。MSETNX命令在成功执行设置操作时返回1,在放弃执行设置操作时则返回0。

示例:存储文章信息

在构建应用程序的时候,我们经常会需要批量地设置和获取多项信息。以博客程序为例:

  • 当用户想要注册博客时,程序就需要把用户的名字、账号、密码、注册时间等多项信息存储起来,并在用户登陆的时候取出这些信息。
  • 当用户想在博客中撰写一篇新文章的时候,程序就需要把文章的标题、内容、作者、发表时间等多项信息存储起来,并在用户阅读文章的时候取出这些信息。
STRLEN:获取字符串值的字节长度
STRLEN key

对于不存在的键,STRLEN命令将返回0。

字符串值的索引

因为每个字符串都是由一系列连续的字节组成的,所以字符串中的每个字节实际上都拥有与之相对应的索引。其中:

  • 字符串值的正数索引以0为开始,从字符串的开头向结尾不断递增。
  • 字符串值的负数索引以-1为开始,从字符串的结尾向开头不断递减。

“hello world”字符串的正负索引:
在这里插入图片描述

GETRANGE:获取字符串值指定索引范围上的内容
GETRANGE key start end

start:索引开始位置

end:索引结束位置

GETRANGE命令接受的是闭区间索引范围,也就是说,位于start索引和end索引上的值也会被包含在命令返回的内容当中。

SETRANGE:对字符串值的指定索引范围进行设置

将字符串键的值从索引index开始的部分替换为指定的新内容,被替换的内容长度取决于新内容的长度:

SETRANGE key index substitute

SETRANGE命令在执行完设置操作之后,会返回字符串值当前的长度作为结果。

自动扩展被修改的字符串:当用户给定的新内容比被替换的内容更长时,SETRANGE命令就会自动扩展被修改的字符串值,从而确保新内容可以顺利写入。

redis> GET message
	"hello redis"
redis> SETRANGE message 5 ", this is a message send from peter"
	(integer) 41
redis> GET message
	"hello, this is a message send from peter"

在值里面填充空字节:当用户给定的index索引超出字符串值的长度时,字符串末尾直到索引index-1之间的部分将使用空字节进行填充,也就是说,这些字节的所有二进制位都会被设置为0

例如:

redis> GET greeting
	"hello"
	
redis> SETRANGE greeting 10 "world"
	(integer) 15
	
redis> GET greeting
	"hello\x00\x00\x00\x00\x00world"
示例:给文章存储程序加上文章长度计数功能和文章预览功能

在前面的内容中,我们使用MSET、MGET等命令构建了一个存储文章信息的程序,在学习STRLEN命令和GETRANGE命令之后,我们可以给这个文章存储程序加上两个新功能,其中一个是文章长度计数功能,另一个则是文章预览功能。

  • 文章长度计数功能用于显示文章内容的长度,读者可以通过这个长度来了解一篇文章大概有多长,从而决定是否继续阅读。
  • 文章预览功能则用于显示文章开头的一部分内容,这些内容可以帮助读者快速的了解文章大意,并吸引读者进一步阅读整篇文章

其中文章长度计数功能是通过对文章内容执行STRLEN命令来实现的,文章预览功能是通过对文章内容执行GETRANGE命令来实现的。

APPEND:追加新内容到值的末尾

将给定的内容追加到字符串键已有值的末尾

APPEND key suffix

返回字符串值当前的长度。

处理不存在的键:如果给定的键并不存在,那么APPEND命令会先将键的值初始化为空字符串“”,然后再执行追加操作,最终效果与使用SET命令为键设置值的情况类似

redis> GET append_msg --键不存在
	(nil)

redis> APPEND append_msg "hello" --效果相当于SET append_msg "hello"
	(integer) 5

redis> GET append_msg
	"hello"

当键有了值之后,APPEND又会像平时一样,将用户给定的值追加到已有值的末尾。

示例:存储日志

数值操作

使用字符串键存储数字值

每当用户将一个值存储到字符串键里面的时候,Redis都会对这个值进行检测,如果这个值能够被解释为以下两种类型的其中一种,那么Redis就会把这个值当作数字来处理:

  • 能够使用C语言的long long int类型存储的整数,取值范围介于-9223372036854775808和9223372036854775807之间
  • 能够使用C语言的long double类型存储的浮点数,取值介于3.36210314311209350626e-4932和1.18973149535723176502e+4932L之间。
INCRBY、DECRBY:对整数值执行加法操作或减法操作

当字符串键存储的值能够被Redis解释为整数时,可以通过INCRBY命令和DECRBY命令对被存储的整数值执行加法或减法操作

INCRBY命令用于为整数值加上指定的整数增量,并返回执行加法之后的值:

INCRBY key incrment

DECRBY命令用于为整数减去指定的整数减量,并返回执行减法之后的值:

DECRBY key incrment

类型限制:当字符串键的值不能被Redis解释为整数时,对键执行INCRBY命令或是DECRBY命令将返回一个错误

不能对浮点数值执行:

redis> SET pi 3.14
	OK

redis> INCRBY pi 100 --不能对浮点数值执行
	(error) ERR value is not an integer or out of range

不能对字符串值执行:

redis> SET message "hello world"
	OK

redis> INCRBY message --不能对字符串值执行
	(error) ERR wrong number of argments for 'incrby' command
redis> SET big-number 123456789123456789123456789
	OK

redis> INCRBY big-number 100 --不能对超过64位长度的整数执行
	(error) ERR value is not an integer or out of range

另外需要注意的一点是,INCRBY和DECRBY的增量和减量也必须能够被Redis解释为整数,使用其他类型的值作为增量或减量将返回一个错误

处理不存在的键:当INCRBY命令或DECRBY命令遇到不存在的键时,命令回先将建的值初始化为0,然后再执行相应的加法操作或减法操作。

redis> GET x --键x不存在
	(nil)

redis> INCRBY x 123 --先将键x的值初始化为0,然后再执行加上123
	(integer) 123

redis> GET x
	"123"
	
DECRBY同理
INCE、DECR:对整数值执行加1操作或减1操作

因为对整数执行加1或减1操作的场景经常出现,为了方便执行这两个操作,Redis分别提供了INCR加1和DECR减1命令。

对整数值加1,相当于INCRBY key 1:

INCR key

对整数值减1,相当于DECRBY key 1:

DECR key

除了增量和减量被固定为1之外,INCR命令和DECR命令的其他方面与INCRBY命令以及DECRBY命令完全相同。

INCRBYFLOAT:对数字值执行浮点数加法操作
INCRBYFLOAT key incrment

INCRBYFLOAT命令可以把shuz一个浮点数增量加到字符串键存储的数字值上面,并返回键在执行加法操作之后的数值。

处理不存在的键:INCRBYFLOAT命令在遇到不存在的键时,会先将键的值初始化为0,然后在执行相应的加法操作。

使用INCRBYFLOAT执行浮点数减法操作:传入负数增量

INCRBYFLOAT与整数值:INCRBYFLOAT命令对于类型限制的要求比INCRBY命令和INCR命令要宽松的多:

  • INCRBYFLOAT命令即可用于浮点数值,也可以用于整数值。
  • INCRBYFLOAT命令的增量既可以是浮点数,也可以是整数。
  • 当INCRBYFLOAT命令的执行结果可以表示为整数时,命令的执行结果将以整数形式存储。

小数位长度限制:在使用INCRBYFLOAT命令处理浮点数的时候,命令最多只会保留计算结果小数点后的17位数字,超过这个范围的小数将被截断:

redis> GET i 
	"0.01234567890123456789" --小数部分20位长

redis> INCRBYFLOAT i 0
	"0.012345678901234567" --执行加法操作之后,小数部分只保留了17位
示例:
ID生成器 INCR
计数器
限速器

为了保障系统的安全性和性能,并保证系统的重要资源不被滥用,应用程序常常会对用户的某些行为进行限制:比如:

  • 为了防止网站内容内网络爬虫抓取,网站管理者通常会限制每个IP地址在固定时间段内能够访问的页面数量。比如1min之内最多只能访问30个页面,超过这一限制的用户将被要求进行身份验证,确认被人并非网络爬虫,或者等到限制解除之后再进行访问。
  • 为了防止用户的账户遭到暴力破解,网上银行通常会对访客的密码试错次数进行限制,如果一个方可在尝试登陆某个账号的过程中,连续好几次输入了错误的密码,那么这个账号将被冻结,只能等到第二天再尝试登陆,有的银行还会向账号持有者的手机发送通知来汇报这一情况。

限速器程序会把操作的最大可执行次数存储在一个字符串键里面,然后在用户每次尝试执行被限制的操作之前,使用DECR命令将操作的可执行次数键1,最后通过检测可执行次数的值来判断是否执行该操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值