当前位置: 首页 > news >正文

redis的一些重要的基础知识

文章目录

    • 1. rehash
      • 1.1 redis的hash表的数据结构
    • 2. AOF日志
      • 2.1 简要介绍
      • 2.2 AOF重写
    • 3. RDB快照
      • 3.1 执行过程
      • 3.2 存在问题
      • 解决方式

1. rehash

本文只介绍数据结构和结果图,如果要看文字描述过程,可以参考链接:rehash的详细过程

1.1 redis的hash表的数据结构

在这里插入图片描述
dictType类型:

type dictType struct {hashFunction   func(key interface{}) uint32keyDup         func(privdata interface{}, key interface{}) interface{}valDup         func(privdata interface{}, obj interface{}) interface{}keyCompare     func(privdata interface{}, key1 interface{}, key2 interface{}) intkeyDestructor  func(privdata interface{}, key interface{})valDestructor  func(privdata interface{}, obj interface{})
}
//hashFunction:哈希函数,用于计算键的哈希值; MurmurHash方法
//keyDup:键复制函数,用于插入插入键值对
//valDup:值复制函数, 用于插入键值对
//keyCompare:键比较函数,用于比较两个键是否相等,用于查找键值对;
//keyDestructor:键销毁函数,用于释放键占用的内存;
//valDestructor: 值销毁函数,用于释放值占用的内存;

dict类型:

type dict struct {ht [2]*dictht //两个hash表rehashIndex int // 表示重新哈希的索引位置(如果等于 -1,则表示没有进行重新哈希)iterators uint32 //当前正在迭代的迭代器数randomSeed uint64 //是一个随机种子,用于在哈希函数中生成随机值privdata interface{} //私有数据,保存着dictType结构中函数的 参数,保存哈希表的一些额外信息type_ *dictType //指向了一个 dictType 结构体,用于实现哈希表的各项功能。
}

dictht类型:

//dict结构中ht[0]、ht[1]哈希表的数据结构
type dictht struct {table []dictEntry 存放一个数组的地址,数组中存放哈希节点dictEntry的地址size int 哈希表table的大小,初始大小为4sizemask int 用于将hash值映射到table位置的索引,大小为(size-1)used int  //记录哈希表已有节点(键值对)的数量
}

dictEntry类型

type dictEntry struct {key interface{}v   dictEntryValuenext *dictEntry
}
type dictEntryValue struct {ptr interface{}integer int64uinteger uint64_float float64
}

2. AOF日志

2.1 简要介绍

  • 主要作用:redis是内存存储,如果系统崩溃可能会导致数据丢失,而AOF的作用就是用来redis崩溃后数据恢复的;
  • 格式实例:AOF是直接将redis命令进行记录的,set testKey testValue这个命令:
    在这里插入图片描述
  • 该日志属于写后日志:在redis执行命令后在插入日志
    • 优点:不会阻塞当前写操作;确保写入的命令是正确执行的;
    • 缺点:redis执行成功后,数据写入AOF日志缓冲区没能及时同步,导致数据丢失,从而数据不一致;这个时候就需要选择合理的同步策略:
      在这里插入图片描述

2.2 AOF重写

  • 重写原因:作为文本记录的AOF日志,随着命令的增加,记录越来越多,从而导致了文件也越来越大,在数据恢复的时候会对系统产生较大的负担;
  • 重写步骤:
    • 主线程fork一个子线程来进行重写,用主线程如果文件过大,会阻塞主流程;
    • 子线程对AOF日志进行重写,重写过程中新来的命令记录在AOF日志和重写AOF日志缓冲区中,避免数据不一致。重写完成后,将缓冲区中的数据加入到日志中,从而完成重写。
    • 重写逻辑:即将多个命令合并成一个命令。通过这种方式,可以有效地减少AOF文件的大小,提高数据恢复的速度,并解决上述问题。因此,AOF重写确实是因为AOF日志中重复key的操作合并,以提高数据持久化的效率和效果‌。
      在这里插入图片描述
