redis笔记一

如果图片显示有问题,欢迎访问我的语雀链接:https://www.yuque.com/u28057058/kfwbwy/hakzvxg0i36a69oc?singleDoc#



redis基本命令


  1. 连接redis客户端
redis-cli -h x.x.x.x -p 6379
  1. 如果报错(error) NOAUTH Authentication required.需要权限验证
  2. 

  3. 使用命令AUTH [password] ,password为你设置的redis密码
  4. 沟通状态,查看命令
  5. 连接到客户端之后,输入ping,redis返回pong。表示redis能够正常运行。
  6. 

  7. 切换库命令:select db
  8. redis默认有16个库,下标0-15。刚进去的时候默认在0库。




  1. dbsize 查看当前库所有拥有的key数量




  1. type name : name为key的名字。查看key所存的value的类型



  1. keys * : * 为匹配任意字符,这个命令的意思是返回当前库所有的key



  1. ttl :查看key所剩的生命周期。声明周期以秒为单位。
  2. 返回-1 说明当前key 永不过期



  1. 返回-2 说明当前key已经过期
  2. 



Redis对象

Redis Object


redis是键值对存储(key-value),key和value在redis里面都被抽象为对象

在 Redis 中,键(Key)只能是一个字符串对象,用于唯一标识一个数据项。Redis 中的键是以字节数组的形式存储的,可以是任意长度的字符串(字符串的长度影响底层的编码方式,后面会讲到),但是建议使用较短的字符串作为键,以减少内存占用和提高性能。

值(Value)是 Redis 中存储的数据对象,可以是String、List、Set、Hash、ZSet等多种数据类型。Redis 中的值可以是任意长度的二进制数据,因此可以存储各种类型的数据,包括文本、图片、音频、视频等。

需要注意的是,Redis 中的键和值都是以字节数组的形式存储的,因此在使用时需要进行序列化和反序列化操作。Redis 提供了多种序列化和反序列化方式,包括 JSON、MessagePack、Protobuf 等,可以根据实际需求选择合适的方式。


redis的Object源码结构


typedef struct redisObject {
unsigned type:4; // 对象类型
unsigned encoding:4; // 对象编码方式
unsigned lru:LRU_BITS; // 对象最近访问时间
int refcount; // 对象引用计数
void *ptr; // 对象值指针
} robj;
  1. type 字段表示对象的类型,包括字符串、列表、哈希表、集合、有序集合等多种类型。
  2. encoding 字段表示对象的底层编码方式,使用object encoding [key] 可以看到对应的编码方式
  3. lru 字段表示对象的最近访问时间,用于实现 Redis 的 LRU 策略。
  4. refcount 字段表示对象的引用计数,用于实现 Redis 的内存回收机制。
  5. ptr :内容指针,指向对象的值,可以是字符串、列表、哈希表、集合、有序集合等多种类型的值。



redis实际操作的主要有6个Redis对象,他们底层依赖一些数据结构,包括字符串、跳表、哈希表、压缩

列表、双端链表等,不同对象可能有依赖相同数据结构。接下来我们会一一讲到。



Redis-String

String是什么?


String也就是字符串,他是redis中最常见的的基本数据对象,他最大可存储512MB的数据。但是我们也可以定制他的大小,我们可以通过redis配置项proto-max-bulk-len 来修改它的大小。但是我们一般不会去修改它。




使用场景


一般可以用来存字节数据、文本数据、序列化后的对象数据等。

也就是说只要是字符串,都可以往里存。再具体点的例子:

  1. 缓存场景,Value存Json字符串等信息
  2. 计数场景,因为Redis处理命令是单线程,所以执行命令的过程是原子的。因此String数据类型适

合计数场景,比如计算访问次数、点赞、转发、库存数量等等。



常见操作

1. SET


语法:SET key value

功能:设置一个key的值为特定的value,成功则返回OK。

String对象的创建或者更新都是该命令。

127.0.0.1:6379>SET WLH qxaw
OK

Set命令很重要,这里多讲几个扩展参数:

  1. EX second:设置键的过期时间为多少秒。
  2. PX millisecond:设置键的过期时间为多少毫秒。
  3. NX:SET key value NX 命令用于向 Redis 中设置一个键值对,当且仅当该键不存在时才会设置成功。如果键已经存在,则该命令不会执行任何操作。拓展:(可以使用 SET key value NX EX seconds 命令来实现分布式锁。具体来说,可以将 key 参数设置为锁的名称,将 value 参数设置为一个唯一的标识符,将 NX 参数设置为保证原子性,将 EX 参数设置为锁的过期时间。)
  4. XX:只在键已经存在时,才对键进行设置操作
127.0.0.1:6379 SET WLH qxaw NX
(nil)


2. SETNX


