台州网站建设方案服务代理ip 海外

bicheng/2026/1/22 14:52:11/文章来源:
台州网站建设方案服务,代理ip 海外,软件系统商城定制开发,公众号开发者密码前言 redis的核心是数据的快速存储#xff0c;下面就来分析一下godis的底层存储是如何实现#xff0c;先分析单机服务。 此文采用抓大放小原则#xff0c;先大的流程方向#xff0c;再抓细节。 流程图 源码分析 现在以客户端连接#xff0c;并发起set key val命令为例…前言 redis的核心是数据的快速存储下面就来分析一下godis的底层存储是如何实现先分析单机服务。 此文采用抓大放小原则先大的流程方向再抓细节。 流程图 源码分析 现在以客户端连接并发起set key val命令为例子 在单机部署的时候服务启动会创建一个处理实例并创建一个单机的db // redis/server.go // 创建一个处理实例 // MakeHandler creates a Handler instance func MakeHandler() *Handler {// redis的一个存储引擎var db database.DB// 创建是集群还是单例if config.Properties.ClusterEnable {db cluster.MakeCluster()} else {db database2.NewStandaloneServer()}return Handler{db: db,} }有客户端连接会生成一个异步方法处理每个客户端一旦有客户端的消息都会进入Handle方法。 // redis/server/server.go // 处理接收到客户端的命令 // Handle receives and executes redis commands func (h *Handler) Handle(ctx context.Context, conn net.Conn) {if h.closing.Get() {// closing handler refuse new connection_ conn.Close()return}client : connection.NewConn(conn)// 存储一个客户端h.activeConn.Store(client, struct{}{})// 获取字符串ch : parser.ParseStream(conn)// 接收客户端数据for payload : range ch {// 遍历消息体// ......... 经过各种校验// 获取到客户端信息r, ok : payload.Data.(*protocol.MultiBulkReply)if !ok {logger.Error(require multi bulk protocol)continue}// 执行结果result : h.db.Exec(client, r.Args)// 结果回复if result ! nil {_, _ client.Write(result.ToBytes())} else {_, _ client.Write(unknownErrReplyBytes)}} }客户端的各种命令进行判断set是属于正常的数据操作命令直接通过判断获取数据库并在当前数据库中执行 // database/server.go func (server *Server) Exec(c redis.Connection, cmdLine [][]byte) (result redis.Reply) {defer func() {if err : recover(); err ! nil {logger.Warn(fmt.Sprintf(error occurs: %v\n%s, err, string(debug.Stack())))result protocol.UnknownErrReply{}}}()cmdName : strings.ToLower(string(cmdLine[0]))// pingif cmdName ping {return Ping(c, cmdLine[1:])}// authenticateif cmdName auth {return Auth(c, cmdLine[1:])}// ........// 各种各样的判断暂时不管// 获取当前的数据索引// normal commandsdbIndex : c.GetDBIndex()// 获取当前数据库selectedDB, errReply : server.selectDB(dbIndex)if errReply ! nil {return errReply}// 以当前数据库执行命令return selectedDB.Exec(c, cmdLine) }命令名称解析出来后从cmdTable获取对应的执行方法如prepare、executor // Exec executes command within one database func (db *DB) Exec(c redis.Connection, cmdLine [][]byte) redis.Reply {// transaction control commands and other commands which cannot execute within transactioncmdName : strings.ToLower(string(cmdLine[0]))// ...return db.execNormalCommand(cmdLine) }func (db *DB) execNormalCommand(cmdLine [][]byte) redis.Reply {// 获取到正常的执行命令cmdName : strings.ToLower(string(cmdLine[0]))// 获取到commondcmd, ok : cmdTable[cmdName]if !ok {return protocol.MakeErrReply(ERR unknown command cmdName )}if !validateArity(cmd.arity, cmdLine) {return protocol.MakeArgNumErrReply(cmdName)}prepare : cmd.preparewrite, read : prepare(cmdLine[1:])db.addVersion(write...)// 数据库上锁db.RWLocks(write, read)// 命令执行完后解锁defer db.RWUnLocks(write, read)// 执行命令方法fun : cmd.executorreturn fun(db, cmdLine[1:]) }set命令对应的方法从代码可以发现其实数据是存储在定义的map结构的集合中自此命令已经执行完毕返回执行结果。 func execSet(db *DB, args [][]byte) redis.Reply {// 提取keykey : string(args[0])// 提取valvalue : args[1]// 提取策略policy : upsertPolicy// 提取过期时间ttl : unlimitedTTL// parse options// 如何参数大于2个说明有其他参数需要做其他处理// .....entity : database.DataEntity{Data: value,}var result int// 更新策略switch policy {case upsertPolicy:// 默认策略db.PutEntity(key, entity)result 1case insertPolicy:result db.PutIfAbsent(key, entity)case updatePolicy:result db.PutIfExists(key, entity)}if result 0 {if ttl ! unlimitedTTL {expireTime : time.Now().Add(time.Duration(ttl) * time.Millisecond)// 设置过期时间db.Expire(key, expireTime)db.addAof(CmdLine{[]byte(SET),args[0],args[1],})db.addAof(aof.MakeExpireCmd(key, expireTime).Args)} else {db.Persist(key) // override ttldb.addAof(utils.ToCmdLine3(set, args...))}}if result 0 {return protocol.OkReply{}}return protocol.NullBulkReply{} }// database.go // 将数据放入DB // PutEntity a DataEntity into DB func (db *DB) PutEntity(key string, entity *database.DataEntity) int {// 当前数据库的数据字段ret : db.data.PutWithLock(key, entity)// db.insertCallback may be set as nil, during if and actually callback// so introduce a local variable cbif cb : db.insertCallback; ret 0 cb ! nil {cb(db.index, key, entity)}return ret }// datastruct/dict/concurrent.go // ConcurrentDict is thread safe map using sharding lock // 这里可以看出数据其实就是存在map集合里面 type ConcurrentDict struct {table []*shardcount int32shardCount int }type shard struct {m map[string]interface{}mutex sync.RWMutex }// datastruct/dict/concurrent.go func (dict *ConcurrentDict) PutWithLock(key string, val interface{}) (result int) {if dict nil {panic(dict is nil)}hashCode : fnv32(key)index : dict.spread(hashCode)s : dict.getShard(index)// 将数据放入map中if _, ok : s.m[key]; ok {s.m[key] valreturn 0}dict.addCount()// 存储kv结构数据完成s.m[key] valreturn 1 } 其实还有一个问题就是cmdTable怎么来的为什么fun(db, cmdLine[1:])就完成了 在router.go这个代码中是生成一个新的cmdTable的map集合registerCommand这个函数是将各种命令塞入cmdTable里面。每个数据结构如string等都有定义的方法。 main启动前都会调用init()这个是golang特殊的函数顺序按照文件的顺序执行。 这里就是在服务启动前将所有命令注册到cmdTable集合。 // database/router.go // 命令集 var cmdTable make(map[string]*command) // .... // 注册命令将命令存放在cmdTable集合里面 // registerCommand registers a normal command, which only read or modify a limited number of keys func registerCommand(name string, executor ExecFunc, prepare PreFunc, rollback UndoFunc, arity int, flags int) *command {name strings.ToLower(name)cmd : command{name: name,executor: executor,prepare: prepare,undo: rollback,arity: arity,flags: flags,}cmdTable[name] cmdreturn cmd }//// database/string.gofunc execSet(db *DB, args [][]byte) redis.Reply { //.... }// execSetNX sets string if not exists func execSetNX(db *DB, args [][]byte) redis.Reply {// ..... }// execSetEX sets string and its ttl func execSetEX(db *DB, args [][]byte) redis.Reply {// ... }func init() {// 调用注册命令函数注册方法如Set则是执行execSet方法registerCommand(Set, execSet, writeFirstKey, rollbackFirstKey, -3, flagWrite).attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)registerCommand(SetNx, execSetNX, writeFirstKey, rollbackFirstKey, 3, flagWrite).attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)registerCommand(SetEX, execSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite).attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)// ..... } ExecFunc是规范方法每个命令对应的执行都按照规范定义。 // database/router.gotype command struct {// 命令名称name string// 执行方法executor ExecFunc// prepare returns related keys commandprepare PreFunc// undo generates undo-log before command actually executed, in case the command needs to be rolled backundo UndoFunc// arity means allowed number of cmdArgs, arity 0 means len(args) -arity.// for example: the arity of get is 2, mget is -2arity intflags intextra *commandExtra }// // database/database.go // 执行方法接口 // ExecFunc is interface for command executor // args dont include cmd line type ExecFunc func(db *DB, args [][]byte) redis.Reply

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/87820.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

