redis学习-11- Redis string字符串类型操作

7.Redis string字符串

7.1 string字符串数据结构
  • string(字符串)结构是 Redis 中最简单的数据类型。Redis 所有数据类型都是以 key 作为键,通过检索这个 key 就可以获取相应的 value 值。Redis 存在多种数据类型,比如字符串、列表、哈希散列等,它们对应的 value 结构各不相同。

  • Redis 使用标准 C 语言编写,但在存储字符时,Redis 并未使用 C 语言的字符类型,而是自定义了一个特殊结构 SDS(Simple Dynamic String)即简单动态字符串,这是一个可以修改的内部结构,非常类似于 Java 的 ArrayList。

  • SDS动态字符串:结构定义如下:

struct sdshdr{
     //记录buf数组中已使用字符的数量,等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用的字符数量
     int free;
     //字符数组,用于保存字符串
     char buf[];

从结构体可以看出,Redis string 将字符串存储到字符类型的buf[]中,并使用 lenfreebuf[]数组的长度和未使用的字符数进行描述。

SDS 字符串的结构示意图:
在这里插入图片描述

该图存储了一个len为 4 的 “java\0”字符串,并且未使用的字符数free为 0。 buf 数组存储的字符串仍然以 C语言字符格式的“\0”结尾的,这样做的目的是为了能够重用 C语言库 <string.h> 中的部分函数。

  • 分配冗余空间:string 采用了预先分配冗余空间的方式来减少内存的频繁分配,如下图所示:

在这里插入图片描述

Redis 每次给 string 分配的空间都要大于字符串实际占用的空间,这样就在一定程度上提升了 Redis string 存储的效率,比如当字符串长度变大时,无需再重新申请内存空间。

  • string自动扩容:当字符串所占空间小于 1MB 时,Redis 对字符串存储空间的扩容是以成倍的方式增加的;而当所占空间超过 1MB 时,每次扩容只增加 1MB。Redis 字符串允许的最大值字节数是 512 MB。
7.2 字符串命令
  • 通过相关字符串命令对其进行操作,比如设置、检索、删除等等。操作字符串的命令格式
redis 127.0.0.1:6379> COMMAND KEY_NAME
#COMMAND:表示字符串的命令;
#KEY_NAME:表示 key(键)的名称。
  • 利用 Redis 客户端给出的自动语法提示,比如SET命令的格式如下:
127.0.0.1:6379> SET key value [EX seconds|PX milliseconds] [NX|XX]
  • 其中[]内代表可选参数,其含义如下所示:

