【3y】从零单排学Redis【青铜】(一)

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 笔记

前言


1.jpg                                                             redis

最近在学Redis,我相信只要是接触过Java开发的都会听过Redis这么一个技术。面试也是非常高频的一个知识点,之前一直都是处于了解阶段。秋招过后这段时间是没有什么压力的,所以打算系统学学Redis,这也算是我从零学习Redis的笔记吧。

本文力求讲清每个知识点,希望大家看完能有所收获。


一、介绍一下Redis


首先,肯定是去官网看看官方是怎么介绍Redis的啦。https://redis.io/topics/introduction

如果像我一样,英语可能不太好的,可能看不太懂。没事,咱们Chrome浏览器可以切换成中文的,中文是我们的母语,肯定没啥压力了。Eumm…

读完之后,发现中文也就那样了。

一大堆没见过的技术:lua(Lua脚本)、replication(复制)、Redis Sentinel(哨兵)、Redis Cluster(Redis 集群),当然我们也会有看得懂的技术:transactions(事务)、different levels of on-disk persistence(数据持久化)、LRU eviction(LRU淘汰机制)..

至少官方介绍Redis的第一句应该是可以很容易看懂:"Redis is an open source (BSD licensed),in-memory data structure store, used as a database,cache and message broker."

Redis是一个开源的,基于内存的数据结构存储,可用作于数据库、缓存、消息中间件。

  • 从官方的解释上,我们可以知道:Redis是基于内存,支持多种数据结构。
  • 从经验的角度上,我们可以知道:Redis常用作于缓存。

就我个人认为:学习一种新技术,先把握该技术整体的知识(思想),再扣细节,这样学习起来会比较轻松一些。所以我们先以“内存”、“数据结构”、“缓存”来对Redis入门。


1.1为什么要用Redis?


从上面可知:Redis是基于内存,常用作于缓存的一种技术,并且Redis存储的方式是以key-value的形式。

我们可以发现这不就是Java的Map容器所拥有的特性吗,那为什么还需要Redis呢?

  • Java实现的Map是本地缓存,如果有多台实例(机器)的话,每个实例都需要各自保存一份缓存,缓存不具有一致性
  • Redis实现的是分布式缓存,如果有多台实例(机器)的话,每个实例都共享一份缓存,缓存具有一致性
  • Java实现的Map不是专业做缓存的,JVM内存太大容易挂掉的。一般用做于容器来存储临时数据,缓存的数据随着JVM销毁而结束。Map所存储的数据结构,缓存过期机制等等是需要程序员自己手写的。
  • Redis是专业做缓存的,可以用几十个G内存来做缓存。Redis一般用作于缓存,可以将缓存数据保存在硬盘中,Redis重启了后可以将其恢复。原生提供丰富的数据结构、缓存过期机制等等简单好用的功能。

参考资料:

  • 为什么要用redis而不用map做缓存?
  • https://segmentfault.com/q/1010000009106416


1.2为什么要用缓存?


如果我们的网站出现了性能问题(访问时间慢),按经验来说,一般是由于数据库撑不住了。因为一般数据库的读写都是要经过磁盘的,而磁盘的速度可以说是相当慢的(相对内存来说)

2.jpg                                                         数据库撑不住了

如果学过Mybaits、Hibernate的同学就可以知道,它们有一级缓存、二级缓存这样的功能(终究来说还是本地缓存)。目的就是为了:不用每次读取的时候,都要查一次数据库

有了缓存之后,我们的访问就变成这样了:

3.jpg                                                  有了缓存提高了并发和性能


二、Redis的数据结构


本文不会讲述命令的使用方式,具体的如何使用可查询API。

Redis支持丰富的数据结构,常用的有string、list、hash、set、sortset这几种。学习这些数据结构是使用Redis的基础!

"Redis is written in ANSI C"-->Redis由C语言编写

首先还是得声明一下,Redis的存储是以key-value的形式的。Redis中的key一定是字符串,value可以是string、list、hash、set、sortset这几种常用的。

4.jpg                                                  redis数据结构

但要值得注意的是:Redis并没有直接使用这些数据结构来实现key-value数据库,而是基于这些数据结构创建了一个对象系统

  • 简单来说:Redis使用对象来表示数据库中的键和值。每次我们在Redis数据库中新创建一个键值对时,至少会创建出两个对象。一个是键对象,一个是值对象。

