Redis

字符串 实现 使用SDS(简单动态字符串),SDS不仅可以保存字符串还可以保存二进制数据,获取长度的时间复杂度是O(1),SDS的API是安全的,比如拼接字符串不会造成缓冲区溢出,总的来说就是对数组封装,提供一系列方便操作的API。 字符串对象有三种编码:int、raw、embstr 整数:ptr从void*转换为long 短字符串(至于多短,每个redis版本不一样):分配一块连续空间保存redisObject和SDS 长字符串:分别为redisObject和SDS分配两个内存,redisObject.ptr指向SDS embstr如果要修改大小的话,只能重新分配空间。因此embstr实际上是只读的,当要修改embstr的长度,redis会先将其转换为raw再进行修改。 使用场景 缓存对象、常规计数(INCR)、分布式锁(SET-NX)、共享Session List 列表 List在使用上就是一个Deque双端队列,存字符串 实现 redis3.2之前:小列表使用压缩列表实现,大列表使用双向链表实现 redis3.2之后:使用quicklist实现 使用场景 消息队列: 保序:LPUSH+RPOP,但是RPOP需要轮询,浪费CPU性能,因此还提供了BRPOP阻塞式读取 处理重复:每条消息设置一个全局唯一ID,利用ID判断是否已经消费,List不会为消息生成ID,需要用户自己添加 保证可靠:BRPOPLPUSH,读取的同时将消息插入另一个List作为留存,如果用户处理消息时失败,下次从留存List重新读取 作为消息队列的缺点: 不支持消费者组 Hash 哈希 适合存储对象 实现 redis7.0之前:小Hash使用压缩列表,大Hash使用哈希表 redis7.0之后:小Hash使用listpack,大Hash使用哈希表 使用场景 缓存对象:一般可以用String+序列化存储对象,并将变化频繁的字段抽出来用Hash存储 Set 集合 实现 元素都是整数的小Set:整数集合 否则:哈希表 使用场景 点赞:保证每个用户只能点一次赞 共同关注(SINTER) 推荐关注(SDIFF) 抽奖(允许重复中奖SRANDMEMBER,不允许SPOP) 潜在风险:「并、交、差」的计算复杂度高,数据量大的情况下会阻塞redis。可以用从库进行计算,或交给客户端来自行处理,从而不阻塞主库 ZSet 有序集合 比Set多了一个score,按照score排序。ZSet不支持「差」运行 实现 redis7.0之前:小zset使用压缩列表,大zset使用跳表 redis7.0之后:小zset使用listpack,大zset使用跳表 使用场景 排行榜:score最大的前几个(ZREVRANGE),范围score内最小的前几个(ZRANGEBYSCORE) 电话排序:获取132、133开头的号码( ZRANGEBYLEX phone [132 (134 ),不要在分数不一致的 SortSet 集合中去使用 ZRANGEBYLEX和 ZREVRANGEBYLEX 指令,因为获取的结果会不准确 BitMap 实现 String 使用场景 签到统计:比如一年的签到只需要365个bit 判断登陆态:用户ID作为offset,如果ID是连续的,5000 万用户只需要 6 MB 的空间(5000万位) ...

九月 2, 2024 · by NOSAE

网络

tcp 报文 tcp 三次握手 客户端发送:SYN、随机序列号 x 服务端发送:SYN、ACK、随机序列号 y、确认应答号 x+1 客户端发送:ACK,可以携带数据 tcp 为什么不是两次握手 防止旧的 SYN 建立连接:如果只有两次握手,那么服务端收到 SYN 后直接进入 established 状态(此时可以发送数据),然后返回 ack 给客户端,如果这个 SYN 是旧的,那么最终客户端发现不是想要的 ack,就会发送 rst 断开连接,那么服务端又要去断开已经建立好的连接,浪费资源。 如果是三次握手,那么服务端不会直接进入 established。 同步序列号:初始化序列号是最重要的,所以客户端发送初始序列号 x(第一次握手),客户端需要得知服务端已经收到并且服务端发送初始序列号 y(第二次握手),服务端需要得知客户端已经收到(第三次握手) 如果第三次握手没发送到对端:本端也能直接发送数据,因为: 但这不说明只需两次握手,三次握手和和两次握手的区别在于第二次握手后,对端是否直接进入 established。 tcp keepalive keepalive 是 TCP 保鲜定时器,链接空闲时的心跳机制。 当超过一段时间之后,TCP 自动发送一个数据为空的报文给对方,如果对方回应了这个报文,说明对方还在线,链接可以继续保持,如果对方没有报文返回,并且重试了多次之后则认为链接丢失,没有必要保持链接。 tcp 四次挥手 客户端发送:FIN 服务端发送:ACK 服务端发送:FIN 客户端发送:ACK 客户端进入 TIME_WAIT,等待 2MSL(报文最大生存时间) 其中,客户端一直收不到第三次握手 FIN 的话,客户端有两种情况: 对于客户端调用 shutdown() 的情况,只关闭发送数据不关闭接收数据,因此客户端死等 对于客户端调用 close() 的情况,同时关闭发送和接收数据,长时间收不到 FIN 就会主动 close 服务端一直收不到第四次握手 ACK 的话(在这之前处于 CLOSED_WAIT,并且服务端调用 close(),发送了 FIN),就会主动 close。 ...

九月 2, 2024 · by NOSAE

在MacOS中运行k3s

k3s https://github.com/caicloud/kube-ladder 安装ubuntu家的multipass虚拟机 brew install multipass (镜像路径在/var/root/Library/Caches/multipassd/qemu/vault/images下) 创建一个虚拟机并启动 multipass launch -n k3s01 -c 2 -m 2G -d 16G 查看虚拟机 multipass list multipass info k3s01 进入虚拟机终端 multipass shell k3s01 设置root密码,更新apt sudo passwd apt-get update 数据卷,数据传输 multipass mount host-path vm-name:vm-path multipass umount vm-name multipass transfer host-file vm-name:vm-path 虚拟机操作 multipass start/stop/delete/purge vm-name 指定虚拟机初始化时的配置、执行的命令等 multipass launch -n vm-name --cloud-init config.yaml # config.yaml runcmd: - apt-get update # 更新包 - curl -sfL https://get.k3s.io | sh - # 安装k3s - echo "alias k=kubectl" >> ~/.bash_aliases 指定k3s启动时config的访问权限,使得在非root用户下也能kubectl管理k3s ...

九月 1, 2024 · by NOSAE

jekyll chrispy主题的语法

Headings H1 — heading {: .mt-4 .mb-0 } H2 — heading {: data-toc-skip=’’ .mt-4 .mb-0 } H3 — heading {: data-toc-skip=’’ .mt-4 .mb-0 } H4 — heading {: data-toc-skip=’’ .mt-4 } Paragraph Quisque egestas convallis ipsum, ut sollicitudin risus tincidunt a. Maecenas interdum malesuada egestas. Duis consectetur porta risus, sit amet vulputate urna facilisis ac. Phasellus semper dui non purus ultrices sodales. Aliquam ante lorem, ornare a feugiat ac, finibus nec mauris. Vivamus ut tristique nisi. Sed vel leo vulputate, efficitur risus non, posuere mi. Nullam tincidunt bibendum rutrum. Proin commodo ornare sapien. Vivamus interdum diam sed sapien blandit, sit amet aliquam risus mattis. Nullam arcu turpis, mollis quis laoreet at, placerat id nibh. Suspendisse venenatis eros eros. ...

八月 31, 2024 · by NOSAE

nju pa3

穿越时空的旅行 异常响应机制及CTE 实现异常响应机制 我们要实现操作系统的自陷功能,虽然中断的大致原理和流程上课都讲过,但不同操作系统有着不同的具体设计,因此在这之前有必要结合文档与源码过一遍我们框架代码中“异常响应机制”的流程 riscv对于中断与异常提供了各种令人眼花缭乱的CSR控制状态寄存器,我们这里涉及到的有: mtvec寄存器 - 存放了发生异常时处理器需要跳转到的地址 mepc寄存器 - 存放发生异常的指令地址,用与异常处理返回时能回到原本程序执行的位置 mstatus寄存器 - 存放处理器的状态 mcause寄存器 - 存放异常的种类 另外根据文档中提到 首先当然是对R的扩充, 除了PC和通用寄存器之外, 还需要添加上文提到的一些特殊寄存器 所以我们先给处理器添加上述的几个CSR typedef struct { word_t mcause; vaddr_t mepc; word_t mstatus; word_t mtvec; } riscv64_CSRs; typedef struct { word_t gpr[32]; vaddr_t pc; riscv64_CSRs csr; } riscv64_CPU_state; 定义好了需要到的寄存器后,接下来我们就结合nanos-lite的运行来分析中断响应流程吧~在此之前需要再次明确一下模拟器的各层的关系:am是硬件层(确切地说是抽象硬件,对操作系统屏蔽了架构的差异),nanos-lite是操作系统层。我们从nanos-lite的入口,main函数看起,其中中断相关我们只需要关注init_irq以及yield,先回忆一下,还记得文档说的那句话吗? 我们刚才提到了程序的状态, 在操作系统中有一个等价的术语, 叫"上下文". 因此, 硬件提供的上述在操作系统和用户程序之间切换执行流的功能, 在操作系统看来, 都可以划入上下文管理的一部分. init_irq里调用的cte_init,其实就是操作系统向硬件注册事件发生(如中断)的回调函数do_event,这个回调函数就是真正把异常交给操作系统处理的地方(要与异常处理入口函数区分开来),其中的参数为事件和相关的程序上下文。那么这个回调函数什么时候被调用呢,显然是异常发生的时候。 我们接着查看cte_init的代码,其功能简单地说就是保存异常处理入口函数地址,以及保存用户回调函数即上述的do_event,以便异常处理过程中时调用这个用户回调函数。其中异常处理入口函数是__am_asm_trap,这个函数在trap.S这个文件中用汇编语言实现,暂时不管,先接着看流程。 接下来在main函数的最后调用了yield,如果说init_irq描述如何处理异常,那么yield就是真正触发了一个异常(自陷),并进入之前注册的异常处理函数进行异常处理。yield只有两句汇编指令 li a7, -1 ecall 将异常种类存放到a7寄存器中,以及发起自陷,其中ecall会使得程序流程转到之前注册的异常处理入口函数中去执行,即__am_asm_trap,这里就得分析一下这个函数都干了些什么了: __am_asm_trap: ... jal __am_irq_handle ... mret 目前只关注运行流程,多余的代码先去除,__am_asm_trap简单来说是提供了统一的异常入口地址,主要作用是将csr和gpr的内容作为参数调用__am_irq_handle并在其返回后把csr和gpr的新值再存回去(值得一提的是,csr和gpr作为cpu的寄存器,am将他们包装在上下文结构中传给了操作系统,而不是让操作系统直接访问cpu,体现了处处都是抽象和屏蔽的艺术)。__am_irq_handle这个函数也是定义在抽象硬件层(am)中的,通过判断程序上下文内容(比如在riscv-nemu中通过分支mcause的值)来构造事件,最终将事件和上下文一并通过回调函数传给操作系统,开始真正的异常处理….至此从异常注册到异常触发及响应的流程分析就结束了,如果说PA3之前的工作还没对这些抽象硬件、操作系统层等形成认知,或者到了PA3这个部分依然存疑,建议一定要好好做这一小节的内容并去认真体会它是如何设计的,因为确实值得。 若理解了流程,剩下的填代码环节就是顺便的事情了。首先实现几条指令,csr的读写指令和ecall指令 INSTPAT("??????? ????? ????? 001 ????? 11100 11", csrrw , I, R(dest) = CSR(imm); CSR(imm) = src1); INSTPAT("??????? ????? ????? 010 ????? 11100 11", csrrs , I, R(dest) = CSR(imm); CSR(imm) |= src1); INSTPAT("0000000 00000 00000 000 00000 11100 11", ecall , I, ECALL(s->dnpc)); 其中两个新宏CSR, ECALL如下: ...

三月 1, 2023 · by NOSAE