    • EX seconds:设置指定的过期时间,以秒为单位;
    • PX milliseconds:设置指定的过期时间,以毫秒为单位;
    • NX:先判断 key 是否存在,如果 key 不存在,则设置 key 与 value;
    • XX:先判断 key 是否存在,如果 key 存在,则重新设置 value。
  • SET命令演示:在 key 不存在的情况下设置过期时间为 60s:

#key的过期时间为60s,过期后自动删除
remote:0>set name tony ex 60 nx
"OK"
# 查询 key 对应的值
remote:0>get name
"tony"
7.3 常用命令
命令说明
SET key value用于设定指定键的值。
GET key用于检索指定键的值。
GETRANGE key start end返回 key 中字符串值的子字符。start从0开始
GETSET key value将给定 key 的值设置为 value,并返回 key 的旧值,即先get再set。
GETBIT key offset对 key 所存储的字符串值,获取其指定偏移量上的位(bit)。
MGET key1 [key2…]批量获取一个或多个 key 所存储的值,减少网络耗时开销。
SETBIT key offset value对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。
SETEX key seconds value将值 value 存储到 key中 ,并将 key 的过期时间设为 seconds (以秒为单位)。是一步操作,保证了原子性
SETNX key value当 key 不存在时设置 key 的值。用于分布式锁,保证这个值存在,不会被覆盖+乐观锁。有值加锁,可当版本号
SETRANGE key offset value从偏移量 offset 开始,使用指定的 value 覆盖、替换的 key 所存储的部分字符串值。
STRLEN key返回 key 所储存的字符串值的长度。
MSET key value [key value …]该命令允许同时设置多个键值对。
MSETNX key value [key value …]当指定的 key 都不存在时,用于设置多个键值对。
PSETEX key milliseconds value此命令用于设置 key 的值和过期时间(以毫秒为单位)。
INCR key将 key 所存储的整数值加 1。自增
INCRBY key increment将 key 所储存的值加上给定的递增值(increment)。设置步长,指定增量
INCRBYFLOAT key increment将 key 所储存的值加上指定的浮点递增值(increment)。
DECR key将 key 所存储的整数值减 1。自减
DECRBY key decrement将 key 所储存的值减去给定的递减值(decrement)。设置步长,指定减量
APPEND key value该命令将 value 追加到 key 所存储值的末尾。
  • Redis string 的SET/GET命令只能一次设置/查询一个键值对,这样虽然简单,但是效率不高。为了提高命令的执行效率,Redis 提供了可以批量操作多个字符串的读写命令 MSET/MGET(“M”代表“Many”),它们允许一次性设置或查询多个键值对,这样就有效地减少了网络耗时。
7.4 SET、GET命令
  • SET 命令用于设置 key 存储的值,当 key 已经存储了其他值时, SET 命令会将原值覆盖,重新设置新值。GET 命令返回 key 所存储的字符串值。如果 key 不存在则返回 null,若 key 存储的不是一个字符串类型的值,将返回一个错误,因为 GET 命令只能处理字符串。 命令可用版本:>= 1.0.0

SET 命令在 Redis 2.6.12 版本做了参数的扩充,允许同时使用EXNX参数对 key 进行设置。

  • 基本语法如下:
#SET 命令的基本语法如下:
127.0.0.1:6379>SET key value [expiration EX seconds|PX milliseconds] [NX|XX]

#GET 命令的基本语法如下:
GET key
  • 参数说明:

    • EX second:设置键的过期时间为 second 秒。SET key value EX second 效果等同于 SETEX key second value。
    • PX millisecond:设置键的过期时间为毫秒。SET key value PX millisecond 效果等同于 PSETEX key millisecond value。
    • NX:只在键不存在时,才对键进行设置操作。SET key value NX 效果等同于 SETNX key value。
    • XX:只在键已经存在时,才对键进行设置操作。
  • SET返回值:在 Redis 2.6.12 版本以前, SET 命令总是返回 OK 。从 Redis 2.6.12 版本开始, SET 在设置操作成功完成时,才返回 OK 。如果设置了 NX 或者 XX 参数,但因为条件没达到而造成设置操作未执行,那么命令返回 NULL Bulk Reply。

  • GET返回值当 key 不存在时,返回 null ,否则,返回 key 的值。如果 key 不是字符串类型,那么返回一个错误。

  • 命令演示:

 #使用EX和NX设置key
remote:0>set url www.baidu.com ex 60 nx
"OK"
remote:0>set url www.baidu.com px 600 xx
"OK"
#对已经存在的键进行设置
remote:0>set name marry
"OK"
#获取存储的值
remote:0>get name
"marry"
#key不存在
remote:0>get urls
null
#列表类型的key
remote:0>lpush course java php python
"3"
#返回错误,get只能操作字符串类型的key
remote:0>get course
"WRONGTYPE Operation against a key holding the wrong kind of value"
7.5 SETBIT、GETBIT命令
  • SETBIT 命令用于对 key 所储存的字符串值,设置或清除指定偏移量上的位(bit)。位的设置或清除取决于 value,可以是 0 或者是 1 。
  • 当 key 不存在时,自动生成一个新的字符串值。字符串会进行伸展以确保它可以将 value 保存在指定的偏移量上。当字符串值进行伸展时,空白位置以 0 填充。offset 参数必须大于或等于 0 ,小于 2^32 (bit 被限制在 512 MB 之内)。SETBIT 命令可用版本:>= 2.2.0
  • GETBIT 命令对 key 所储存的字符串值,获取指定偏移量上的位(bit)。当 offset 比字符串值的长度大,或者 key 不存在时,返回 0。GETBIT 命令可用版本:>= 2.2.0
提示:如果 offset 偏移量的值较大,计算机进行内存分配时可能会造成 Redis 服务器被阻塞。
  • 命令的基本语法如下:
#SETBIT 命令#SETBIT 命令的基本语法如下:
setbit key offset value  

#GETBIT 命令的基本语法如下:
GETBIT key offset
  • SETBIT 命令的返回值指定了偏移量原来储存的位。

