MIT6.5840-2023-Lab4B: Sharded K/V Service-Sharded K/V Server

实验内容

实现一个分片 k/v 存储系统,分片指如所有以“a”开头的键可能是一个分片,所有以 “b”开头的键可能是另一个分片。每个副本组仅处理几个分片的 Put、Append 操作,实现并行操作,系统总吞吐量(单位时间的放入和获取)与组的数量成正比。

分片 k/v 存储系统由多个副本组和一个分片控制器组成,分片控制器管理配置信息,决定哪个副本组为哪个分片服务。
某些组的负载可能远高于其他组,实现在多个副本组之间转移分片,以达到负载均衡。同时可能会添加新的副本组以增加容量,或者现有的副本组可能会脱机以进行修复,因此必须移动分片以继续满足要求。

主要挑战是处理重新配置,即将分片重新分配给副本组。在单个副本组中, 所有组成员必须就客户端的 Put/Append/Get 请求在进行重新配置时达成一致。如 Put 可能与重新配置同时到达,重新配置导致副本组不再对 Put 的 key 对应的分片负责。所以组中的所有副本必须就 Put 发生在重新配置之前还是之后达成一致。若在重新配置之前,则 Put 应生效,并且该分片的新所有者需要看到生效效果;若在重新配置之后,Put 将不会生效,客户必须重新请求该 key 的新所有者。

推荐的方法是让每个副本组使用 Raft 不仅记录请求的ID,还记录重新配置的ID。需要确保任何时间最多只有一个副本组为一个分片提供服务。

重新配置还涉及到副本组之间的交互,如在配置 10 中,组 G1 负责分片 S1,在配置 11 中,组 G2 负责分片 S1;在 10 到 11 的重新配置期间,G1 和 G2 必须使用 RPC 将分片 S1 的内容(键/值对)从 G1 移动到 G2。

实验环境

OS:WSL-Ubuntu-18.04
golang:go1.17.6 linux/amd64

Part B: Sharded Key/Value Server

Impl:shardkv/client.go, shardkv/common.go, and shardkv/server.go

实现一个分片 k/v 存储系统,每个副本组仅处理其所负责的分片中的键,并支持 Get、Put、Append 操作。利用 PartA 中实现的 ShardCtrler 维护配置信息。

No-credit challenge exercises

Garbage collection of state
当副本组失去对分片的所有权时,该副本组应消除其数据库中对应的key,从而避免浪费。但是,这在分片迁移上会有一些问题。假设我们有两个组G1和G2,并且有一个新的配置C——将Shard S从G1移至G2。如果G1转换为配置C时从其数据库中删除了S中的所有key,则G2在尝试移动到C时如何获取S的数据?

Client requests during configuration changes
处理配置更改的最简单方法是禁止所有客户端操作,直到过渡完成。虽然从概念上讲简单,但这种方法在生产级系统中是不可行的。每当将机器带入或取出时,它会导致所有客户暂停。
即使配置转换仍在进行中,副本组仍然能够使用新配置已经join的分片。

addConfig()

定时检测是否有更新的配置,若当前正在更新配置,则等待更新完成再继续检测;否则向raft提交命令,等待达成共识然后执行。