//代码浅浅编写:
func aofRewrite(newAofFileName string) {// 创建新的 AOF 文件f := createFile(newAofFileName)// 遍历数据库for _, db := range redisServer.db {// 忽略空数据库if db.isEmpty() {continue}// 写入 SELECT 命令,指定数据库号码f.writeCommand("SELECT", db.id)// 遍历数据库中的所有键for _, key := range db {// 忽略已过期的键if key.isExpired() {continue}// 根据键的类型对键进行重写switch key.type {case String:rewriteString(key, f)case List:rewriteList(key, f)case Hash:rewriteHash(key, f)case Set:rewriteSet(key, f)case SortedSet:rewriteSortedSet(key, f)}// 如果键带有过期时间,那么过期时间也要被重写if key.haveExpireTime() {rewriteExpireTime(key, f)}}}// 写入完毕,关闭文件f.close()
}func rewriteString(key *Key, f *File) {// 使用 GET 命令获取字符串的值value := redis.Get(key).Val()// 使用 SET 命令重写字符串键f.writeCommand("SET", key, value)
}func rewriteList(key *Key, f *File) {// 使用 LRANG 命令获取列表键包含的所有元素items := redis.LRange(key, 0, -1).Val()// 使用 RPUSH 命令重写列表键args := []interface{}{key}for _, item := range items {args = append(args, item)}f.writeCommand("RPUSH", args...)
}func rewriteHash(key *Key, f *File) {// 使用 HGETALL 命令获取哈希键包含的所有键值对fieldVals := redis.HGetAll(key).Val()// 使用 HMSET 命令重写哈希键args := []interface{}{key}for field, value := range fieldVals {args = append(args, field, value)}f.writeCommand("HMSET", args...)
}func rewriteSet(key *Key, f *File) {// 使用 SMEMBERS 命令获取集合包含的所有元素elems := redis.SMembers(key).Val()// 使用 SADD 命令重写集合键args := []interface{}{key}for _, elem := range elems {args = append(args, elem)}f.writeCommand("SADD", args...)
}func rewriteSortedSet(key *Key, f *File) {// 使用 ZRANG 命令获取有序集合包含的所有元素memberScores := redis.ZRangeWithScores(key, 0, -1).Val()// 使用 ZADD 命令重写有序集合键args := []interface{}{key}for _, memberScore := range memberScores {args = append(args, memberScore.Score, memberScore.Member)}f.writeCommand("ZADD", args...)
}func rewriteExpireTime(key *Key, f *File) {// 获取毫秒精度的键过期时间戳timestamp := getExpireTimeInUnixStamp(key)// 使用 PEXPIREAT 命令重写键的过期时间f.writeCommand("PEXPIREAT", key, timestamp)
}

3. RDB快照

3.1 执行过程

在这里插入图片描述

3.2 存在问题

如果快照间隔时间太短:
在这里插入图片描述
如果间隔时间过长,可能会导致数据大量丢失

解决方式

在这里插入图片描述
本文的目的只是做一个简单的记录,详细的可以参考链接:https://blog.csdn.net/m0_70325779/article/details/132409948

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • onvif应用--IPC鉴权(认证)
  • Linux起源
  • matlab基本语法
  • windows安装composer
  • 网恋照妖镜源码搭建教程
  • LINUX常用命令-docker-Kubernetes
  • 【机器人工具箱Robotics Toolbox开发笔记(二)】Matlab中机器人工具箱的下载与安装
  • k8s-pod 实战一 (创建pod,启动命令,参数,pod故障排除,拉取命令)
  • Fileupload - Endpoint and OpenAI Generation for the Service
  • 快速幂算法——求解大指数幂
  • 强化学习实操入门随笔
  • 【云原生之kubernetes实战】k8s环境中部署Nginx服务
  • 学习记录——day42 模板
  • 数字货币是怎么回事什么是数字货币
  • 由浅入深学习 C 语言:Hello World【提高篇】
  • 【css3】浏览器内核及其兼容性
  • HomeBrew常规使用教程
  • input的行数自动增减
  • java B2B2C 源码多租户电子商城系统-Kafka基本使用介绍
  • Java编程基础24——递归练习
  • js面向对象
  • js写一个简单的选项卡
  • js作用域和this的理解
  • linux安装openssl、swoole等扩展的具体步骤
  • react-native 安卓真机环境搭建
  • Terraform入门 - 3. 变更基础设施
  • Twitter赢在开放,三年创造奇迹
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 分享一份非常强势的Android面试题
  • 复杂数据处理
  • 前端工程化(Gulp、Webpack)-webpack
  • 前端路由实现-history
  • 让你成为前端,后端或全栈开发程序员的进阶指南,一门学到老的技术
  • 正则表达式小结
  • 7行Python代码的人脸识别
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​虚拟化系列介绍(十)
  • (06)Hive——正则表达式
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (附源码)流浪动物保护平台的设计与实现 毕业设计 161154
  • (接口自动化)Python3操作MySQL数据库
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (贪心 + 双指针) LeetCode 455. 分发饼干
  • (一)UDP基本编程步骤
  • (转)德国人的记事本
  • ***原理与防范
  • .Net Attribute详解(上)-Attribute本质以及一个简单示例
  • .NET 回调、接口回调、 委托
  • .NET4.0并行计算技术基础(1)
  • .NET6 命令行启动及发布单个Exe文件
  • [000-01-022].第03节:RabbitMQ环境搭建
  • [20150629]简单的加密连接.txt
  • [C/C++] -- 二叉树
  • [C++]:for循环for(int num : nums)
  • [LeetCode] Contains Duplicate