  • GETBIT命令的返回值:字符串值指定偏移量上的位(bit)。

  • 命令演示

#setbit key值的偏移量
remote:0>SETBIT mybit 0 1
"0"
remote:0>SETBIT mybit 1 1
"0"
remote:0>SETBIT mybit 2 0
"0"
127.0.0.1:6379> getbit mybit 0
(integer) 1
127.0.0.1:6379> getbit mybit 1
(integer) 1
127.0.0.1:6379> getbit mybit 2
(integer) 0
127.0.0.1:6379> get mybit
"\xd0"


#key默认各bit位初始化为0
#对不存在的 offset 进行 GETBIT, 返回 0
remote:0>getbit mybit 200
"0"

#对不存在的 key 或者不存在的 offset 进行 GETBIT, 返回 0
remote:0>exists mybits
"0"
remote:0>getbit mybits 10
"0"
#对已存在的 offset 进行 GETBIT
remote:0>setbit mybit 3 1
"0"
remote:0>getbit mybit 3
"1"
7.6 BITCOUNT命令
  • BITCOUNT 命令用于计算给定字符串中,被设置为 1 的比特位数量。一般情况下,给定的整个字符串都会被计数,通过指定 start 或 end 参数,就可以让计数只在特定的位上进行。

提示:start 和 end 参数的设置和 GETRANGE 命令类似,都可以使用负数值:比如 -1 表示最后一个位,而 -2 表示倒数第二个位,以此类推。start 从0开始

  • 如果 key 不存在,则会被当成空字符串来处理,因此对一个不存在的 key 进行 BITCOUNT 操作,结果为 0 。命令可用版本:>= 2.6.0。 BITCOUNT 命令的基本语法如下:
BITCOUNT key [start end]  
  • 返回值:被设置为 1 的位的数量。命令演示
#setbit key值的偏移量
remote:0>SETBIT mybit 0 1
"0"
remote:0>SETBIT mybit 1 1
"0"
remote:0>SETBIT mybit 2 0
"0"
remote:0>SETBIT mybit 3 1
"0"
#统计1的数量
remote:0>bitcount mybit 0 3
"3"
remote:0>bitcount mybit 0 -1
"3"
#不存在的key进行BITCOUNT操作
remote:0>bitcount mybits 0 3
"0"
7.7 SETRANGE、GETRANGE命令
  • SETRANGE 命令用指定的字符串覆盖给定 key 所储存的字符串值,覆盖的位置从偏移量 offset 开始。如果 key 原来储存的字符串长度比偏移量小,比如字符串只有 5 个字符长,但你设置的 offset 是 8,那么原字符和偏移量之间的空白字符将用零字节(“\x00” )来填充。

  • 最大偏移量是 2^29-1(536870911) ,因为 Redis 字符串的大小被限制在 512 兆以内,如果需要使用比这更大的空间,可以使用多个 key 来实现 。

  • 注意:当生成一个很长的字符串时,Redis 需要分配内存空间,该操作有时候可能会造成服务器阻塞。命令可用版本:>= 2.2.0

  • GETRANGE 命令用于截取一定长度的 value返回 key 中字符串值的子字符串,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内的闭区间)。负数偏移量表示从字符串末尾开始计数,-1 表示最后一个字符,-2 表示倒数第二个,以此类推。GETRANGE 子字符串的长度大小(range)不能超过实际字符串的长度。命令可用版本:>= 2.4.0

  • 基本语法如下:

