`C`语言中因为字符串内部没有记录长度,所以如果扩充字符串非常容易造成**缓冲区溢出(buffer overflow)**。
请看下面这张图,假设下图就是内存里面的连续空间,可以很明显的看到,此时`wolf`和`Redis`两个字符串之间只有三个空位,那么这时候如果我们要将`wolf`字符串修改为`lonelyWolf`,那么就需要`6`个空间,这时候下面这个空间是放不下的,必须要重新申请空间。但是假如说程序员忘了申请空间,或者说申请到的空间依然不够,那么就会出现后面的`Redis`字符串中的`Red`被覆盖了:

同样的,假如要缩小字符串的长度,那么也需要重新申请释放内存。否则,字符串一直占据着未使用的空间,会造成**内存泄露**。
`C`语言避免缓存区溢出和内存泄露完全依赖于人为,很难把控,但是使用`sds`就不会出现这两个问题,因为当我们操作`sds`时,其内部会自动执行**空间分配策略**,从而避免了上述两种情况的出现。
#### 空间预分配
空间预分配指的是当我们通过`api`对`sds`进行扩展空间时,假如未使用空间不够用,那么程序不仅会为`sds`分配必须要的空间,还会额外分配未使用空间,未使用空间分配大小主要有两种情况:
* 假如扩大长度之后的`len`属性小于等于`1MB`(即 1024 \* 1024),那么就会同时分配和`len`属性一样大小的未使用空间(**此时`buf`数组已使用空间 = 未使用空间**)。
* 假如扩大长度之后的`len`属性大于`1MB`,那么就会分配`1MB`未使用空间大小。
执行空间预分配策略的好处是**提前分配了未使用空间备用后,就不需要每次增大字符串都需要分配空间,减少了内存重分配的次数。**
#### 惰性空间释放
惰性空间释放指的是当我们需要通过`api`减小`sds`长度的时候,程序并不会立即释放未使用的空间,而只是更新`free`属性的值,这样空间就可以留给下一次使用。而为了防止出现内存溢出的情况,`sds`单独提供给了`api`让我们在有需要的时候去真正的释放内存。
- Redis 为什么这么快
- 什么是 Redis
- Redis 的安装
- Redis 到底有多快
- Redis 是单线程还是多线程
- Redis 为什么选择使用单线程来执行请求
- 什么是 IO 多路复用机制
- Redis 中 I/O 多路复用的应用
- 一个简单的字符串,为什么 Redis 要设计的如此特别
- Redis 的 9 种数据类型
- 二进制安全字符串
- sds 空间分配策略
- sds 和 C 语言字符串区别
- sds 是如何被存储的
- type 属性
- encoding 属性
- 通过牺牲速度来节省内存,Redis 是觉得自己太快了吗
- 什么是压缩列表
- ziplist 的存储结构
- entry 存储结构
- ziplist 数据示例
- ziplist 连锁更新问题
- 为了加快速度,Redis 都做了哪些“变态”设计
- 列表对象
- linkedlist
- linkedlist 和 ziplist 的选择
- quicklist
- 列表对象常用操作命令
- Redis 中哈希分布不均匀该怎么办
- 哈希对象
- hashtable
- ziplist
- ziplist 和 hashtable 的编码转换
- 哈希对象常用命令
- 同一份数据,Redis 为什么要存”两次”
- 五种基本类型之集合对象
- intset 编码
- 集合对象常用命令
- 五种基本类型之有序集合对象
- skiplist 编码
- ziplist 编码
- ziplist 和 skiplist 编码转换
- 有序集合对象常用命令
- 要想用活 Redis,Lua 脚本是绕不过去的坎
- 发布与订阅
- 基于频道的实现
- 基于模式的实现
- Lua 脚本
- Lua 脚本的调用
- Lua 脚本中执行 Redis 命令
- Lua 脚本摘要
- Lua 脚本文件
- 脚本异常
- 作为一款内存数据库,为什么断电后 Redis 数据不会丢失
- Redis 持久化机制
- RDB 持久化机制
- AOF 持久化机制
- 内存耗尽后 Redis 会发生什么
- 内存回收
- 过期策略
- 8 种淘汰策略
- LRU 算法
- LFU 算法
- 不能回滚的 Redis 事务还能用吗
- Redis 有事务吗
- Redis 事务实现原理
- Redis 事务 ACID 特性
- watch 命令
- watch 命令的作用
- watch 原理分析
- Redis 为什么不直接用 master-slave 集群
- Redis 集群方案
- 主从复制
- 配置一主两从 master-slave 集群
- 主从复制原理分析
- 主从服务的不足之处
- Sentinel(哨兵)机制为什么从神坛滑落
- 哨兵 Sentinel 机制
- Sentinel 原理分析
- 配置 Sentinel 集群
- Sentinel 机制实战
- Sentinel 机制的不足之处
- Redis Cluster 集群凭什么成为了最终的胜利者
- Redis 分布式集群方案
- 客户端实现分片
- 中间代理服务实现分片
- Redis Cluster 方案
- 手动配置一个 Redis Cluster 集群
- Redis Cluster 集群常用命令
- 客户端如何使用 Redis Cluster 集群
- Redis Cluster 的不足
- 如何从 10 亿数据中快速判断是否存在某一个元素
- 缓存雪崩
- 缓存击穿
- 缓存穿透
- 布隆过滤器(Bloom Filter)
- 布隆过滤器的 2 大特点
- 布隆过滤器的实现(Guava)
- 布隆过滤器的如何删除