Redis-数据结构与对象

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: <div class="markdown_views"><p>Redis中的数据结构分为: 字符串,链表,哈希,集合Set和有序集合</p><h2 id="sds">SDS</h2><h3 id="what">what</h3><p>Simple Dynamic String <br>用来代替C的原生字符串</p><h3 id="where-用在哪儿

Redis中的数据结构分为: 字符串,链表,哈希,集合Set和有序集合

SDS

what

Simple Dynamic String
用来代替C的原生字符串

where 用在哪儿

key,值中的字符串类型,以及AOF等缓冲区中

why 为啥要用

因为比C原生的字符串要好:
1. O(1)获取长度
2. 杜绝缓冲区溢出
3. 减少修改字符串时带来的内存重新分配次数
4. 二进制安全
5. 兼容部分C字符串函数

how 怎么做到的

基本结构:

public class SDS {
        // 占用长度 1满足了
    private int len;
    // 空闲,用来预留空间,减少重新分配次数
    private int free;
    // 数据 4满足了
    private byte[] buf;

    public SDS(int length){
        buf = new byte[length + 1];
        len = 0;
        free = length;
    }

    public SDS(String s){
        buf = new byte[s.length() + 1];
        System.arraycopy(s.toCharArray(), 0, buf, 0, s.length());
        // 5满足了
        buf[s.length()] = '\u0000';
        free = 0;
        len = s.length();
    }
}

该结构一眼看去,有一个len属性,于是上面why中的第1条满足了。
第二眼看去,居然真正的长度比实际的要多1,存放了’\u0000’。 卡卡,这个跟c原生的结构就一样了,因此5满足了
第三眼看去,用的是bute 而不是char, 这就说明了数据是按字节存储的,如果是char的话,就是带有规则的,而byte是纯粹的字节,提供了对二进制数据的支持,满足了4

修改SDS

看实现:

/**
     * 添加到末尾,如果空间不够,会重新分配
     * @param sds
     */
      public void sdscat(SDS sds){
        if(sds.len > this.free){
            byte[] temp = new byte[(this.len + sds.len) * 2 + 1];
            free = 0;
            System.arraycopy(this.buf, 0, temp, 0, this.len);
            System.arraycopy(sds.buf, this.len, temp, 0, sds.len);
            temp[this.len + sds.len] = '\u0000';
            this.len = (this.len + sds.len) * 2 + 1;
            this.buf = temp;
        }
    }

首先这里在添加到末尾的时候,如果是c语言则会造成脏数据,内存溢出这种情况,对于Java来说直接就是内存溢出异常了,不管怎么说都不行,因此实现的方式是先判断够不够,不够就扩展。
这样2满足了。

再看, 实际创建的长度,是需要的二倍+1, 1就是空字符了,二倍呢就是留着以后用的了,这个叫做预分配,是为了减少重新分配次数的一种办法。Java中ArrayList也是可以这样搞的。
除了预分配,还有懒回收,就是删除的空间先不回收,留着用。如下:

    public void sdstrim(byte a){
        // 不重新分配,只是增加free的值,删除char a后所有后面的前移,具体算法的复杂度在O(N^2)
    }

链表

提供节点重排, 灵活插入,顺序遍历的特性
主要用在列表键,发布订阅等功能中
不具体展开说了,很像Java的LinkedList.具有如下特性:
- 双头
- 无环
- 带表头和表尾指针,而不用遍历,使复杂度为O(1)
- 带长度计数器,不用遍历

哈希

hash键的实现之一

结构

联系到Java就是HashMap
Redis中一个字典对应多个HashTable, 一个HashTable对应多个Hash节点。
Java中,字典对应HashMap, 一个HashMap有多个Entry, Entry是一个单项链表,所以一个Entry会对应多个Entry节点。

算法

计算hash值,然后求索引,找到其所在的HashTable。
因为HashTable中的节点是链式的,所以把该值放到链的最前面。 如果是查询值,则会先根据所以找到对应的HashTable,然后遍历HashTable的节点找到具体的值。

其他

跳跃表

用于实现有序集合

整数集合

集合键的一种实现
该数据结构包含了存储数据的数组以及数据类型(int8, int16),
如果把长度不同的混存,就会引起升级的现象

压缩列表

用于列表键和哈希键
当值为小整数,或者短字符串,并且数量不多的时候会采用该数据结构。
是为了节约内存而设计的

对象

上面仅仅是介绍了一些底层的数据结构,但是Redis并没有直接使用这些数据结构,而是封装为了对象。用对象来封装键值。
一个对象的结构:

public class RedisObject{
    // 类型
    Enum type;
    // 编码
    Enum encoding;
    // 底层的数据结构
    *impl
}

type的取值:{字符串,列表,哈希,集合,有序集合}
encoding, 这个编码集的意思跟mysql中的整理有点像,不是字符集编码,是具体采用了什么底层数据结构{字典,双端列表,整数集合…}

对象与数据结构

  • 字符串 全int时用long, >39是SDS, <39时另外的算法
  • 列表 ziplist或者linkedlist
  • 哈希 ziplist(同样把键值对铺开紧密相连) hashtable
  • 集合 intset hashtable
  • 有序集合 ziplist(用紧挨的连个值一个表示成员,一个表示分值) skiplist

回收与共享

对象中有refcount作为引用计数器,每多一个引用+1.为0时被释放,可以看做最简单的GC。
另外想要对象共享时也可使用此方法,指向同一个对象,只是增加计数器。但是只有由int型的小字符串才能共享,这是因为共享对象太复杂,那么验证共享对象是否是目标对象的操作就会很耗CPU。

空转时长

对象有多久没被访问了。
主要是redis的GC算法来使用的,会优先释放lru较大的数据。

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
9天前
|
XML JSON NoSQL
Redis的常用数据结构之字符串类型
Redis的常用数据结构之字符串类型
19 0
|
16天前
|
存储 消息中间件 NoSQL
Redis数据类型详解:选择合适的数据结构优化你的应用
Redis数据类型详解:选择合适的数据结构优化你的应用
|
21天前
|
存储 NoSQL 算法
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)(二)
【Redis技术进阶之路】「底层源码解析」揭秘高效存储模型与数据结构底层实现(字典)
34 0
|
21天前
|
存储 NoSQL Redis
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)(三)
作者推荐 |【Redis技术进阶之路】「原理系列开篇」揭秘高效存储模型与数据结构底层实现(SDS)
19 0
|
23天前
|
存储 NoSQL Java
Redis 数据结构操作入门
Redis 数据结构操作入门
15 0
|
11天前
|
消息中间件 存储 搜索推荐
深入理解栈和队列(二):队列
深入理解栈和队列(二):队列
29 0
|
1月前
【栈】数据结构栈的实现
【栈】数据结构栈的实现
|
1月前
|
存储
数据结构--栈和队列
数据结构--栈和队列
|
1月前
|
存储 算法 数据处理
数据结构从入门到精通——栈
栈,作为一种后进先出(LIFO)的数据结构,在计算机科学中扮演着重要的角色。它的特性使得它在处理函数调用、括号匹配、表达式求值等问题时具有得天独厚的优势。然而,如果我们跳出传统思维的束缚,会发现栈的用途远不止于此。
49 0
|
1月前
|
C语言
数据结构之栈详解(C语言手撕)
数据结构之栈详解(C语言手撕)
35 1

热门文章

最新文章