#SETRANGE 命令的基本语法如下:
SETRANGE key offset value

#参数说明
KEY_NAME:指 key 的名字;
OFFSET:指初始偏移量;
VALUE:指要替换成的字符串。 

#GETRANGE 命令的基本语法如下:
GETRANGE key start end 
  • SETRANGE 命令的返回值:被修改之后的字符串总长度 。

  • GETRANGE 命令的返回值:截取后得到的子字符串。

  • 命令演示:

remote:0>set pwd 123456
"OK"
remote:0>get pwd
"123456"
remote:0>setrange pwd 6 abcdef
"12"
remote:0>get pwd
"123456abcdef"

#key储存的字符串长度比偏移量小时,如何覆盖
remote:0>set pwd 123456
"OK"
remote:0>setrange pwd 8 abcdef
"14"
remote:0>get pwd
123456\x00\x00abcdef


remote:0>get pwd
"123456abcdef"
remote:0>getrange pwd 1 8
"23456abc"
remote:0>getrange pwd 1 -1
"23456abcdef"
remote:0>getrange pwd 1 -2
"23456abcde"
remote:0>getrange pwd 1 -3
"23456abcd"
#不支持从负数到正数,或者负数到负数
remote:0>getrange pwd -1 -3
  • 在 2010 年的一台 Macbook Pro 上,设置偏移量为 536870911(512MB 内存分配),耗时约 300 毫秒,设置偏移量为 134217728(128MB 内存分配),耗时约 80 毫秒,设置偏移量 33554432(32MB 内存分配),耗时约 30 毫秒,设置偏移量为 8388608(8MB 内存分配),耗时约 8 毫秒。

注意:若首次内存分配成功之后,再对同一个 key 调用 SETRANGE 命令,无须重新分配内存。

7.8 SETEX命令
  • SETEX 命令为 key 设置 value 值,并将 key 的过期时间设为 seconds (以秒为单位)。如果 key 已经存在,那么将覆盖 key 原来的值。SETEX 命令与 PSETEX 命令类似,不过后者以毫秒(milliseconds)为单位。命令可用版本:>= 2.0.0

  • SETEX 命令的基本语法如下:

SETEX key seconds value
  • ETEX 命令的返回值设置成功时返回 OK,若 second 参数不符合要求,则会返回一个错误,比如设置成了负数或者浮点数。

  • 命令演示:

remote:0>setex url 60 links
"OK"
remote:0>get url
"links"
#覆盖成功
remote:0>setex url 60 www.baidu.com
"OK"
#返回错误
remote:0>setex url -60 www.baidu.com
"ERR invalid expire time in 'setex' command"
remote:0>setex url 60.0 www.baidu.com
"ERR value is not an integer or out of range"
7.9 STRLEN命令
  • STRLEN 命令返回 key 所储存的字符串值的长度。当 key 储存的不是字符串值时,返回一个错误。命令可用版本:>=2.2.0。SETNX 命令的基本语法如下:
STRLEN key
  • SETNX 命令返回字符串值的长度。当 key 不存在时,返回 0。命令演示
remote:0>setnx url www.baidu.com
"1"
#获取长度
remote:0>strlen url
"13"
#若key不存在,则长度为 0
remote:0>strlen urls
"0"
7.10 SETNX命令
  • SETNX 命令,当且仅当给定的 key 不存在的时候,才创建 key,并为其设置 value 值。如果 key 已经存在,则命令执行失败。命令可用版本:>= 1.0.0

  • SETNX 命令的基本语法如下:

SETNX key value
  • SETNX 命令的返回值设置成功,返回 1;设置失败,返回 0 。命令演示