func (kv *ShardKV) addConfig() {for kv.killed() == false {if _, isLeader := kv.rf.GetState(); !isLeader {time.Sleep(100 * time.Millisecond)continue}kv.mu.Lock()isAllServing := truefor _, shard := range kv.shards {if shard.State != Serving {isAllServing = falsebreak}}kv.mu.Unlock()if isAllServing {config := kv.manager.Query(kv.config.Num + 1) // next configif config.Num == kv.config.Num+1 {command := Command{CommandType: AddConfig,Data:        config,}reply := CommonReply{}kv.startCommand(command, &reply)}}time.Sleep(100 * time.Millisecond)}
}

insertShard()

定时检测是否需要从其他副本组pull shard,向pulling状态分片所在的副本组发送GetShards-rpc,得到分片信息后,向raft提交插入分片的命令,达成共识后执行。

func (kv *ShardKV) insertShard() {for kv.killed() == false {if _, isLeader := kv.rf.GetState(); !isLeader {time.Sleep(100 * time.Millisecond)continue}kv.mu.Lock()GID2ShardIds := kv.getLastGID2ShardIds(Pulling) // gid in last configwg := &sync.WaitGroup{}wg.Add(len(GID2ShardIds))for gid, shardIds := range GID2ShardIds {configNum, servers := kv.config.Num, kv.lastConfig.Groups[gid]go func(gid int, shardIds []int, configNum int, servers []string) {defer wg.Done()// get pulling shards in other groupfor _, server := range servers {args := PullShardArgs{GID:       gid,ShardIds:  shardIds,ConfigNum: configNum,}reply := PullShardReply{}srv := kv.make_end(server)ok := srv.Call("ShardKV.GetShards", &args, &reply)if ok && reply.Err == OK {reply.ConfigNum = configNumcommand := Command{CommandType: InsertShard,Data:        reply,}kv.startCommand(command, &CommonReply{})}}}(gid, shardIds, configNum, servers)}kv.mu.Unlock()wg.Wait()time.Sleep(100 * time.Millisecond)}
}

adjustGCing()——Garbage collection of state

定时检测是否有GCing状态分片,这种状态表示分片已经复制到副本组中。若有,则向这些分片之前所在的副本组发送DeleteShards-rpc,删除其中BePulling状态分片;然后向raft提交将GCing状态修改为Serving状态的命令。

func (kv *ShardKV) adjustGCing() {for kv.killed() == false {if _, isLeader := kv.rf.GetState(); !isLeader {time.Sleep(100 * time.Millisecond)continue}kv.mu.Lock()GID2ShardIds := kv.getLastGID2ShardIds(GCing)wg := &sync.WaitGroup{}wg.Add(len(GID2ShardIds))for gid, shardIds := range GID2ShardIds {configNum, servers := kv.config.Num, kv.lastConfig.Groups[gid]go func(gid int, shardIds []int, configNum int, servers []string) {defer wg.Done()// remove gcing shards in other groupfor _, server := range servers {args := RemoveShardArgs{ShardIds:  shardIds,ConfigNum: configNum,}reply := RemoveShardReply{}srv := kv.make_end(server)ok := srv.Call("ShardKV.DeleteShards", &args, &reply)if ok && reply.Err == OK {args := AdjustShardArgs{ShardIds:  shardIds,ConfigNum: configNum,}command := Command{CommandType: AdjustState,Data:        args,}kv.startCommand(command, &CommonReply{})}}}(gid, shardIds, configNum, servers)}kv.mu.Unlock()wg.Wait()time.Sleep(100 * time.Millisecond)}
}

adjustBePulling()

主要解决快照记录的时间点不同,不同服务器回退到了不同的状态。定时检测状态为BePulling的分片,若配置落后于被插入分片的副本组(即原先分片状态为Pulling的副本组,而快照回退正常,所有分片正常迁移,状态均为Serving,而不是GCing)的配置,则可以判断持久化状态回退失误,将BePulling状态转为Serving。

func (kv *ShardKV) adjustBePulling() {for kv.killed() == false {if _, isLeader := kv.rf.GetState(); !isLeader {time.Sleep(100 * time.Millisecond)continue}kv.mu.Lock()GID2ShardIds := kv.getNowGID2ShardIds(BePulling)wg := &sync.WaitGroup{}wg.Add(len(GID2ShardIds))for gid, shardIds := range GID2ShardIds {configNum, servers := kv.config.Num, kv.lastConfig.Groups[gid]go func(gid int, shardIds []int, configNum int, servers []string) {defer wg.Done()// get bepulling shards in now groupfor _, server := range servers {args := CheckArgs{ShardIds:  shardIds,ConfigNum: configNum,}reply := CheckReply{}srv := kv.make_end(server)ok := srv.Call("ShardKV.CheckShards", &args, &reply)if ok && reply.Err == OK {args := AdjustShardArgs{ShardIds:  shardIds,ConfigNum: configNum,}command := Command{CommandType: AdjustState,Data:        args,}kv.startCommand(command, &CommonReply{})}}}(gid, shardIds, configNum, servers)}kv.mu.Unlock()wg.Wait()time.Sleep(100 * time.Millisecond)}
}

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

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

相关文章

恶意软件样本行为分析——Process Monitor和Wireshark

1.1 实验名称 恶意软件样本行为分析 1.2 实验目的 1) 熟悉 Process Monitor 的使用 2) 熟悉抓包工具 Wireshark 的使用 3) VMware 的熟悉和使用 4) 灰鸽子木马的行为分析 1.3 实验步骤及内容 第一阶段:熟悉 Process Monitor 的使用 利用 Process …

在Linux上安装CLion

本教程将指导你如何在Linux系统上安装CLion,下载地址为:https://download.jetbrains.com.cn/cpp/CLion-2022.3.3.tar.gz。以下是详细的安装步骤: 步骤1:下载CLion 首先,你需要使用wget命令从提供的URL下载CLion的tar…

Redis安全性加强:认证与加密实践

大家好,我是升仔 引言 Redis作为一个广泛使用的高性能键值存储系统,在众多应用场景中扮演着重要角色。然而,由于其默认配置不强调安全性,因此在生产环境中部署Redis时,加强其安全性是非常重要的。 1、实际使用场景&…

前端学习——关于前端框架的思考

前端框架 我们知道在AngularJS,react,vue等前端框架出现之前,前端开发都是通过js直接操作dom树来实现的,而有了前端框架之后,前端开发基本上不需要在直接操作dom树,相当于在原生html的dom树之间和前端程序…

springboot(ssm小学生身体素质测评管理系统 学生体测平台Java系统

springboot(ssm小学生身体素质测评管理系统 学生体测平台Java系统 开发语言:Java 框架:ssm/springboot vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库:mysql 5.7(或8.0&#…

Linux笔记---文件和目录操作

🍎个人博客:个人主页 🏆个人专栏:Linux学习 ⛳️ 功不唐捐,玉汝于成 目录 前言 命令 ls (List): pwd (Print Working Directory): cp (Copy): mv (Move): rm (Remove): 结语 我的其他博客 前言 学习Linux命令…

Centos 7.9安装Oracle19c步骤亲测可用有视频

视频介绍了在虚拟机安装centos 7.9并安装数据库软件的全过程 视频链接:https://www.zhihu.com/zvideo/1721267375351996416 下面的文字描述是安装数据库的部分介绍 一.安装环境准备 链接:https://pan.baidu.com/s/1Ogn47UZQ2w7iiHAiVdWDSQ 提取码&am…

页面级UI状态存储LocalStorage

目录 1、LocalStorageProp 2、LocalStorageLink 3、LocalStorage的使用 4、从UI内部使用LocalStorage 5、LocalStorageProp和LocalStorage单向同步的简单场景 6、LocalStorageLink和LocalStorage双向同步的简单场景 7、兄弟节点之间同步状态变量 LocalStorage是页面级的…

JMeter常见配置及常见问题修改

一、设置JMeter默认打开字体 1、进入安装目录:apache-jmeter-x.x.x\bin\ 2、找到 jmeter.properties,打开。 3、搜索“ languageen ”,前面带有“#”号.。 4、去除“#”号,并修改为:languagezh_CN 或 直接新增一行&…

《代码整洁之道:程序员的职业素养》读后感

概述 工作即将满8年,如果算上2年实习的话,满打满算我已经走过将近10年的程序员编码生涯。关于Spring Boot知识点,关于微服务理论,也已经看过好几本书籍,看过十几篇技术Blog,甚至自己也写过相关技术Blog。 …

Django5.0发布

Django 5.0 发行说明 2023 年 12 月 4 日 欢迎来到 Django 5.0! 这些发行说明涵盖了新功能,以及从 Django 4.2 或更早版本升级时需要注意的一些向后不兼容的更改。我们已经 开始对某些功能进行弃用流程。 如果您要更新现有项目,请参阅如何…

以存算一体芯片加速汽车智能化进程,后摩智能带来更优解?

汽车产业的长期价值锚点已悄然变化,催生出新的商业机遇。 过去,在燃油车市场,燃油经济性和品牌认知度等是重要的消费决策因素和资本价值衡量标准,但在新能源时代,产业价值聚焦在两方面,一是电动化&#xf…

音频筑基:基音、基频和共振峰

音频筑基:基音、基频和共振峰 是什么深入理解相关参考 音频信号分析中,经常遇到基音、周期、共振峰的概念,这里总结下自己的粗浅理解,不当之处,还望各位大佬提出指正。 是什么 基音,是复音中强度最大、频率…

【UML】第11篇 类图(6种关系)(3/3)

目录 五、类图中的6种关系 5.1 关联关系(Association) 5.2 聚合关系(Aggregation) 5.3 组合关系(Composition) 5.4 依赖关系(Dependency) 5.5 继承关系(Inheritanc…

【MIKE】MIKE河网编辑器操作说明

目录 MIKE河网编辑器说明河网定义河网编辑工具栏河网文件(.nwk11)输入步骤1. 从传统的地图引入底图1.1 底图准备1.2 引入河网底图1.3 输入各河段信息2. 从ARCView .shp文件引入底图MIKE河网编辑器说明 河网编辑器主要功能有两个: ①河网的编辑和参数输人,包括数字化河网及…

spark中 write.csv时, 添加第一行的标题title

在 Spark 中使用 write.csv 写入 CSV 文件时,默认情况下是不会在文件中添加标题行的。但是,你可以通过设置 header 选项来控制是否包含标题行。 下面是一个示例: val data Seq((1, "John", 28),(2, "Alice", 22),(3, …

Netty Review - Netty与Protostuff:打造高效的网络通信

文章目录 概念PrePomServer & ClientProtostuffUtil 解读测试小结 概念 Pre 每日一博 - Protobuf vs. Protostuff&#xff1a;性能、易用性和适用场景分析 Pom <dependency><groupId>com.dyuproject.protostuff</groupId><artifactId>protostuff-…

论文阅读——RS DINO

RS DINO: A Novel Panoptic Segmentation Algorithm for High Resolution Remote Sensing Images 基于MASKDINO模型&#xff0c;加了两个模块&#xff1a; BAM&#xff1a;Batch Attention Module 遥感图像切分的时候把一个建筑物整体比如飞机场切分到不同图片中&#xff0c;…

STM32微控制器在热电偶传感器应用中的性能评估

热电偶传感器是一种常用的温度测量技术&#xff0c;广泛应用于工业和自动化领域。在本文中&#xff0c;我们将探讨STM32微控制器在热电偶传感器应用中的性能评估。我们将涵盖STM32的特性、热电偶传感器的原理、硬件连接、软件编程以及性能评估的方法和指标。 STM32微控制器的特…