营口网站建设价格宁夏网络推广公司

MySQL作为一款常用的关系型数据库管理系统,也在逐渐向云原生架构演进。本文将介绍MySQL云原生应用实践方法,并提供示例进行说明。 一、MySQL云原生架构概述 MySQL云原生架构是指将MySQL部署在云环境中,利用容器化技术实现高可用、可扩展和弹…

嘉禾专业网站建设开发网站中心

一、伯努利随机过程 1. n次伯努利实验中(x1)发生的总次数Yn: (二项分布) 2. 伯努利实验中事件第一次发生的时间L1: (几何分布) 3. n次伯努利实验中事件第k次发生的时间Lk: (帕斯卡分…

网站建设规划书网页视频下载器破解版

Mybatis中的设计模式 Mybatis中使用了大量的设计模式。 以下列举一些看源码时,觉得还不错的用法: 创建型模式 工厂方法模式 DataSourceFactory 通过不同的子类工厂,实例化不同的DataSource TransactionFactory 通过不同的工厂&#xff…

室内设计网站哪些号网站开发业务需求分析

目录 《Python数据分析初探》项目报告 基于Python数据可视化的网易云音乐歌单分析系统一、项目简介(一)项目背景(二)项目过程 二、项目设计流程图(一)基于Python数据可视化的网易云音乐歌单分析系统的整体…

济南建设高端网站郑州网站建设老牌公司

Flink 运行架构和核心概念 几个角色的作用: 客户端:提交作业JobManager进程 任务管理调度 JobMaster线程 一个job对应一个JobMaster 负责处理单个作业ResourceManager 资源的分配和管理,资源就是任务槽分发器 提交应用,为每一个…

太原网站建设方案策划win2012 网站建设

面试题1:变量的声明和定义有什么区别 为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但只能在一个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义…

沈阳模板建站哪家好wordpress simplicity

“Ah ha,发现你了!”你的经理突然从桌子后面的假花旁冒出来,发出胜利的叫声。你沮丧地转过头看着经理。 “我已经创建了一个基本报表,并抓取了一些数据,我正打算-”你在他打断你之前快速的解释着。 “赶紧做完就好,大B…

织梦多语言网站网站架构教程

正题 题目链接:https://www.luogu.com.cn/problem/P3327 题目大意 TTT组询问给出n,mn,mn,m,d(x)d(x)d(x)表示xxx的约数个数,求∑i1n∑j1md(i∗j)\sum_{i1}^n\sum_{j1}^md(i*j)i1∑n​j1∑m​d(i∗j) 解题思路 对于iii和jjj的两个约数a,ba,ba,b如果他们…

成品网站 售卖建筑设计师要学什么专业

软件实例,物流货运配货单打印模板软件单据打印查询管理系统软件教程,可以同时打印标签或补打 一、前言 以下软件教程以 佳易王物流单打印查询系统V17.1为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 这个版本在原来基…

摄影网站app怎么做网络运营

国际荐酒师(香港)协会亮相第六届知交会暨地博会,助力中欧地理标志产品交流合作 12月9日,第六届粤港澳大湾区知识产权交易博览会暨国际地理标志产品交易博览会(以下简称“第六届知交会暨地博会”)在中新广州…

购物网站seo相亲网站用什么做的

患者在就诊之前一直使用的二甲双胍和达格列净这两种降糖药物,这两种药对于控制血糖是有一定效果的。北京崇文门医院朱学敏主任的建议是继续服用,然后患者空腹血糖在7-8mmol/L左右,餐后血糖稍高,达到9-10mmol/L,但总体上…

获取网站访客qq代码亿网

C后端开发之Sylar学习三:VSCode连接Ubuntu配置Gitee 为了记录学习的过程,学习Sylar时写的代码统一提交到Gitee仓库中。 Ubuntu配置Gitee 安装git sudo apt-get install -y git配置用户名和邮箱 git config --global user.name 用户名 …

js网站繁体如何自己设计装修效果图

文章目录 什么是 NVMe?什么是固态硬盘?为什么 NVMe 很重要?NVMe、SAS 和 SATA 之间的区别只有SSD运行在NVMe上PCIe和NVMe有关系,但它们不是同一个东西NVMe-oF连接SSD到网络NVMe 的工作原理是什么?NVMe SSD 外形尺寸M.2…

资质做网站需要用到什么郑州企业网站建设团队

😁 作者简介:一名大四的学生,致力学习前端开发技术 ⭐️个人主页:夜宵饽饽的主页 ❔ 系列专栏:JavaScript进阶指南 👐学习格言:成功不是终点,失败也并非末日,最重要的是继…

php做的购物网站代码专门做网站制作的公司

动态规划:有很多重叠子问题,每一个状态一定是由上一个状态推导出来的 贪心:没有状态推导,而是从局部直接选最优的 动规五步曲: 确定dp数组(dp table)以及下标的含义 确定递推公式(容…

做平台网站一般有php还是js南阳市网站建设

🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java项目分享》 《RabbitMQ》《Spring》《SpringMVC》 🛸学无止境,不骄不躁,知行合一 文章目录 前言一、SpringBoot…

无锡高端网站设计公司网站进入沙盒后

上次小伍带大家看了部分机房的照片,并且简单介绍了一下电梯能量回馈装置,小伙伴们表示很新奇,没看够,今天小伍又来了,带大家看一下电梯能量回馈装置到底安装在电梯什么位置。跟着小伍去看看吧。Lets go! 电…

夫妻找做伙食饭工作哪个网站好四川网站建设费用

5G智能制造纺织工厂数字孪生可视化平台,推进纺织行业数字化转型。纺织工业作为传统制造业的重要组成部分,面临着转型升级的紧迫需求。随着5G技术的快速发展,智能制造成为纺织工业转型升级的重要方向。数字孪生可视化平台作为智能制造的核心技…

宝安网站建设方案外包制作相册app

基础数据结构 ngx_int_t 32位操作系统4字节,64位操作系统8字节 解决跨平台以及,普通int类型在x86和x64操作系统上面是4字节,在类型转换时造成内存浪费(如在x64下面转换long类型) typedef intptr_t ngx_int_t;#ifdef _WIN64 typedef __int64 intptr_t; #else typedef _…

国际外贸网站推广二维码制作生成器

MyBatis 支持一对一,一对多,多对多查询。XML 文件和注解都能实现关系的操作。多对多实质就是一对多 1. 表关系的维护 1.1 One一对一 一对一查询和多表(两表)查询很相似, 都能查询两表的全部属性 区别是一对一可以在对象中嵌套对象, 呈现包含关系; 多表…