Redis 数据类型 String
Redis 数据类型 String
Redis主要支持的数据类型有5种:String ,Hash ,List ,Set ,和 Sorted Set
String
string类型在redis中是最常见的类型,value存储最大数据量为512M,可以存放json数据,图像数据等等
String 底层实现
Redis中,默认以SDS作为自己的字符串表示。只有在一些字符串不可能出现变化的地方使用C字符串。
SDS源码定义如下:
struct sdshdr{
// 用于记录buf数组中使用的字节的数目
// 和SDS存储的字符串的长度相等
int len;
// 用于记录buf数组中没有使用的字节的数目
int free;
// 字节数组,用于储存字符串
char buf[];
//buf的大小等于len+free+1,其中多余的1个字节是用来存储’\0’的(‘\0’ 在c语言中占用一个字节的内存空间,也代表结束)。
};
SDS除了用来保存数据库中的字符串之外,SDS还被用作缓冲区(buffer),如AOF模块中的AOF缓冲区,以及客户端状态中的输入缓冲区
SDS 的存储示例:
使用SDS而不使用c语言的string的好处:
1、常数复杂度获取字符串长度:
SDS:只需要访问SDS的len属性就能得到字符串的长度,复杂度为O(1)。
2、杜绝缓冲区溢出:
Redis是C语言编写的,并没有方便的数据类型来进行内存的分配和释放(C++ STL String),必须手动进行内存分配和释放。
对于字符串的拼接、复制等操作,C语言开发者必须确保目标字符串的空间足够大,不然就会出现溢出的情况。
当使用SDS的API对字符串进行修改的时候,
API内部第一步会检测字符串的大小是否满足。
如果空间已经满足要求,那么就像C语言一样操作即可。如果不满足,则拓展buf的空间
之后再进行操作。每次操作之后,len和free的值会做相应的修改。
扩展buf空间策略:
修改之后总长度len<1MB: 总空间为2*len+1;
修改之后总长度len>=1MB: 总空间为len+1MB+1。
换句话说,预分配的空间上限是1MB,尽量为len。
3、减少修改字符串时带来的内存重分配次数
当执行字符串长度缩短的操作的时候,SDS并不直接重新分配多出来的字节,而是修改len和free的值(len相应减小,free相应增大,buf的空间大小不变化),避免内存重分配。
SDS也提供直接释放未使用空间的API,在需要的时候,也能真正的释放掉多余的空间。
4、二进制安全
C字符串除了末尾之外不能出现空字符,否则会被程序认为是字符串的结尾。这就使得C字符串只能存储文本数据,而不能保存图像,音频等二进制数据
使用SDS就不需要依赖控制符,而是用len来指定存储数据的大小,所有的SDS API都会以处理二进制的方式来处理SDS的buf的数据。程序不会对buf的数据做任何限制、过滤或假设,数据写入的时候是什么,读取的时候依然不变。
总结
C字符串 |
SDS |
获取字符串长度的复杂度为O(N) |
获取字符串长度的复杂度为O(1) |
API是不安全的,可能会造成缓冲区溢出 |
API是安全的,不会造成缓冲区溢出 |
修改字符串长度N次必然需要执行N次内存重分配 |
修改字符串长度N次最多需要执行N次内存重分配 |
只能保存文本数据 |
可以保存文本或者二进制数据 |
可以使用所有库中的函数 |
可以使用一部分库的函数 |
String应用场景
Session + Redis 实现Session共享
做计数器,计算文档浏览量。INCR article:readcount:{文章id} GET article:readcount:{文章id}
分布式锁
线程1:SETNX product:10001 true//返回1代表锁获取成功
线程2:SETNX product:10001 true//返回0代表所获取失败
为什么不用hash存储呢?
如果想获取一个对象数据(user1)的name,那么需要把user1的所有数据拿出,在单独获取name;如果用STRING格式,那么只需要取出user:1:name数据即可。
常用命令的使用
redis数据写命令Set,相当于数据插入
redis 127.0.0.1:6379> set name zlh
--返回值: ok,说明插入成功。如果当前name存在值则覆盖替换原有的value值。
redis数据读命令Get,获取数据
redis 127.0.0.1:6379> get name
--返回值: "zlh" ,如果当前key没有value值,则返回null
redis数据追加命令Append,追加数据
redis 127.0.0.1:6379> append name ' is my friend'
--返回值:"zlh is my friend" ,如果当前key的value有值则附加到原有string后面,如果没有则写入。
redis数据删除
redis 127.0.0.1:6379>del name
redis数据读写操作命令GetSet,获取原有value值的同时写入新的value值
1、redis 127.0.0.1:6379>getset name zlh
--返回值:"zlh is my friend",这里返回的是原有name的value值,同时又给name的value设置新值zlh。
此时name的值真实值为zlh
2、redis 127.0.0.1:6379>get name
--返回值:zlh ,因为上面getset给name的value设置值为zlh。
redis数据加法计算命令incr,incrby,
数据加法运算,incr为+1内置运算,incrby为+n自设n运算
1、redis 127.0.0.1:6379>incr name
---返回值:“数据不是整型或数据超出64位有符号整形数据范围” ,由于原有name的value为"zlh",所以不能转换为整型,故报异常。
2、redis 127.0.0.1:6379>incr age
----返回值:1,由于不存在age的key与value值,但是默认age为key值为0进行+1运算。
3、redis 127.0.0.1:6379>incr age
---返回值:2,由于上一行代码给age赋值为1,这里incr命令进行+1运算,故返回值为2。
4、redis 127.0.0.1:6379>incrby age 10
---返回值:12 ,因为原有age是2,这里+10故为12。
redis数据减法计算命令decr,decrby,
数据减法运算,decr为-1内置运算,decrby为减n自设n运算
1、redis 127.0.0.1:6379>decr name
--返回值:“数据不是整型或数据超出64位有符号整形数据范围” ,由于原有name的value为"zlh",所以不能转换为整型,故报异常。
2、redis 127.0.0.1:6379>decr age
--返回自:11,因为原有age的value值为12,这里decr是自减1的意思,故为11。
3、redis 127.0.0.1:6379>decrby age 10
--返回值:1,因为原有age为11,这里-10,故为1。
redis获取string长度的命令strlen
redis 127.0.0.1:6379>strlen name
--返回值:3,因为name的value值为zlh,故长度为3,如果该key或者value不存在,则返回0。
redis设置value值并设置过期时间命令setex(单位秒)
redis 127.0.0.1:6379>setex sex 20 male
---返回值:ok,设置key为sex的value值为male,缓存的过期时间为20s。
redis 127.0.0.1:6379>ddl sex
---返回值: 剩余过期时间,0为已过期,-1为永不过期。
redis 127.0.0.1:6379>get sex
---返回值:male,说明此时为没有过期,当已经过期此处返回数据为null。
redis赋值判断原值是否存在,存在不赋值,返回0;不存在才赋值,返回1;命令setnx
redis 127.0.0.1:6379>setnx name Tom
---返回值:0,因为name的原有value为zlh,存在值则不赋值。
redis 127.0.0.1:6379>gete name
---返回值:zlh,因为有值,故上面赋值为tom失败,返回0。
redis 127.0.0.1:6379>setnx phone 18501733702
---返回值:1,赋值成功,因为原来不存在phone的key与value。
redis 127.0.0.1:6379>get phone
---返回值:18501733702,说明上面的setnx赋值成功。
redis字符串替换赋值,从指定位置开始替换,命令setrange
redis 127.0.0.1:6379>setrange phone 9 123
--返回值:12,12为字符串长度,11位号码变成了12位。因为从第9位开始替换,替换到原有字符串的最后一位还没有替换完毕,所以在最后面添加啦一位设置为3。
redis 127.0.0.1:6379>get phone
---返回值为:185017337123
redis 127.0.0.1:6379>set phone 1
---这里为了下面说下setrange的其他特性,把电话设置为1.
redis 127.0.0.1:6379>setrange phone 3 aaa
---返回值为:6,因为原有phone的value值为1,不到三位,用0*00替换2位,所以要添加2为才能替换第三位后面的值为aaa。
redis 127.0.0.1:6379>get phone
---返回值:1\*00\*00aaa。理解下上面的操作就知道这里为什么是这样的返回值了
redis截取字符串,从下标为n开始截取到n或n+1,类似c#中的substring,命令getrange
redis 127.0.0.1:6379>set phone 18501733701
----方便下面操作
redis 127.0.0.1:6379>getrange phone 1 5
---返回值:85017,因为getrange是从下标为1开始截取截取到下标为5,这里包含下标为5的值。
redis 127.0.0.1:6379>getrange phone 0 0
---返回值:1,从下标为0开始截取,截取到下标为0,包含下标为0。故返回值为1。
redis 127.0.0.1:6379>getrange phone 10 13
--返回值为:1,此号码下标直到10的11位号码,从10开始截取,截到第13位,后2位不存在忽略,只返回第10位。故返回干净的1。
redis批量操作修改及读取string数据,
命令mget,批量读取,命令mset,批量赋值,
命令msetnx,带事务性的赋值,发现有一个key已经存在,所有事务回归,不做赋值处理操作
redis 127.0.0.1:6379>mset name zlh age 30
---返回值:ok,这里设置了 key为name和age的value分别为zlh,30
redis 127.0.0.1:6379>mget name zlh
---返回值:1>zlh 2>30
redis 127.0.0.1:6379>msetnx name Jim address China
---返回值为:0,没有做任何修改,因为key(name)已存在。
redis 127.0.0.1:6379>mget name address
---返回值:1>zlh 2>null
---这里看到adress空null,说明 mestnx 事物回归
redis 127.0.0.1:6379>msetnx address China,hobbies sports
--返回值为:1,插入成功
redis 127.0.0.1:6379>mget address hobbies
---返回值:1>China 2>sports
Redis 数据类型 String的更多相关文章
- redis数据类型[string 、list 、 set 、sorted set 、hash]
1. Keys redis本质上一个key-value db,所以我们首先来看看他的key. 首先key也是字符串类型,但是key中不能包括边界字符:由于key不是binary safe的字符串, ...
- Redis数据类型--string
在Redis中支持丰富的数据类型的存储系统,包括:字符串(string),散列(hashes),列表(lists),集合(sets),有序集合(sorted sets),与范围查询,bitmaps,h ...
- 【Redis学习之四】Redis数据类型 string
环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 FTP:Xftp4 jdk8 redis-2.8.18 一.redis客户端基础命令1.帮 ...
- Redis 数据类型String 使用
字符串是Redis中最基本的数据类型,它能够存储任何类型的字符串,包含二进制数据.可以用于存储邮箱,JSON化的对象,甚至是一张图片,一个字符串允许存储的最大容量为512MB.字符串是其他四种类型的基 ...
- Redis数据类型String
set和get Set带空格的字符串值,这时候就需要使用双引号了,否则会出错 getset getset设置某个key-value,然后把设置之前的值返回来 incr,incrby 和 decr,de ...
- redis数据类型及使用场景
Redis数据类型 String: Strings 数据结构是简单的key-value类型,value其实不仅是String,也可以是数字. 常用命令: set,get,decr,incr,mge ...
- Redis 数据类型总结—String
1.1 数据类型 Redis常用五种数据类型:string, hash, list, set, zset(sorted set). Redis内部使用一个redisObject对象来 ...
- Redis学习-string数据类型
Redis 是一个开源的使用 ANSI C 语言编写.支持网络.可基于内存亦可持久化的日志 型.Key-Value 数据库. redis提供五种数据类型string,hash,list,set及sor ...
- Linux+Redis实战教程_day02_3、redis数据类型_4、String命令_5、hash命令_6、java操作redis数据库技术
3. redis数据类型[重点] redis 使用的是键值对保存数据.(map) key:全部都是字符串 value:有五种数据类型 Key名:自定义,key名不要过长,否则影响使用效率 Key名不要 ...
- 缓存数据库-redis数据类型和操作(string)
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合) 一:String(字符串) string是redis ...
随机推荐
- nodejs实现页面的增删查
一.在mong0db.js中写如下代码 1.导入 const mongoose = require("mongoose"); // 建立数据库连接 mongoose.connect ...
- api接口基础Day1
精华笔记: String: String的常用方法: length():获取字符串的长度(字符个数) trim():去除当前字符串两边的空白字符 toUpperCase()/toLowerCase() ...
- django_模型层及ORM介绍
一.模型层介绍 1.作用:负责跟数据库之间进行通信. 2.django通过驱动mysqlclient与mysql数据库进行通信,所以需要先安装.版本需要是1.3.13以上. 如果直接安装报错,可以直接 ...
- js字符串常用的方法
1. charAt( ) 获取指定下标处的字符 let str = 'hello' console.log(str.charAt(0));//h 2. charCodeAt 获取下标出的字符的Un ...
- 【Unity】检测目标是否在视线范围内(附视线范围扇形画法)
检测目标是否在视线范围内(附视线范围扇形画法) using UnityEngine; public class Test_CanSeeTarget : MonoBehaviour { public G ...
- 8、HTTP Cookie管理器
如果有需要加的cookie 就选择添加 如果没有特殊的 就默认就好了 第一次访问是没有cookie的 会话 session Cookie 是明文的 Session id 是保存在cookie里 ...
- 【原创】解决Multiple dex files define问题的思路
Multiple dex files define Landroid/support/v4/media/MediaMetadataCompat$Builder; 工作中我们可能会遇到各种 muxtip ...
- Delphi数据库备份
此处代码只是测试代码,仅仅是测试 //环境:D7+SQL Server 2008 1 unit Unit1; 2 3 interface 4 5 uses 6 Windows, Messages, S ...
- C#中Socket连接请求的超时设置
C#中Socket连接请求的超时设置 <转载> C#中, 对于Socket的请求,无论是同步还是异步,都没有提供超时机制,SendTimeout,ReceiveTimeout均无用.. 对 ...
- dockerflie
FROM newbe36524/aspnet:5.0-buster-slim AS base ENV TZ=Asia/Shanghai WORKDIR /app EXPOSE 3400 3400 RU ...