SETNX是Redis中的一个常见命令,用于设置键的值,当且仅当键不存在时。下面是SETNX的常见操作:


  1. 如果键不存在,执行SETNX key value,设置键key的值为value。
  2. 如果键已经存在,SETNX不会对键进行任何操作,保持键原有的值不变。
  3. SETNX返回一个整数值,表示操作的结果:如果键被成功设置,返回1;如果键已经存在,返回0。

设置成功:

127.0.0.1:6379> SETNX mykey "Hello Redis"
(integer) 1

设置失败:

127.0.0.1:6379> SETNX mykey "Hello Redis"
(integer) 0


3. DEL


DEL命令用于删除Redis中的一个或多个键。它的语法如下:

DEL key [key ...]

其中,key是要删除的键的名称。可以一次指定多个键进行删除。

删除单个键:

127.0.0.1:6379> DEL mykey
(integer) 1

删除多个键:

127.0.0.1:6379> DEL key1 key2 key3
(integer) 3
  1. 在第一个示例中,DEL mykey命令将删除键mykey,并返回整数1表示成功删除了一个键。
  2. 在第二个示例中,DEL key1 key2 key3命令将删除键key1、key2和key3,并返回整数3表示成功删除了三个键。
  3. 请注意,删除键操作是永久性的,一旦执行DEL命令,键及其对应的值将被立即删除,无法恢复。


4. GET


语法:GET key

功能:查询某个key,存在就返回对应的value,如果不存在返回nil。

127.0.0.1:6379>get strniuniu
"cat"
127.0.0.1:6379>get strmart
(nil)



5. MGET


语法:MGET key [key....]

功能:一次查询多个key,如果某个key不存在,对应位置返回nil。

127.0.0.1:6379>MGET strniuniu strmart
1)"cat"
2)(nil)



底层操作


String底层有三种编码方式,INT,EMBSTR,RAW



  1. INT编码:可以long表示的整数就以这种编码存储;(非整数类型,比如float类型数据首先会转成字符串,然后判断该字符串的大小是否小于等于阈值字节或者大于阈值字节。小于使用EMBSTR编码,大于使用RAW编码)
  2. EMBSTR编码:如果字符串小于等于阈值字节,使用EMBSTR编码;
  3. RAW编码:字符串大于阈值字节,则用RAW编码。

这个阈值字节在源码里是用常量OBJ_ENCODING EMBSTR SIZE LIMIT:来表示,redis3.2版本之前是

39字节,redis3.2版之后是44字节。


EMBSTR和RAW都是由redisObjectSDS两个结构组成,它们的差异在于,EMBSTR下redisObject和

SDS是连续的内存,RAW编码下redisobject和SDS的内存是分开的

EMBSTR优点是redisObjecti和SDS两个结构可以一次性分配空间,

缺点在于如果重新分配空间,整体都需要再分配,所以EMBSTR设计为只读,任何写操作之后EMBSTR都会变成RAW,理念是发生过修改的字符串通常会认为是易变的。(也因为阈值字节大小的限制,更容易遇到重新分配大小的情况。因为底层实现是连续的内存空间,所以重新分配内存的代价是比较大的,所以综合考虑使用只读模式)


EMBSTR内存结构:



RAW内存结构:



随着我们的操作,编码可能会转换:

  1. INT->RAW:当存的内容不再是整数,或者大小超过了Iong的时候,
  2. EMBSTR->RAW:任何写操作之后EMBSTR都会变成RAW,原因前面有解释。

我们注意到,字符串编码EMBSTR和RAW都包含一个结构叫SDS,它是Simple Dynamic String的缩

写,即简单动态字符串,这是Redis内部作为基石的字符串封装,十分重要,下面我们详细介绍下

SDS.


SDS


SDS(Simple Dynamic String)是Redis中用于字符串存储的动态字符串实现。SDS是一种自定义的字符串类型,用于替代C语言中的传统字符串表示。


Redis中SDS分为sdshdr8、sdshdr16、sdshdr32、sdshdr64,它们的字段属性都是一样,区

别在于应对不同大小的字符串,我们以sdshdr8为例:



其中有两个关键字段,

  1. len字段表示SDS中存储的字符串的字节长度,即字符串占用的内存大小。这个字段的值等于实际存储在buf数组中的字节数。(请注意len不是表示存储字符串的长度,而是实际字符串占用的大小),
  2. alloc字段表示为字符串分配的实际内存大小,它通常会比字符串的长度(len字段)大,其中包含了一定的预留空间。这个预留空间可以用于未来字符串长度的扩展,以减少频繁的内存重分配操作,提高性能。
  3. 这两个字段的差值(alloc-len)就是预留空间的大小。
  4. flags则是标记是哪个分类,比如sdshdr8的分类 #define SDS_TYPE_8 1。
  5. buf[]为一个字节数组,存储字符串数据。

在redis中字符串的追加和长度计算很常见,所以这两个操作不应该成为性能的瓶颈,所以redis封装了sds字符串结构

  1. 在redis中怎么进行字符串的追加。使用append命令