remote:0>setnx url www.baidu.com
"1"
#setnx命令,当key存在时,不可以覆盖
remote:0>setnx url links
"0"
remote:0>get url
"www.baidu.com"
7.11 GETSET命令
  • GETSET 命令将给定 key 的值设置为 value,并且返回 key 的旧值(old value)。先get在set。 命令可用版本:>= 1.0.0。GETSET 命令的基本语法如下:
GETSET key value
  • GETSET 命令返回给定 key 的旧值,若 key 不存在则返回 null;当 key 存在但不是字符类型是,返回一个错误。命令演示
#类似juc中的cas自旋锁,比较并交换,在数据结构上是相同的java/高并发
remote:0>get pwd
"123456abcdef"
remote:0>getset pwd 12345678
"123456abcdef"
#key不存在
remote:0>getset pwds 12345678
null
#设置新值并返回旧值
remote:0>getset pwds abcdefg
"12345678"
7.12 MSET、MGET命令
  • MSET 命令用于同时设置一个或多个 key-value 键值对,MSET 命令可用版本:>= 1.0.1。MGET 命令返回一个或多个给定 key 的值,MGET 命令可用版本:>= 1.0.0。

  • 命令的基本语法如下:

#MSET 命令的基本语法如下:
MSET key value [key value ...]   
#MGET 命令的基本语法如下:
MGET key [key ...]
  • MSET 命令返回 OK,MGET 命令返回所有 key 存储的 value 值。命令演示:
remote:0>mset name tony age 14
"OK"
remote:0>get name
"tony"
remote:0>get age
"14"
remote:0>mget name age
 1)  "tony"
 2)  "14"
  • 设置对象的高级用法
set user:1 {name:zs,zge:10} #设置一个user:1对象,值位json字符来保存一个对象

# 这里的key是一个巧妙的设计:user:{id}:{filed},如此设计在redis是可行的。

remote:0>mset user:2:name zs user:2:age 15
"OK"

remote:0>mget user:2:name user:2:age
 1)  "zs"
 2)  "15"
7.13 MSETNX命令
  • MSETNX 命令类似于 MSET 命令用于所有给定 key 都不存在时才能够执行成功,同时设置一个或多个 key-value 键值对。**该命令具有原子性,它执行结果只有两种:全部成功或者全部失败。**命令可用版本:>= 1.0.1。MSETNX 命令的基本语法如下:
MSETNX key value [key value ...]
  • MSETNX 命令返回值:当所有 key 都成功设置时,返回 1,如果其中至少一个 key 已经存在,那么将设置失败,此时会返回 0。命令演示
#设置成功返回 1
remote:0>msetnx stu1 zs stu2 ls stu3 ww
"1"
#由于stu3已经存在,因此设置失败
remote:0>msetnx stu3 zs stu4 ls stu5remote:0> ww
"0"
remote:0>mget stu1 stu2 stu3
 1)  "zs"
 2)  "ls"
 3)  "ww"
7.14 APPEND命令
  • APPEND 命令用于为指定的 key 追加值。如果 key 已经存在并且是一个字符串, APPEND 命令将 value 追加到 key 原来的值的末尾。当 key 不存在时,它就为这个 key 设置 value 值,等同于 SET key value 操作。APPEND 命令可用版本:>= 2.0.0。该命令语法:
 APPEND key value
  • APPEND 命令的返回值:追加 value 之后, key 存储的字符串长度。命令演示
#确保name不存在,删除key
remote:0>del name
"1"
#自动创建,并设置value
remote:0>append name to
"2"
#追加到末尾
remote:0>append name ny
"4"
remote:0>get name
"tony"

  • 时间序列(Time series):APPEND 命令可以为一系列定长(fixed-size)数据(sample)提供一种紧凑的表示方式,这种操作通常被应用于时间序列的表示上。命令的格式如下所示:
APPEND timeseries "fixed-size sample"
  • 通过以下的方式可以访问时间序列的各项属性:
    • STRLEN:给出时间序列中数据的数量;
    • GETRANGE:可以用于随机访问;
    • SETRANGE:可以用于覆盖或修改已存在的的时间序列。

