SDS

Redis研究-1.简单动态字符串

烈酒焚心 提交于 2020-03-26 12:12:21
3 月,跳不动了?>>> 我们知道,在C字符串中,底层的实现是使用c字符数组来实现的,但是在高性能以及内存安全方面,使用底层的c字符串是满足不了的,举个简单的例子,如果你使用strcat(s,s1)函数,如果在操作之前不判断s的空间是否能够容纳s1的内容,那么就很有可能导致内存溢出,而导致操作失败,因此,为了满足性能及内存安全方面的要求,Redis实现了SDS。 SDS的定义是(位于sds.h): struct sdshdr { // buf 中已占用空间的长度 int len; // buf 中剩余可用空间的长度 int free; // 数据空间,默认是使用C字符串的空字符结尾的 char buf[]; }; 其中每项的含义已经在注释中说明。 通过上面的定义,我们可以看到,sds与传统的c字符串做了几方面的优化: 在sds中,记录了“字符数组”的的长度len; 通过使用free可以实现预分配策略优化。 通过这两方面的优化,我们可以得到以下方面的提升: 在做需要设计到内存扩展方面的操作的时候,只要检查free属性,就可以很容易得到是否需要扩展内存,从而避免内存溢出; 在获取字符串长度方面,再也不用花费O(N)时间复杂度,只主要获得len属性就可以得到长度,时间复杂度变为O(1); 我们知道,C字符串和底层数组之间是有密切联系的,因此每次增加或者缩短一个C字符串

Redis研究-2.简单动态字符串操作

旧街凉风 提交于 2020-03-26 12:11:40
3 月,跳不动了?>>> 上一篇,讲了基本的Redis为什么要使用自己的SDS,以及使用SDS带来的好处,这一篇主要说说针对这个SDS,Redis封装了哪些操作,在看封装的函数之前,先看一下sds.h里面的一个申明:typedef char *sds;这个申明,在Redis的SDS中启到了非常重要的作用,这个字符指针是用于指向 sdshdr 的 buf 属性。因此,如果你要根据这个sds指针来求出SDS的首地址,你应该使用(s-(sizeof(struct sdshdr )))的方式就能得到。 在sds.h中定义了两个局限于本文件使用的两个函数,分别是获得sdshdr的len属性值,以及获得sdshdr的free值,分别是: 获得sdshdr的len属性 static inline size_t sdslen(const sds s) { struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->len; } 获得sdshdr的free属性 static inline size_t sdsavail(const sds s) { struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->free; } 同样,在这个头文件中

Redis 存储原理(1)

北慕城南 提交于 2020-03-11 22:58:29
Redis现在基本也算是后台开发的基础服务,基本像Mysql一样普遍在应用中使用了。我第一次接触的Nosql是memcache用来解决夸服务session共享问题。后来因为memcache无法持久化问题改为使用Redis。这次主要针对Redis做一个整理。 Redis数据类型 类型 特点说明 String 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB Hash Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。 List Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边) Set Redis 的 Set 是 string 类型的无序集合。集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1) ZSet 与Set不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序 HyperLogLog 在 2.8.9 版本添加是用来做基数统计的算法,HyperLogLog 的优点是,在输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的 Bitmaps 可做为 布隆过滤器 使用 GeoHash Redis 3.2 版本地理空间位置(纬度

回归单体模式——Istio 1.5 新特性解读

对着背影说爱祢 提交于 2020-03-06 22:15:07
Istio 1.5 是一个具有重大变革的版本。长久以来,面对社区对 Istio 的性能和易用性的诟病,Istio 团队终于正视自身的问题,在当前版本中彻底推翻了原有控制平面的架构,完成了重建。正如 Simplified Istio 文中所说: 复杂是万恶之源,让我们停止焦虑,爱上单体。 Istio 1.5 回归单体,无论架构和使用方式都发生了巨大变化。因此笔者决定对 1.5 的变化内容做深入解读,以便开发者可以更好的理解和学习新版本,为使用和升级提供参考。 参考: 官方文档, https://istio.io/zh/docs/ 概念 安装 任务 运维 参考 示例 特性介绍, https://www.servicemesher.com/blog/istio-1-5-explanation/ 架构调整 这部分主要分析 Istio 1.5 在架构上的调整,这也是该版本最核心的变化。主要包括重建了控制平面,将原有的多个组件整合为一个单体结构 istiod ;同时废弃了被诟病已久的 Mixer 组件。还对是否向后兼容的部分也做了说明,如果你要从 1.4.x 版本升级到 1.5 必须知道这些变化。 重建控制平面 官方使用的是重建(Restructuring)而不是重构(Refactoring)一词,可见其变化之大。在 Istio 1.5 中,控制平面将使用新的部署模式

聊一聊Redis之数据结构

依然范特西╮ 提交于 2020-03-06 16:38:28
基本数据结构 简单动态字符串 Redis中的字符串使用“简单动态字符串”(SDS)表示,无论是字符串值还是键底层都采用“简单动态字符串”。 free:未使用空间大小; len:字符串长度; buf:以空字符结尾的char数组。 为了减少内存重新分配次数,SDS做出了以下优化: 空间预分配:额外分配的未使用空间数量由以下公式决定: 如果对SDS进行修改之后,SDS的长小于1MB,那么程序分配和len 属性同样大小的未使用空间, 如果对SDS进行修改之后,SDS的长度将大于等千1MB, 那么程序会分配 1MB 的未使用空间。 惰性空间释放:程序并不立即使用内存重分配来回收缩短后多出来的字节,而是使用free属性将这些字节的数量记录起来,并等待将来使用。 链表 链表是Redis列表键实现之一,也是很多其他功能实现的基础,链表节点定义如下: 链表的完整结构体定义如下 head为表头指针; tail为表尾指针; len为链表长度计数器; dup为函数指针,用于复制链表节点所保存的值; free为函数指针,用于释放链表节点所保存的值; match为函数指针,则用于对比链表节点所保存的值和另一个输入值是否相等。 字典 字典将键和值进行关联,当哈希键中的键值对数量比较多,或者键值对中的元素比较大的时候,采用字典作为底层实现。字节的数据结构如下 哈希表结构dict中,table属性是一个数组

了解下Redis的SDS结构

泪湿孤枕 提交于 2020-03-04 18:31:21
SDS (简单动态字符串) sds是Redis里面的一种结构,通过它对字符串的操作进行了很多的优化操作。 SDS的结构定义 struct stdhdr { int len //记录buff数组中已使用字节的数量 int free //记录buff数组中未使用字节的数量 char buff[] //字节数组,用于保存字符串 } SDS的示例,见下图 free值为0, 表示这个SDS没有分配任何未使用空间。 len值为4, 表示这个SDS保存一个四字节长的字符串。 buff值为一个char类型数组,分别保存’L‘,’i','a','n' 4个字符,最后一个字节保存;’\0‘ SDS与C字符串的区别 C语言使用长度N+1的字符数组来表示长度为N的字符串,并且最后一个字符串总是空字符串’\0‘. ,而且它并不记录自身的长度信息,如果要获取,必须全部遍历;但SDS不一样,他有len属性记录了长度,所以获取长度的复杂度很高。 C字符串容易缓冲区溢出,而SDS的空间分配策略则不会,当需要操作字符串时,会先检测空间大小,如果不满足,则需要对空间做扩展。 C在对字符串做修改时,因为没有记录长度信息,所以需要频繁对内存做分配,而SDS通过free属性来记录未使用的空间,实现空间预分配和惰性空间释放。 #### 1 空间预分配 空间预分配用于优化SDS的字符串增长操作,当对SDS字符做修改时

见微知著 —— Redis 字符串内部结构源码分析

£可爱£侵袭症+ 提交于 2020-03-01 13:47:57
本篇我们开始讲字典 key 的内部结构,也就是 sds 字符串。首先它不是普通字符串,而是 sds 字符串,这个 sds 的意思是「Simple Dynamic String」,它的结构很简单,它是动态的,意味着可以支持修改。不过即使是这样简单的字符串结构,在结构设计上作者可是煞费苦心。 我们知道 C语言里面的字符串是以0x\0结尾,通常就说是以 NULL 结尾。它不包含长度信息,当我们需要获取字符串长度时,需要调用 strlen(s) 来获取长度,它的时间复杂度是 O(n),如果一个字符串太长,这个函数就太浪费 CPU了。 所以 Redis 不能这么干,它需要将长度信息使用单独的字段进行存储,这就需要一个额外的字段,这个字段也要占用存储空间。在日常使用中,小字符串才是大头,它的长度信息往往只需要 1byte 存储就可以了,可以表示最大长度为 255 的字符串。如果字符串再大一些,就需要 2byte,甚至是 3byte、4byte。Redis 会为不同长度的字符串选择不同长度的字段来表示长度信息。同时 Redis 为了可以直接使用标准C语言字符串库函数,sds 的字符串内容还是以 NULL 结尾,这会额外多占用一个字节的空间。 sds 是动态字符串,它需要支持追加操作,需要能扩充容量。如果字符串放置的比较紧凑,追加时,就需要重新分配新的更大的存储空间,然后进行内容的拷贝(不严格

Redis源码阅读笔记-动态字符串(SDS)结构

纵饮孤独 提交于 2020-02-29 20:21:17
Redis中采用自定义的结构来保存字符串,在 sds.h 中: /* Note: sdshdr5 is never used, we just access the flags byte directly. * However is here to document the layout of type 5 SDS strings. */ struct __attribute__ ((__packed__)) sdshdr5 { unsigned char flags; /* 3 lsb of type, and 5 msb of string length */ char buf[]; }; struct __attribute__ ((__packed__)) sdshdr8 { uint8_t len; /* used */ uint8_t alloc; /* excluding the header and null terminator */ unsigned char flags; /* 3 lsb of type, 5 unused bits */ char buf[]; }; struct __attribute__ ((__packed__)) sdshdr16 { uint16_t len; /* used */ uint16_t alloc; /*

抑郁症SDS测试题和抑郁症的表现症状自测

被刻印的时光 ゝ 提交于 2020-02-27 15:09:38
生活中我们有着这样那样的困难和坎坷,慢慢的心理总会有所阴霾,很多小伙伴觉得这很正常,心烦意乱乃人之常情,不需要处理,短期是不需要处理,如果时间久了那就会积劳成疾,就好比偶尔熬夜对身体没有影响,但是长时间就会引起各种并发症,游戏公告有句话说的好,适当游戏易脑,沉迷游戏伤身。接下来这3款抑郁症在线测试工具,可以让你清楚的知道自己是个什么状态。 抑郁症SDS测试题 https://www.zxgj.cn/g/yiyuzheng 抑郁症自评量表,简称SDS,一共有20个项目分为4个等级的测评,虽然这个测试简单有效,但是也是有局限性,对于文化水平不高,或者明显精神障碍的小伙伴效果不佳,该测试针对心理问诊时的初期筛选很有效,例如一开始不觉得自己有抑郁症的患者,或者抑郁症前兆的同学,没有其他精神障碍的情况下进行测试,主要起到预防,前期治疗的作用。目前应用于心理门诊的粗筛调研,如果你最近总是心情烦躁,心神不宁,那你可要注意了,也许你是个潜在的抑郁患者,那么这款SDS测试你就可以拿起了测试一下哦。 PHQ-9抑郁筛查量表 https://www.zxgj.cn/g/phq9 预防总是大于治疗,会有1+1>2的效果,因此数据测试筛选总是越多越好,如果症状轻或者不知道自己有没有小伙伴,不妨可以试试PHQ-9抑郁筛查表,该考量表相对其他测试内容较少,只有10个题,题目相对简单,适合长期筛查考量

sharding sphere 4.0.0-RC1版本 按年分表(后续优化)

故事扮演 提交于 2020-02-27 03:41:44
1. sharding sphere 4.0.0-RC1版本 按年分表(后续优化) 1.1. 概述 关于上一篇中 LogShardingAlgorithm 的 tables ,我原先是在第一次调用的时候初始化,这样做虽然能实现功能,但每次调用都会走这个if判断,虽然性能损耗不大,但我觉得这不是业务应该走的逻辑顺序,我的理想是在 LogShardingAlgorithm 被实例化后去自动初始化 tables 现在面对的问题是 LogShardingAlgorithm 的实例化是在Spring初始化中间执行的,且它本身的创建不是通过Spring的 @Component 等注解生成,而是通过反射实例化。若在实例化刚开始,也就是构造方法执行的时候执行初始化,那时候 applicationContext 还没有初始化完毕,拿不到环境参数,连 Datasource 也还没开始初始化 1.2. 解决方法 经过改造后,代码如下,单独拎出一个初始化方法,在类对象实例化后调用 /** * @author: laoliangliang * @description: 日志分片 * @create: 2020/1/2 10:19 **/ @Slf4j public class LogShardingAlgorithm implements PreciseShardingAlgorithm,