127.0.0.1:6379> SET mykey "Hello"
OK

127.0.0.1:6379> APPEND mykey " World"
(integer) 11

127.0.0.1:6379> GET mykey
"Hello World"
  1. 让我们来根据sds的结构来理解一下redis中字符串的追加操作的步骤

sds的结构



1.增加长度字段len,快速返回长度;

2.增加预留空间(alloc-len),为后续追加数据留余地;

3.不再以'\0'作为判断标准,二进制安全。(传统C语言的字符串会以空字符'\0'作为截断标志,如果我们在字符串中不小心存入一个空字符'\0',那么他就会被C语言当成字符串的结尾从而被截断。这就是二进制不安全。



那么因为在sds中,不在以'\0'作为字符串的结尾标志,而是以len的大小从buf数组里读出len位。所以他是二进制安全。也正是他的这个二进制安全性,使得SDS可以存储任意二进制数据,包括文本字符串和非文本数据

包括文本字符串、图像数据、序列化对象等)

科普一下什么是空字符:


空字符(null character),在C语言中通常表示为\0,是一个特殊的控制字符。它的ASCII码为0,也被称为NUL字符。

空字符并不代表空格或空白位置,而是用于表示字符串的结束标志。在C语言中,字符串是由一系列字符组成的,以空字符作为结尾。空字符告诉程序字符串的结束位置。

空字符在字符串中起到了重要的作用,它标志着字符串的结束,帮助C语言函数正确识别字符串的边界。

在C语言中,字符串通常使用字符数组来表示,以空字符结尾。例如,"Hello"这个字符串实际上是由5个字符组成的,最后以空字符结尾。其存储形式为{'H', 'e', 'l', 'l', 'o', '\0'}

需要注意的是,空字符是一个不可打印字符,它在字符串中不会显示出来,但它是字符串结束的标志。


这里可能会想,SDS可以预留空间,那么预留空间有多大呢,规则如下:

  1. len小于1M的情况下,alloc=2倍len,即预留len大小的空间;
  2. len大于1M的情况下,alloc是1M+len,即预留1M大小的空间.
  3. 简单来说,预留空间为min(len,1M)



Redis-List





0个评论
点击登录,快来和大家讨论吧~
表情
图片
暂无评论
星河梦
作者分享
问题描述 我们评测一个功能是否正确,应该怎么写测试呢?特别是在AI时代,不人工review代码的情况 如何更好的使用测试来验收代码呢 具体疑问 平时都用AI写代码,随着需求增加,每次生成的代码都看不过来,只能借助AI生成测试来验收一下。但是测试也是AI生成的,我并不知道AI生成的测试是否符合我的需求,我也不太清楚,应该生成哪几种类型的测试才能更好的评估我们开发的功能。 已有理解 目前让AI写的有单元测试,集成测试,但是总感觉不太安稳,因为都是AI写的 预期目标 想知道在大厂规范下的测试一般都是怎么设计的。
4
时隔一年,又回来看到这个帖子,真是感慨万千啊! 这一年里因为刚毕业进入一家外包,导致工作一直没有价值感和认同感。这一年基本上都是在焦虑中度过的。 终于在今年七月份受一个以前认识的老板的邀请前往深圳创业。投了一万块钱。结果被白嫖试用期三个月。在转正的时候把我裁员了。股权也是一元回购,理由是公司没有盈利,属于负资产状态。 之后独自一人在深圳的出租屋里度过了我人生中第一次失业的低谷。这段时间里面报复性熬夜,常常失眠,回想起这个月那个老板对我的PUA,常常感到害怕和懊悔。之后一想到这些事情就有点惊恐发作了。 后面慢慢调整状态,明白再这样下去不行。开始整理以前项目经历,背诵八股,积极投递简历。经历两个星期的投递,在十一月底找到两份工作。 一份是13.5k的钉钉外包,一份是10.5k的自研小厂。由于毕业的第一份工作就是一份外包,所以对于外包留下了阴影,也就抵挡住了想去大厂看看的欲望,最终选择了小厂。 也不知道这个选择对不对,反而现在时常回想起当时的决定是否正确。
5
钉钉外包建议去吗?24年双非毕业,从来没去过大厂。 做AI agent方向的。这个ai让我挺心动的 和易宝软件签的合同。搜一下易宝发现风评不是很好。 然后就是近期每天需要加班到十点左右,单休。 薪资是13.5k。试用期六个月 然后现在有一家小公司,大概七十多号人,做移动app的。岗位是服务端开发,需要兼顾JAVA和Python,做点ai客服之类的功能。 给的是10k,正常双休。也有年终奖,但是说得看绩效评估。试用期六个月。
2
24年七月毕业,进了一家银行外包。薪资七八千,出差性质,技术老旧,如何破局?🙂
1
公司接口任务完成
0
下载 APP