这个方法的唯一缺陷就是只能增长时间序列,而不能缩短。因为 Redis 目前还没有对字符串进行修剪(tirm)的命令,但是,这种储存方式仍然节省了大量空间。

我们可以考虑使用 UNIX 时间戳作为时间序列的键名,这样可以避免单个 key 因为保存过大的时间序列而占用大量内存。

  • 时间序列的例子
remote:0>append ts 0012
"4"
remote:0>append ts 0045
"8"
remote:0>getrange ts 0 3
"0012"
remote:0>getrange ts 4 7
"0045"

7.15 DECR、DECRBY命令
  • DECR 命令对 key 中存储的数值做减 1 操作。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECR 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。DECR 命令可用版本:>= 1.0.0。
  • DECRBY 命令对 key 中存储的数值做定减运算。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 DECRBY 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。INCRBY 命令可用版本:>= 1.0.0

注意:被操作的数值限制在 64 位(bit)有符号数字表示之内。

  • 语法:
#DECR 命令的基本语法如下:
DECR key
#RBY 命令的基本语法如下:
DECRBY key increment
  • DECR 命令的返回值:执行 DECR 命令减 1 操作后 key 的值。

  • DECRBY 命令的返回值:减去 decrement 之后, key 存储的的数值。

  • 命令演示:

remote:0>get age
"14"
remote:0>decr age
"13"
remote:0>decr age
"12"
#对不存在的key的值进行减1操作
remote:0>decr ages
"-1"
remote:0>decr ages
"-2"
#对可以进行指定数值的递减操作
remote:0>decrby age 5
"7"
#递增操作
remote:0>incr age
"8"
remote:0>incrby age 10
"26"

7.16 INCR、INCRBY命令
  • INCR 命令对 key 中存储的数值做加 1 操作。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。INCR 命令可用版本:>= 1.0.0

  • INCRBY 命令对 key 中存储的数值做增量运算。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCRBY 操作。如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。INCRBY 命令可用版本:>= 1.0.0

注意:被操作的数值限制在 64 位(bit)有符号数字表示之内。

  • 语法
#INCR 命令的基本语法如下:
INCR key
#INCRBY 命令的基本语法如下:
INCRBY key increment
  • NCR 命令的返回值:执行 INCR 命令加 1 操作后 key 的值。

  • INCRBY 命令的返回值:加上 increment 之后, key 存储的的数值。

  • 命令演示:

remote:0>get age
"26"
remote:0>incr age
"27"
remote:0>incr age
"28"
remote:0>incrby age 10
"38"

#key进行拓展使用,表明age是哪个对象的属性
remote:0>incr user:1:age
"28"
7.17 INCRBYFLOAT命令
  • INCRBYFLOAT 命令对 key 中存储的数值加上浮点数增量。如果 key 不存在,那么 INCRBYFLOAT 会先将 key 的值设为 0 ,再执行加法操作。如果命令执行成功,那么 key 的值会被更新为新值,并且新值会以字符串的形式被返回。INCRBYFLOAT 命令可用版本:>= 2.6.0
  • 无论是 key 存储的值,还是 increment 增量值,它们都可以使用指数符号来表示,比如 2.0e7 、 3e5 、 90e-2。

注意:INCRBYFLOAT 的计算结果最多只能表示小数点的后十七位。

  • INCRBYFLOAT 命令的基本语法如下:
INCRBYFLOAT key increment
  • INCRBYFLOAT 命令的返回值:加上 increment 浮点数后, key 存储的的数值。命令演示:
remote:0>set myfloat 314e-2
"OK"
remote:0>get myfloat
"314e-2"
#最多保留17位小数
remote:0>incrbyfloat myfloat 0
"3.14"
#小数加法。
remote:0>incrbyfloat myfloat 10.5
"13.64"
#表示负数,减法。
remote:0>incrbyfloat myfloat -2.5
"11.14"
下一篇:redis学习-12- Redis bitmap位图操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值