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[]中,并使用 lenfreebuf[]数组的长度和未使用的字符数进行描述。

下图展示了 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) 常用命令

Redis字符串命令
命令 说明
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字符串的更多相关文章

  1. Java String字符串/==和equals区别,str。toCharAt(),getBytes,indexOf过滤存在字符,trim()/String与StringBuffer多线程安全/StringBuilder单线程—— 14.0

    课程概要 String 字符串 String字符串常用方法 StringBuffer StringBuilder String字符串: 1.实例化String对象 直接赋值  String str=& ...

  2. [CareerCup] 1.3 Permutation String 字符串的排列

    1.3 Given two strings, write a method to decide if one is a permutation of the other. 这道题给定我们两个字符串,让 ...

  3. 03-Java String字符串详解

    1.Java字符串String A.实例化String字符串:直接赋值(更合理一些,使用较多).使用关键字new. B.String内容的比较 // TODO Auto-generated metho ...

  4. C++学习38 string字符串的增删改查

    C++ 提供的 string 类包含了若干实用的成员函数,大大方便了字符串的增加.删除.更改.查询等操作. 插入字符串 insert() 函数可以在 string 字符串中指定的位置插入另一个字符串, ...

  5. C++学习37 string字符串的访问和拼接

    访问字符串中的字符 string 字符串也可以像字符串数组一样按照下标来访问其中的每一个字符.string 字符串的起始下标仍是从 0 开始.请看下面的代码: #include <iostrea ...

  6. java String字符串——进度1

    String字符串    在JAVA中提供了多种创建字符串对象的方法,这里介绍最简单的两种,    第一种是直接赋值,    第二种是使用String类的构造方法:    如下所示:    Strin ...

  7. 关于String字符串反转

    这是网上看到的一篇java面试题中的问题: 问题是: 如何将一个String字符串反转. String str = "1234567"; int length = str.leng ...

  8. JavaScript的内置对象(Date日期+string字符串)基础语法总结

    1.Date日期对象可以储存任意一个日期,并且可以精确到毫秒数(1/1000 秒). 1)定义一个时间对象 : var Udate=new Date(); //注意:使用关键字new,Date()的首 ...

  9. 【转】String字符串相加的问题

    String字符串相加的问题 前几天同事跟我说我之前写的代码中在操作字符串时候,使用字符串相加的方式而不是使用StringBuffer或者StringBuilder导致内存开销很大.这个问题一直在困扰 ...

  10. 从零开始学习前端JAVASCRIPT — 3、JavaScript基础string字符串介绍

    1:字符串 JS中的任何数据类型都可以当作对象来看.所以string既是基本数据类型,又是对象. 2:声明字符串 基本数据类型:var sStr = '字符串'; 对象的方法:var oStr = n ...

随机推荐

  1. 首页页面(html+css+js)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  2. TCP Wrappers

    TCP Wrappers 是 RHEL 7 系统中默认启用的一款流量监控程序,它能够根据来访主机的地址与本机的目标服务程序作出允许或拒绝的操作.换句话说,Linux 系统中其实有两个层面的防火墙,第一 ...

  3. 【以太坊剖析】以太坊虚拟机(EVM)之基本定义

    以太坊虚拟机(EVM) 以太坊虚拟机(Ethereum Virtual Machine,简称EVM)是一个基于栈的虚拟机,基于特定的环境数据,执行一系列的字节代码形式的指令,以修改系统状态.EVM目前 ...

  4. ApacheCN PythonWeb 译文集 20211110 更新

    Django By Example 中文版 1 创建一个博客应用 2 为博客添加高级功能 3 扩展你的博客应用 4 创建一个社交网站 5 分享内容到你的网站 6 跟踪用户动作 7 构建在线商店 8 管 ...

  5. react-motion 动画案例介绍

    第一个案例:Motion组件 import React,{Component} from 'react'; import {Motion,spring,presets} from 'react-mot ...

  6. JS generator(生成器)

    笔记整理自:廖雪峰老师的JS教程 目录 简介 与函数的不同之处 函数写法 generator写法 generator调用 generator对象的`next()`方法调用 `for ... of`循环 ...

  7. Git refusing to merge unrelated histories (拒绝合并不相关仓库)

    感谢原文作者:lindexi_gd 原文链接:https://blog.csdn.net/lindexi_gd/article/details/52554159 本文讲的是把git在最新2.9.2,合 ...

  8. 聊天泡泡(仿微信)By-H罗

    在做私信时,聊天泡泡仿着QQ做时,聊天泡泡底图有露出,不怎么好看,微信的就比较好看,当时就因为那2行纠结了好久 - (void)viewDidLoad { [super viewDidLoad]; / ...

  9. Squid代理服务器应用

    Squid代理服务器应用 目录 Squid代理服务器应用 一.Squid的脚本概念 1. Squid的作用 2. Web代理的工作机制 3. 代理服务器的概念 4. 代理服务器的作用 5. 代理的基本 ...

  10. Git忽略文件.gitignore的使用

    本博客旨在自我学习使用,如有任何疑问请及时联系博主 1.WHY? 当你使用git add .的时候有没有遇到把你不想提交的文件也添加到了缓存中去?比如项目的本地配置信息,如果你上传到Git中去其他人p ...