Redis中的每个对象都由一个redisObject结构来表示:

typedef struct redisObject{
    // 对象的类型
    unsigned type 4:;
    // 对象的编码格式
    unsigned encoding:4;
    // 指向底层实现数据结构的指针
    void * ptr;
    //.....
}robj;

5.jpg                                        数据结构对应的类型与编码

简单来说就是Redis对key-value封装成对象,key是一个对象,value也是一个对象。每个对象都有type(类型)、encoding(编码)、ptr(指向底层数据结构的指针)来表示。

6.jpg                                    以值为1006的字符串对象为例

下面我就来说一下我们Redis常见的数据类型:string、list、hash、set、sortset。它们的底层数据结构究竟是怎么样的!


2.1SDS简单动态字符串


简单动态字符串(Simple dynamic string,SDS)

Redis中的字符串跟C语言中的字符串,是有点差距的

Redis使用sdshdr结构来表示一个SDS值:

struct sdshdr{
    // 字节数组,用于保存字符串
    char buf[];
    // 记录buf数组中已使用的字节数量,也是字符串的长度
    int len;
    // 记录buf数组未使用的字节数量
    int free;
}

例子:

7.png                                            SDS例子


2.1.1使用SDS的好处


SDS与C的字符串表示比较

  1. sdshdr数据结构中用len属性记录了字符串的长度。那么获取字符串的长度时,时间复杂度只需要O(1)
  2. SDS不会发生溢出的问题,如果修改SDS时,空间不足。先会扩展空间,再进行修改!(内部实现了动态扩展机制)。
  3. SDS可以减少内存分配的次数(空间预分配机制)。在扩展空间时,除了分配修改时所必要的空间,还会分配额外的空闲空间(free 属性)。
  4. SDS是二进制安全的,所有SDS API都会以处理二进制的方式来处理SDS存放在buf数组里的数据。


2.2链表


对于链表而言,我们不会陌生的了。在大学期间肯定开过数据结构与算法课程,链表肯定是讲过的了。在Java中Linkedxxx容器底层数据结构也是链表+[xxx]的。我们来看看Redis中的链表是怎么实现的:

使用listNode结构来表示每个节点:

typedef strcut listNode{
    //前置节点
    strcut listNode  *pre;
    //后置节点
    strcut listNode  *pre;
    //节点的值
    void  *value;
}listNode

使用listNode是可以组成链表了,Redis中使用list结构来持有链表

typedef struct list{
    //表头结点
    listNode  *head;
    //表尾节点
    listNode  *tail;
    //链表长度
    unsigned long len;
    //节点值复制函数
    void *(*dup) (viod *ptr);
    //节点值释放函数
    void  (*free) (viod *ptr);
    //节点值对比函数
    int (*match) (void *ptr,void *key);
}list

具体的结构如图:

8.jpg

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3月前
|
存储 NoSQL 算法
Redis HyperLogLog 是什么?这些场景使用它,让我枪出如龙,一笑破苍穹
Redis HyperLogLog 是什么?这些场景使用它,让我枪出如龙,一笑破苍穹
54 0
|
1月前
|
NoSQL Redis
【怒怼大厂面试官】听说你精通Redis?Redis数据同步懂吗
面试官:不用慌尽管说,错了也没关系。。。来说说Redis数据同步。是这样的,Redis有一个叫命令传播的概念,如果像面试官说的这种场景,再使用上面我提到的AOF缓冲区就有点浪费内存空间了。所以Redis会将主服务器的这条Del删除命令
62 2
【怒怼大厂面试官】听说你精通Redis?Redis数据同步懂吗
|
5月前
|
NoSQL 算法 Java
Redis魔法:点燃分布式锁的奇妙实现
Redis魔法:点燃分布式锁的奇妙实现
299 0
|
存储 缓存 NoSQL
走进 Redis,让你重新认识 redis。绝不是表面
说到Redis我们不禁的会联想到:缓存。提到缓存我们要聊的就有很多了。
|
存储 消息中间件 缓存
从零开始学Redis之金刚凡境
前言 文本已收录至我的GitHub仓库,欢迎Star:github.com/bin39232820… 种一棵树最好的时间是十年前,其次是现在
110 0
|
NoSQL 网络协议 Java
|
缓存 NoSQL Redis