5.string字符串
string(字符串)是 Redis 中最简单的数据类型。我们知道,Redis 所有数据类型都是以 key 作为键,通过检索这个 key 就可以获取相应的 value 值。Redis 存在多种数据类型,比如字符串、列表、哈希散列等,它们对应的 value 结构各不相同。本节先讲解字符串的相关知识。
一、认识Redis字符串
Redis 使用标准 C 语言编写,但在存储字符时,Redis 并未使用 C 语言的字符类型,而是自定义了一个属于特殊结构 SDS(Simple Dynamic String)即简单动态字符串),这是一个可以修改的内部结构,非常类似于 Java 的 ArrayList。
1) SDS动态字符串
SDS 的结构定义如下:
struct sdshdr{
//记录buf数组中已使用字符的数量,等于 SDS 保存字符串的长度
int len;
//记录 buf 数组中未使用的字符数量
int free;
//字符数组,用于保存字符串
char buf[];
从上述结构体可以看出,Redis string 将字符串存储到字符类型的buf[]
中,并使用 len
、free
对buf[]
数组的长度和未使用的字符数进行描述。
下图展示了 SDS 字符串的结构示意图:
图1
上图 1 存储了一个len
为 4 的 “java\0”字符串,并且未使用的字符数free
为 0。你可能注意到 buf 数组存储的字符串仍然以 C语言字符格式的“\0”结尾的,这样做的目的是为了能够重用 C语言库 <string.h> 中的部分函数。
在 C语言中,字符串类型的结尾以空字符串 ‘\0’来标识的。但在某些情况下,字符串可能会包含具有实际意义的“空字符”,此时 C语言就无法正确的存取这个字符了,而 Redis 通过 len 来标识字符串的总长度,从而保证了数据的二进制安全特性。
2) 分配冗余空间
string 采用了预先分配冗余空间的方式来减少内存的频繁分配,如下图所示:
图2
如图 2 所示,Redis 每次给 string 分配的空间都要大于字符串实际占用的空间,这样就在一定程度上提升了 Redis string 存储的效率,比如当字符串长度变大时,无需再重新申请内存空间。
3) string自动扩容
当字符串所占空间小于 1MB 时,Redis 对字符串存储空间的扩容是以成倍的方式增加的;而当所占空间超过 1MB 时,每次扩容只增加 1MB。Redis 字符串允许的最大值字节数是 512 MB。
二、Redis字符串命令
1) 命令格式
Redis 提供了操作字符串的命令,通过学习这些命令我们可以掌握如何使用它们,其语法格式如下:
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,过期后自动删除
redis 127.0.0.1:6379> SET www.biancheng.net "hello编程帮" EX 60 NX
OK
# 查询 key 对应的值
redis 127.0.0.1:6379> GET www.biancheng.net
"hello编程帮"
2) 常用命令
命令 | 说明 |
---|---|
SET key value | 用于设定指定键的值。 |
GET key | 用于检索指定键的值。 |
GETRANGE key start end | 返回 key 中字符串值的子字符。 |
GETSET key value | 将给定 key 的值设置为 value,并返回 key 的旧值。 |
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”),它们允许你一次性设置或查询多个键值对,这样就有效地减少了网络耗时。
三、简单命令演示
下面对常用命令做简单演示:
1) GETRANGE命令
GETRANGE 命令用于截取一定长度的 value,并返回截取后的新值。语法格式如下:
redis 127.0.0.1:6379> GETRANGE KEY_NAME start end
注意,字符串的截取范围由 start 和 end 两个偏移量决定(包括 start 和 end 在内的闭区间)
示例如下:
127.0.0.1:6379> SET website www.biancheng.net
OK
#索引值
127.0.0.1:6379> GETRANGE website 0 4
"www.b"
#使用负数索引
127.0.0.1:6379> GETRANGE website 0 -1
"www.biancheng.net"
127.0.0.1:6379>
2) GETSET命令
GETSET 命令用于重新设置 value 值,并返回之前旧 value。示例如下:
127.0.0.1:6379> GETSET num first
"6"
127.0.0.1:6379> GETSET num second
"first"
#查看长度值
127.0.0.1:6379> strlen num
(integer) 6
注意:num 之前存储的值为“6”,所以结果返回“6”。
3) SETEX命令
将值 value 存储到 key 中 ,并将 key 的过期时间设为 seconds (以秒为单位)。示例如下:
#设置过期时间为60s
127.0.0.1:6379> SETEX www.biancheng.net 60 hello
OK
#查看过期时间
127.0.0.1:6379> ttl www.biancheng.net
(integer) 5
4) MSETNX命令
该命令了类似于 MSET 命令,但是它仅当指定的 key 不存在时才能够执行成功,用于同时设置多个键值对。示例如下:
#返回0,说明命令执行失败
127.0.0.1:6379> MSETNX www.biancheng.net hello title world
(integer) 0
#删除重复的键
127.0.0.1:6379> del www.biancheng.net
(integer) 1
#重新执行
127.0.0.1:6379> MSETNX www.biancheng.net hello title world
(integer) 1
由于 key 之前已经存在,所以第一次执行失败,当删除存在的后,命令就会执行成功。
5) SETRANGE命令
该命令使用指定的字符在给定的范围内覆盖 key 对应的 value ,其语法格式如下:
redis 127.0.0.1:6379> SETRANGE KEY_NAME OFFSET VALUE
- KEY_NAME:指 key 的名字;
- OFFSET:指初始偏移量;
- VALUE:指要替换成的字符串。
示例如下:
127.0.0.1:6379> SET word "hello world"
OK
127.0.0.1:6379> SETRANGE word 6 www.biancheng.net
(integer) 23
127.0.0.1:6379> GET word
"hello www.biancheng.net"
在线练习工具:https://try.redis.io/
查看更多命令:https://redis.io/commands
5.string字符串的更多相关文章
- Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0
课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值 String str=& ...
- [CareerCup] 1.3 Permutation String 字符串的排列
1.3 Given two strings, write a method to decide if one is a permutation of the other. 这道题给定我们两个字符串,让 ...
- 03-Java String字符串详解
1.Java字符串String A.实例化String字符串:直接赋值(更合理一些,使用较多).使用关键字new. B.String内容的比较 // TODO Auto-generated metho ...
- C++学习38 string字符串的增删改查
C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的增加.删除.更改.查询等操作. 插入字符串 insert() 函数可以在 string 字符串中指定的位置插入另一个字符串, ...
- C++学习37 string字符串的访问和拼接
访问字符串中的字符 string 字符串也可以像字符串数组一样按照下标来访问其中的每一个字符.string 字符串的起始下标仍是从 0 开始.请看下面的代码: #include <iostrea ...
- java String字符串——进度1
String字符串 在JAVA中提供了多种创建字符串对象的方法,这里介绍最简单的两种, 第一种是直接赋值, 第二种是使用String类的构造方法: 如下所示: Strin ...
- 关于String字符串反转
这是网上看到的一篇java面试题中的问题: 问题是: 如何将一个String字符串反转. String str = "1234567"; int length = str.leng ...
- JavaScript的内置对象(Date日期+string字符串)基础语法总结
1.Date日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 1)定义一个时间对象 : var Udate=new Date(); //注意:使用关键字new,Date()的首 ...
- 【转】String字符串相加的问题
String字符串相加的问题 前几天同事跟我说我之前写的代码中在操作字符串时候,使用字符串相加的方式而不是使用StringBuffer或者StringBuilder导致内存开销很大.这个问题一直在困扰 ...
- 从零开始学习前端JAVASCRIPT — 3、JavaScript基础string字符串介绍
1:字符串 JS中的任何数据类型都可以当作对象来看.所以string既是基本数据类型,又是对象. 2:声明字符串 基本数据类型:var sStr = '字符串'; 对象的方法:var oStr = n ...
随机推荐
- 配置kubectl连接多个kubernetes集群
背景:我们通过会有多个k8s集群,例如集群(cn-k8s)和集群(jp-k8s),那个就需要有一台服务器可以同时访问两个集群,方式:将2个集群的config信息存放到一个文件中,通过使用 kubect ...
- SpringBoot使用异步线程池实现生产环境批量数据推送
前言 SpringBoot使用异步线程池: 1.编写线程池配置类,自定义一个线程池: 2.定义一个异步服务: 3.使用@Async注解指向定义的线程池: 这里以我工作中使用过的一个案例来做描述,我所在 ...
- 来自开发者的点赞!HMS Core荣获多个行业奖项
2021年,HMS Core发布全新HMS Core 6,为全球开发者提供多终端.跨OS.全场景的华为移动服务核心能力,和开发者共同成长.通过和开发者在行业解决方案.业务场景创新和商业增长上的持续合作 ...
- ql/sql 循环语句、异常处理、事务处理!
一.ql sql 循环语句? /*1.loop循环 语法: 声明循环变量 loop 判断循环条件 ,如果循环条件不成立,跳出循if 条件表达式 then exit; end if; 语句块; 改变循环 ...
- 如何在pyqt中自定义SwitchButton
前言 网上有很多 SwitchButton 的实现方式,大部分是通过重写 paintEvent() 来实现的,感觉灵活性不是很好.所以希望实现一个可以联合使用 qss 来更换样式的 SwitchBut ...
- rust实战系列 - 使用Iterator 迭代器实现斐波那契数列(Fibonacci )
为什么是斐波那契数列 斐波那契数列十分适合用来实战rust的迭代器,算法也很简单,一目了然.这个例子可以用来学习Iterator的使用,十分适合刚学习了rust的迭代器章节后用来练练手. 代码实战 d ...
- JAVA多线程学习十五 - 阻塞队列应用
一.类相关属性 接口BlockingQueue<E>定义: public interface BlockingQueue<E> extends Queue<E> { ...
- Android Adapter基本理解
感谢大佬:https://blog.csdn.net/l799069596/article/details/47301711 Android Adapter基本理解: 我的理解是: 1.一个有许多ge ...
- Linux Shell脚本攻略复习
1. 打开终端后的提示符中,$表示普通用户,#表示管理员用户root,root是linux系统中权限最高的用户. 2. shell脚本通常是一个#!起始的文本文件,其中#!位于解释器路径之前. 例如: ...
- iOS应用性能调优--初级---王朋
目录 我要给出的建议将分为三个不同的等级: 入门级. 中级和进阶级: 入门级(这是些你一定会经常用在你app开发中的建议) 1. 用ARC管理内存 2. 在正确的地方使用reuseIdentifier ...