MIT6.824 Spring2021 Lab 1: MapReduce
文章目录
- 0x00 准备
- 0x01 MapReduce简介
- 0x02 RPC
- 0x03 调试
- 0x04 代码
- coordinator.go
- rpc.go
- worker.go
0x00 准备
- 阅读MapReduce论文
- 配置GO环境
因为之前没用过GO,所以 先在网上学了一下语法A Tour of Go
感觉Go的接口和方法的语法和C++挺不一样, 并发编程也挺有意思
0x01 MapReduce简介
需要实现master和coordinator。
MapReduce分为两个阶段:Map和Reduce阶段。
Map阶段函数提供Key,比如pg-being_ernest.txt
是key,然后Worker通过这个Key获取Value。比如pg-being_ernest.txt
的具体内容。然后将Key和Value(在例子中是文章的内容),传递给map function。获取结果,并将结果分成R个Reduce内容。
举个例子。假设我们要对pg-being_ernest.txt
和pg-dorian_gray.txt
统计词频。那么就要有两个Map Task
(不一定有两个Worker,比如有3个Worker,那么就是2个Worker干活一个围观;如果只有一个Worker,那么该Worker会被前后分配两次Map操作)。假设有3个Reduce操作,那么Map
的中间操作就会按照key被分为3个文件。
pg-being_ernest.txt
对应Map0 , Map0操作的kv被分进mr-0-0,mr-0-1,mr-0-2
pg-dorian_gray.txt
对应Map0 , Map0操作的kv被分进mr-1-0,mr-1-1,mr-1-2
当所有的Mapf已经生成结果,Worker就会被指派Reduce操作。比如被指派的Reduce操作编号为2,那么Reduce就会读取mr-0-2
,mr-1-2
。并且聚合相同的Key,传递给Reduce函数。
比如,pg-being_ernest.txt
中的map操作有kv,a 1 b 1 b 1
输出到mr-0-2
。pg-dorian_gray.txt
中的map操作有kv,c 1 b 1 c 1
输出到mr-0-2
。
然后Task编号为2的Reduce任务会读取所有对应的中间文件。得到key。a 1 b 1 b 1 c 1 b 1 c 1
。然后再对要处理的key进行排序,得到 a 1 b 1 b 1 b 1 c 1 c 1
。再按照相同的key调用reduce函数。
上面例子的调用为
reducef(key:"a",value:list[1])
,得到"1"
reducef(key:"b",value:list[1,1,1])
,得到"3"
reducef(key:"c",value:list[1,1])
,得到"2"最后将kvs:[{“a”,“1”},{“b”,“3”},{“c”,“2”}]写入该reduce生成的文件
mr-out-2
0x02 RPC
使用GO的RPC库,可以简单地实现Server
学习时参考了Go 每日一库之 rpc - 知乎 (zhihu.com)
在MapReduce操作流程中就是:
- 首先启动多个Worker(以下简称C)和一个Coordinator(以下简称S)
- C每隔一段时间(比如1s)会向S发送一个任务请求
- S首先检查Map任务还有没有分配完(注意不是运行完)。如果没有,分配一个Map任务给C
- 如果Map任务分配完了,并且还没有工作完,S让C等待
- 如果Map工作完了。Reduce还没分配完了,S给C分配一个空闲的Reduce任务
- 如果Reduce都工作完了,所有任务也都结束了。
- 如果C完成了任务,会向S发送一个请求。S知道了某个任务完成,就会进行相应的操作标记。
一些注意的点:
每个任务是有时间上限的(10s)。每分配一个任务就会启动一个GO程,然后等待相应的时间,检查是否完成了工作。如果没完成,将该任务编号重新加入管道。
如何判断一个任务是否完成呢?
比如第一个Worker申请到了任务1,过了10s钟还没有完成,S又将任务1加入待完成管道。此时第2个worker申请到了任务1,又过了4s,第一个Worker发送一个MapDone的请求给S。S如何判断是否完成了该任务。
我的处理是维护任务是由哪个Worker运行的状态。其中Worker由RPC的时间戳标记。比如worker1在第一次请求时时间戳为13213123
,Server维护maptask[1]是由13213123
正在运行,当第一次超时,maptask[1]变成了worker2请求时的时间戳``13219889。在第14s,收到MapDone的请求,检查其时间戳为
13213123`和当前正在运行的时间戳不同,所以丢弃掉该结果。
还有就是并发处理,这个使用锁就行了。
0x03 调试
- 命令行的参数:(因为不用shell的话不能用通配符pg*.txt代替,只能输入所有文件名)
pg-being_ernest.txt
pg-dorian_gray.txt
pg-frankenstein.txt
pg-grimm.txt
pg-huckleberry_finn.txt
pg-metamorphosis.txt
pg-sherlock_holmes.txt
pg-tom_sawyer.txt
- 在调试时出现报错
cannot load plugin ./wc.so err: plugin.Open("./wc"): plugin was built with a different version of package internal/abi
是因为build wc.so
时的参数和运行mr参数不一致导致的。
- 使用
./test-mr-many.sh 3
重复测试3次。通过测试
感觉Lab1做下来还是挺通透。像是引入GO和相关概念。通过lab,学习到了GO调试。
0x04 代码
coordinator.go
package mrimport ("log""sync""time"
)
import "net"
import "os"
import "net/rpc"
import "net/http"type status int // 用于指示worker的状态const (notStart status = iotarunningtaskDone
)
const workMaxTime = 12 * time.Secondtype Coordinator struct {// Your definitions here.nReduce int // Reduce数量mMap int // Map数量taskDone boolreduceTaskStatus []statusmapTaskStatus []status// runningMap 是当前正在running的rpcId// 想一下这种情况:第一个worker没有在10秒内返回结果,于是master开始把同样的任务返回给了第二个worker,此时又过了几秒,比如两秒钟// 那么master如何判断是第二个worker完成了任务,还是第一个worker呢?runningMap []RpcIdTrunningReduce []RpcIdTmapTasks chan TaskIdT // 待开始的mapreduceTasks chan TaskIdT // 待开始的reducefiles []string // 要进行task的文件mapCnt int // 已完成的map数量reduceCnt int // 已完成的reduce数量latch *sync.Cond
}// Your code here -- RPC handlers for the worker to call.// Example
// an example RPC handler.
//
// the RPC argument and reply types are defined in rpc.go.
func (c *Coordinator) Example(args *ExampleArgs, reply *ExampleReply) error {reply.Y = args.X + 1return nil
}// Appoint 用于worker请求一个任务
func (c *Coordinator) Appoint(request *ReqArgs, reply *ResArgs) error {reply.ResId = request.ReqIdreply.MapNumM = c.mMapreply.ReduceNumN = c.nReducec.latch.L.Lock()done := c.taskDonec.latch.L.Unlock()if done {reply.ResOp = WorkDonereturn nil}switch request.ReqOp {case WorkReq:{// 请求一个任务c.latch.L.Lock()if len(c.mapTasks) > 0 {// 如果map任务还没有完全分配 分配一个map workertaskId := <-c.mapTasksreply.ResTaskId = taskIdreply.ResContent = c.files[taskId]reply.ResOp = WorkMapc.runningMap[taskId] = reply.ResIdc.mapTaskStatus[taskId] = runningc.latch.L.Unlock()go c.checkDone(WorkMap, reply.ResTaskId)log.Printf("Assign map \t%d to \t%d\n", reply.ResTaskId, reply.ResId)return nil}if c.mapCnt < c.mMap {// 如果map任务已经全部分配完了,但是还没有运行完成,还不能开始reduce// worker需要暂时等待一下reply.ResOp = WorkNothingc.latch.L.Unlock()log.Println("Map All assigned but not done")return nil}if len(c.reduceTasks) > 0 {// 已经确定完成了所有map,还没有分配完reducetaskId := <-c.reduceTasksreply.ResTaskId = taskIdreply.ResOp = WorkReducec.runningReduce[taskId] = reply.ResIdc.reduceTaskStatus[taskId] = runningc.latch.L.Unlock()go c.checkDone(WorkReduce, reply.ResTaskId)log.Printf("Assign reduce \t%d to \t%d\n", reply.ResTaskId, reply.ResId)return nil}// 如果分配完了所有的reduce,但是还没有done.worker需要等待reply.ResOp = WorkNothinglog.Println("Reduce All assigned but not done")c.latch.L.Unlock()return nil}case WorkMapDone:{c.latch.L.Lock()defer c.latch.L.Unlock()if c.runningMap[request.ReqTaskId] != request.ReqId || c.mapTaskStatus[request.ReqTaskId] != running {// 说明该map已经被abortreply.ResOp = WorkTerminatereturn nil}log.Printf("Work Map \t%d done by \t%d\n", request.ReqTaskId, request.ReqId)c.mapTaskStatus[request.ReqTaskId] = taskDonec.mapCnt++}case WorkReduceDone:{c.latch.L.Lock()defer c.latch.L.Unlock()if c.runningReduce[request.ReqTaskId] != request.ReqId || c.reduceTaskStatus[request.ReqTaskId] != running {// 说明该map已经被abortreply.ResOp = WorkTerminatereturn nil}c.reduceTaskStatus[request.ReqTaskId] = taskDonec.reduceCnt++log.Printf("Work Reduce \t%d done by \t%d\n", request.ReqTaskId, request.ReqId)if c.reduceCnt == c.nReduce {c.taskDone = truereply.ResOp = WorkDone}}default:return nil}return nil
}// start a thread that listens for RPCs from worker.go
func (c *Coordinator) server() {log.Println("Launching Server")e := rpc.Register(c)if e != nil {log.Fatal("register error:", e)}rpc.HandleHTTP()//l, e := net.Listen("tcp", ":1234")sockname := coordinatorSock()_ = os.Remove(sockname)l, e := net.Listen("unix", sockname)go func(l net.Listener) {for {time.Sleep(5 * time.Second)if c.Done() {err := l.Close()if err != nil {log.Fatal("close error:", err)}}}}(l)if e != nil {log.Fatal("listen error:", e)}go func() {err := http.Serve(l, nil)if err != nil {log.Fatal("server error:", err)}}()
}// Done main/mrcoordinator.go calls Done() periodically to find out
// if the entire job has finished.
func (c *Coordinator) Done() bool {c.latch.L.Lock()defer c.latch.L.Unlock()// Your code here.return c.taskDone
}// checkDone 检查任务是否完成
func (c *Coordinator) checkDone(workType WorkType, t TaskIdT) {time.Sleep(workMaxTime)c.latch.L.Lock()defer c.latch.L.Unlock()switch workType {case WorkMap:{if c.mapTaskStatus[t] != taskDone {c.mapTaskStatus[t] = notStartc.mapTasks <- t}}case WorkReduce:{if c.reduceTaskStatus[t] != taskDone {// 如果没有完成任务c.reduceTaskStatus[t] = notStartc.reduceTasks <- t}}default:log.Panicf("Try Check Invalid WorkType %v\n", workType)}}// MakeCoordinator create a Coordinator.
// main/mrcoordinator.go calls this function.
// nReduce is the number of reduce tasks to use.
func MakeCoordinator(files []string, nReduce int) *Coordinator {log.Println("Launching Master Factory")c := Coordinator{}c.nReduce = nReducec.mMap = len(files) // 每个file对应一个mapc.taskDone = falsec.files = filesc.mapTasks = make(chan TaskIdT, c.mMap)c.mapTaskStatus = make([]status, c.mMap)c.runningMap = make([]RpcIdT, c.mMap)c.reduceTaskStatus = make([]status, nReduce)c.reduceTasks = make(chan TaskIdT, nReduce)c.runningReduce = make([]RpcIdT, nReduce)c.latch = sync.NewCond(&sync.Mutex{})for i := 0; i < c.mMap; i++ {c.mapTasks <- TaskIdT(i)c.runningMap[i] = -1c.mapTaskStatus[i] = notStart}for i := 0; i < c.nReduce; i++ {c.reduceTasks <- TaskIdT(i)c.runningReduce[i] = -1c.reduceTaskStatus[i] = notStart}c.server()return &c
}
rpc.go
package mr//
// RPC definitions.
//
// remember to capitalize all names.
//import "os"
import "strconv"//
// example to show how to declare the arguments
// and reply for an RPC.
//type ExampleArgs struct {X int
}type ExampleReply struct {Y int
}
type RpcIdT int64 // RpcIdT 是通过时间戳生成的, 指示一个唯一的RpcId
type ReqArgs struct {ReqId RpcIdTReqOp WorkTypeReqTaskId TaskIdT
}// ResArgs 是RPC的返回
// Response
type ResArgs struct {ResId RpcIdTResOp WorkTypeResTaskId TaskIdT // 分配的任务编号ResContent stringReduceNumN int // 有n个reduceMapNumM int // 有M个map任务
}
type WorkType int// TaskIdT 是对任务的编号
type TaskIdT int// 枚举工作类型
const (WorkNothing WorkType = iotaWorkReq // worker申请工作WorkMap // 分配worker进行map操作WorkReduce // 分配worker进行reduce操作WorkDone // [[unused]]master所有的工作完成WorkTerminate // 工作中止WorkMapDone // Worker完成了map操作WorkReduceDone // Worker完成了reduce操作
)// Rpc exports struct we need
type Rpc struct {Req ReqArgsRes ResArgs
}// Cook up a unique-ish UNIX-domain socket name
// in /var/tmp, for the coordinator.
// Can't use the current directory since
// Athena AFS doesn't support UNIX-domain sockets.
func coordinatorSock() string {s := "/var/tmp/824-mr-"s += strconv.Itoa(os.Getuid())return s
}
worker.go
package mrimport ("encoding/json""fmt""io""os""sort""strconv""time"
)
import "log"
import "net/rpc"
import "hash/fnv"const sleepTime = 500 * time.Millisecond// KeyValue
// Map functions return a slice of KeyValue
type KeyValue struct {Key stringValue string
}
type ByKey []KeyValue// Len 通过HashKey进行排序
func (a ByKey) Len() int { return len(a) }
func (a ByKey) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByKey) Less(i, j int) bool { return ihash(a[i].Key) < ihash(a[j].Key) }// use ihash(key) % NReduce to choose the reduce
// task number for each KeyValue emitted by Map.
func ihash(key string) int {h := fnv.New32a()_, err := h.Write([]byte(key))if err != nil {return 0}return int(h.Sum32() & 0x7fffffff)
}// Worker
// main/mrworker.go calls this function.
func Worker(mapf func(string, string) []KeyValue,reducef func(string, []string) string) {// Your worker implementation here.for {timeStamp := time.Now().Unix()rpcId := RpcIdT(timeStamp)req := ReqArgs{}req.ReqId = rpcIdreq.ReqOp = WorkReq // 请求一个工作res := ResArgs{}ok := call("Coordinator.Appoint", &req, &res)if !ok {// 如果Call发生错误log.Println("Maybe Coordinator Server has been closed")return}switch res.ResOp {case WorkDone:// 所有工作已经完成returncase WorkMap:doMap(rpcId, &res, mapf)case WorkReduce:doReduce(rpcId, &res, reducef)case WorkNothing:// 等待time.Sleep(sleepTime)default:break}time.Sleep(sleepTime)}
}
func doMap(rpcId RpcIdT, response *ResArgs, mapf func(string, string) []KeyValue) {// filename 是response中的文件名filename := response.ResContentfile, err := os.Open(filename)if err != nil {log.Fatalf("cannot open %v", filename)}defer func(file *os.File) {_ = file.Close()}(file)// content读取该文件中的所有内容content, err := io.ReadAll(file)if err != nil {log.Fatalf("cannot read %v", filename)}kvs := mapf(filename, string(content))// 需要将kv输出到n路 中间文件中ofiles := make([]*os.File, response.ReduceNumN)encoders := make([]*json.Encoder, response.ReduceNumN)for i := 0; i < response.ReduceNumN; i++ {// 这里输出的名字是mr-ResTaskId-reduceN// 其中,ResTaskId是0~m的数字oname := "mr-" + strconv.Itoa(int(response.ResTaskId)) + "-" + strconv.Itoa(i)ofiles[i], err = os.Create(oname)if err != nil {log.Fatal("Can't Create Intermediate File: ", oname)}defer func(file *os.File, oname string) {err := file.Close()if err != nil {log.Fatal("Can't Close Intermediate File", oname)}}(ofiles[i], oname)encoders[i] = json.NewEncoder(ofiles[i])}for _, kv := range kvs {ri := ihash(kv.Key) % response.ReduceNumNerr := encoders[ri].Encode(kv)if err != nil {log.Fatal("Encode Error: ", err)return}}req := ReqArgs{ReqId: rpcId,ReqOp: WorkMapDone,ReqTaskId: response.ResTaskId,}res := ResArgs{}call("Coordinator.Appoint", &req, &res)
}func doReduce(rpcId RpcIdT, response *ResArgs, reducef func(string, []string) string) {rid := response.ResTaskId // 当前reduce的编号var kva []KeyValuefor i := 0; i < response.MapNumM; i++ {// 读取所有该rid的中间值func(mapId int) {// 读取m-rid的中间值inputName := "mr-" + strconv.Itoa(i) + "-" + strconv.Itoa(int(rid))// 在当前对应r的输出中,获取所有keyifile, err := os.Open(inputName)if err != nil {log.Fatal("Can't open file: ", inputName)}defer func(file *os.File) {err := file.Close()if err != nil {log.Fatal("Can't close file: ", inputName)}}(ifile)dec := json.NewDecoder(ifile)for {var kv KeyValueif err := dec.Decode(&kv); err != nil {break}kva = append(kva, kv) //}}(i)}// 通过hashKey排序sort.Sort(ByKey(kva))intermediate := kva[:]oname := "mr-out-" + strconv.Itoa(int(rid))ofile, err := os.Create(oname)if err != nil {log.Fatal("Can't create file: ", oname)}defer func(ofile *os.File) {err := ofile.Close()if err != nil {log.Fatal("Can't close file: ", oname)}}(ofile)// log.Println("Total kv len: ", len(intermediate))// cnt := 0i := 0for i < len(intermediate) {j := i + 1for j < len(intermediate) && intermediate[j].Key == intermediate[i].Key {j++}var values []stringfor k := i; k < j; k++ {values = append(values, intermediate[k].Value)}// cnt++output := reducef(intermediate[i].Key, values)// this is the correct format for each line of Reduce output._, fprintf := fmt.Fprintf(ofile, "%v %v\n", intermediate[i].Key, output)if fprintf != nil {return}i = j}// log.Println("Unique key count: ", cnt)req := ReqArgs{ReqId: rpcId,ReqOp: WorkReduceDone,ReqTaskId: response.ResTaskId,}res := ResArgs{}call("Coordinator.Appoint", &req, &res)
}// CallExample
// example function to show how to make an RPC call to the coordinator.
//
// the RPC argument and reply types are defined in rpc.go.
func CallExample() {// declare an argument structure.args := ExampleArgs{}// fill in the argument(s).args.X = 99// declare a reply structure.reply := ExampleReply{}// send the RPC request, wait for the reply.call("Coordinator.Example", &args, &reply)// reply.Y should be 100.fmt.Printf("reply.Y %v\n", reply.Y)
}// send an RPC request to the coordinator, wait for the response.
// usually returns true.
// returns false if something goes wrong.
func call(rpcName string, args interface{}, reply interface{}) bool {// c, err := rpc.DialHTTP("tcp", "127.0.0.1"+":1234")sockname := coordinatorSock()c, err := rpc.DialHTTP("unix", sockname)if err != nil {log.Fatal("dialing:", err)}defer func(c *rpc.Client) {err := c.Close()if err != nil {log.Fatal("Close Client Error When RPC Calling", err)}}(c)err = c.Call(rpcName, args, reply)if err == nil {return true}fmt.Println(err)return false
}
相关文章:
![](https://img-blog.csdnimg.cn/img_convert/cdb5dff7d3e80905afa676c5f792e305.jpeg)
MIT6.824 Spring2021 Lab 1: MapReduce
文章目录 0x00 准备0x01 MapReduce简介0x02 RPC0x03 调试0x04 代码coordinator.gorpc.goworker.go 0x00 准备 阅读MapReduce论文配置GO环境 因为之前没用过GO,所以 先在网上学了一下语法A Tour of Go 感觉Go的接口和方法的语法和C挺不一样, 并发编程也挺有意思 0x01 MapRed…...
![](https://www.ngui.cc/images/no-images.jpg)
JavaScript 日期 – 如何使用 DayJS 库在 JS 中处理日期和时间
当涉及到在 JavaScript 中处理日期和时间时,开发人员经常发现自己正在努力应对内置对象的复杂性Date。 虽然普通 JavaScript 提供了基本功能,但使用起来可能相当麻烦,尤其是在处理解析、格式化和操作日期时。 这就是像 DayJS 这样的外部库发挥作用的地方,它提供了大量的优…...
![](https://img-blog.csdnimg.cn/849c0f6107844b1abf43ece746a9b554.png#pic_center)
Docker基础入门:Docker基础总结篇--超详细
Docker基础入门:Docker基础总结篇[docker3要素、docker安装配置、容器使用、镜像管理发布] 一、Docker 3要素1.1、镜像(Image)1.2、容器(Container)1.3、仓库(Registry)1.4 、总结 二、Docker安…...
![](https://img-blog.csdnimg.cn/img_convert/7f2c37406539a9ea396cad84315afc74.png)
对象临时中间状态的条件竞争覆盖
Portswigger练兵场之条件竞争 🦄条件竞争之对象临时中间状态的条件竞争 Lab: Partial construction race conditions🚀实验前置必要知识点 某些框架尝试通过使用某种形式的请求锁定来防止意外的数据损坏。例如,PHP 的本机会话处理程序模块…...
![](https://img-blog.csdnimg.cn/img_convert/230be051a11cde2cd888e24fe7922683.png)
Nodejs 第十四章(process)
process 是Nodejs操作当前进程和控制当前进程的API,并且是挂载到globalThis下面的全局API API 介绍 1. process.arch 返回操作系统 CPU 架构 跟我们之前讲的os.arch 一样 arm、arm64、ia32、mips、mipsel、ppc、ppc64、s390、s390x、以及 x64 2. process.cwd() …...
![](https://img-blog.csdnimg.cn/565015d53f7c40e5bebcf6b2720630b0.png)
数据分析因子评分学习
当多个因素影响一个结果时,我们需要综合考虑这些因素分别对结果德影响。因子评分就是用于比较其对结果德影响程度。 文章目录 前言一、案例背景二、解决方案(一)分析思路(二)剔除无关数据(三)求…...
![](https://img-blog.csdnimg.cn/fcc4eda096624c7eb8202dca8836761d.png)
【postgresql 基础入门】数据库服务的管理
数据库服务管理 专栏内容: postgresql内核源码分析手写数据库toadb并发编程 开源贡献: toadb开源库 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤ÿ…...
![](https://img-blog.csdnimg.cn/995ae939af4541138f62577ce7aebb71.png)
githubPage部署Vue项目
github中新建项目 my-web (编写vue项目代码) myWebOnline(存放Vue打包后的dist包里面的文件) 发布流程 (假设my-web项目已经编写完成)Vue-cli my-web vue.config.js文件中 const { defineConfig } require(vue/cli-service)…...
![](https://www.ngui.cc/images/no-images.jpg)
【网络编程】网络原来这么简单(更新中)
故事背景:有一天小胖和他的朋友细狗出去吃饭,聊着聊着就聊到了网络,小胖是学校里的编程大佬,而细狗只是个空有求知欲的编程小白。 细狗:胖儿啊,你说计算机是怎么通信的我感觉好抽象啊。为啥别人给我发个消息…...
![](https://img-blog.csdnimg.cn/4cd815c0441c4a6dbfc71c459f7ecafe.webp)
监控系统典型架构
监控系统典型架构如下: 从左往右看: 采集器是负责采集监控数据的,采集到数据之后传输给服务端,通常是直接写入时序库。 对时序库的数据进行分析和可视化。 告警引擎产生告警事件之后交给告警发送模块做不同媒介的通知。 可视化比…...
![](https://img-blog.csdnimg.cn/28b903b5c26349e58d0ed1b095af94c3.png)
jsp 新能源汽车论坛网Myeclipse开发mysql数据库web结构java编程计算机网页项目
一、源码特点 JSP 新能源汽车论坛网是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0…...
![](https://img-blog.csdnimg.cn/2530c6729ab8490ab9b35b34be78a7bc.png)
Code Snippet的使用
文章目录 前言Code Snippet:就是咱们在VS中敲的prop、propfull、ctol【构造器快捷键】、for等快捷键,然后按tab键自动生成代码1.VS自带的:prop、propfull、ctol【构造器快捷键】、for等快捷键,直接使用2.自定义Snippet: 巨人的肩膀…...
![](https://img-blog.csdnimg.cn/9e0374adf6bd4c22a1ec4d4730afe043.png)
华为云云服务器评测|华为云耀云L搭建zerotier服务测试
0. 环境 - Win10 - 云耀云L服务器 1. 安装docker 检查yum源,本EulerOS的源在这里: cd /etc/yum.repos.d 更新源 yum makecache 安装 yum install -y docker-engine 运行测试 docker run hello-world 2. 运行docker镜像 默认配…...
![](https://img-blog.csdnimg.cn/894faaefc1434e9c814f3cbfdf989d4a.jpeg)
企业电脑文件加密系统 / 防泄密软件——「天锐绿盾」
「天锐绿盾」是一种公司文件加密系统,旨在保护公司内网数据安全,防止信息泄露。该系统由硬件和软件组成,其中包括服务端程序、控制台程序和终端程序。 PC访问地址: isite.baidu.com/site/wjz012xr/2eae091d-1b97-4276-90bc-6757c…...
![](https://img-blog.csdnimg.cn/img_convert/81d7600bb7ef1061dc16515eca0ad065.jpeg)
单条视频涨粉50w,逃出大英博物馆背后的逻辑是什么?
为洞察小红书平台的内容创作趋势及品牌营销策略,新红推出8月月度榜单,从创作者、品牌、品类多方面入手,解析月榜数据,为从业者提供参考。 一条视频涨粉50w 情感共鸣是爆火的核心 据8月的『涨粉排行榜』TOP500数据显示,…...
![](https://www.ngui.cc/images/no-images.jpg)
AIGC(生成式AI)试用 1 -- 基本文本查询
以一个字起,依次加一个字构成新句,不断加字使句子越来越长,也许越来越有趣。 1. 使用不同的生成AI提问,提取结果(全部 或 第一句),对比结果,个人评价更喜欢哪个(绿色底色…...
![](https://www.ngui.cc/images/no-images.jpg)
php如何处理高并发请求
PHP 处理高并发请求的方法: 使用异步框架:通过使用异步处理方式,可以有效地降低 PHP 处理请求的响应时间,避免因为 IO 操作而导致的等待阻塞。常用的异步框架有ReactPHP和Swoole等。 使用缓存:使用缓存可以减少每个请求…...
![](https://www.ngui.cc/images/no-images.jpg)
控制台实现汽车租赁系统
汽车租赁系统需求:(基于控制台实现,适合基础小白练习使用) 1、包含汽车租赁和汽车管理两个模块 2、汽车租赁需要包含汽车租赁天数以及汽车租金结算功能 3、汽车管理需要包含租赁汽车的添加、删除、修改、查询功能 代码如下&#…...
![](https://www.ngui.cc/images/no-images.jpg)
机器学习和数据挖掘03-模型性能评估指标
Accuracy(准确率) 概念:模型正确预测的样本数量与总样本数量的比例。 公式:Accuracy (TP TN) / (TP TN FP FN) TP (True Positives):正确预测为正例的样本数。即模型正确地将正例判定为正例。 TN (True Negati…...
![](https://www.ngui.cc/images/no-images.jpg)
PageNumberPagination、LimitOffsetPagination、CursorPagination
数据 from django.db import modelsclass User(models.Model):username models.CharField(max_length64, verbose_name用户名)password models.CharField(max_length64, verbose_name密码)# 用户类型user_type models.IntegerField(choices((1, 菜鸟用户), (2, 普通用户), …...
![](https://img-blog.csdnimg.cn/img_convert/0cd9e8f935fdc93526f506be86049227.png)
怎么把视频转换成mp4格式
怎么把视频转换成mp4格式?如今,随着科技的不断发展,我们在工作中接触到的多媒体视频格式也越来越多。其中,MP4作为一种广泛兼容的视频格式,在许多软件中都能轻松播放,并且成为了剪辑与裁剪视频时大家常用的…...
![](https://www.ngui.cc/images/no-images.jpg)
正则判断字符是否包含手机号
字符前后不能是数字,满足手机号标准 String msg "19009098989";String mobliePattern "((?<!\\d))(mobile|手机号|)(|\\[|\\\":\\\"|:|:||:|)(1)([3-9]{1}\\d{1})(\\d{4})(\\d{4})(\\]|\\\"||)((?!\\d))";String mobileR…...
![](https://img-blog.csdnimg.cn/img_convert/23c7d84d9172d921b5fbbdd2ece4f388.png)
OSCP系列靶场-Esay-Sumo
OSCP系列靶场-Esay-Sumo 总结 getwebshell : nikto扫描 → 发现shellshock漏洞 → 漏洞利用 → getwebshell 提 权 思 路 : 内网信息收集 → 内核版本较老 →脏牛提权 准备工作 启动VPN 获取攻击机IP → 192.168.45.194 启动靶机 获取目标机器IP → 192.168.190.87 信息收…...
![](https://img-blog.csdnimg.cn/img_convert/cf18ac649249f426c9f7f61b1d8f641a.png)
本地电脑搭建web服务器、个人博客网站并发布公网访问 【无公网IP】(1)
文章目录 前言1. 安装套件软件2. 创建网页运行环境 指定网页输出的端口号3. 让WordPress在所需环境中安装并运行 生成网页4. “装修”个人网站5. 将位于本地电脑上的网页发布到公共互联网上 前言 在现代社会,网络已经成为我们生活离不开的必需品,而纷繁…...
![](https://www.ngui.cc/images/no-images.jpg)
Python基础List列表定义与函数
如何定义一个非空的列表? name_list ["liming","xiaohong",15,{"hobby":"basketball"}] 列表的特点: 1.列表是有序的 2.可以存放多个元素 3.每个元素可以是任何数据类型 定义一个空列表 name_list [] 访…...
![](https://www.ngui.cc/images/no-images.jpg)
typeScript--[数据定义]
一.安装ts 1.命令行运行如下命令,全局安装 TypeScript: npm install -g typescript2.安装完成后,在控制台运行如下命令,检查安装是否成功 tsc -V 二.创建ts文件 1.创建一个day01.ts文件,随便在里面码一点代码&…...
![](https://www.ngui.cc/images/no-images.jpg)
【常见相机模型】
常见相机模型 enum class Type {kPinhole 0,kUnifiedProjection 1,kOmni 2, //optimize_on_spherekEqFisheye 3};其余类型optimize_on_plane这4种类型的相机模型具有以下差异: kPinhole (针孔相机模型):这是最基本和常见的相机模型。它假设光线通过…...
![](https://img-blog.csdnimg.cn/c51cee75d3e74e3dbe30457c5b7a77cb.png)
大数据-玩转数据-Flink状态编程(上)
一、Flink状态编程 有状态的计算是流处理框架要实现的重要功能,因为稍复杂的流处理场景都需要记录状态,然后在新流入数据的基础上不断更新状态。 SparkStreaming在状态管理这块做的不好, 很多时候需要借助于外部存储(例如Redis)来手动管理状态, 增加了编…...
![](https://img-blog.csdnimg.cn/3112de0520cf4ecfa2edddefc7a15fd2.png#pic_center)
主动获取用户的ColaKey接口
主动获取用户的ColaKey接口 一、主动获取用户的ColaKey接口二、使用步骤1、接口***重要提示:建议使用https协议,当https协议无法使用时再尝试使用http协议***2、请求参数 三、 请求案例和demo1、请求参数例子(POST请求,参数json格式)2、响应返…...
![](https://img-blog.csdnimg.cn/82baf0b586e94b60ab09989f8e601ef7.png)
C#写一个UDP程序判断延迟并运行在Centos上
服务端 using System.Net.Sockets; using System.Net;int serverPort 50001; Socket server; EndPoint client new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号CreateSocket();void CreateSocket() {server new Socket(AddressFamily.InterNetwork, SocketT…...
![](/images/no-images.jpg)
wordpress英文主题改成中文版/百度网盘优化
Platform: RockchipOS: Android 6.0Kernel: 3.10.92普通类型的多个文件拷贝:方法一:PRODUCT_COPY_FILES $(call find-copy-subdir-files,*,$(LOCAL_PATH)/src_dir,system/etc/dst_dir/)方法二:此方法因为在source envsetup.sh之前执行&#…...
![](https://img-blog.csdnimg.cn/b8fe38d807194bbfb62865c4095a1add.jpeg#pic_center)
做展柜平时在哪里网站推广/推广方式怎么写
定点型 MySQL中使用浮点数类型和定点数类型来表示小数。 浮点型在数据库中存放的是近似值,定点类型在数据库中存放的是精确值。 浮点数类型包括单精度浮点数(float型)和双精度浮点数(double型)。定点数类型就是decim…...
![](/images/no-images.jpg)
网站怎样做注册窗口/合肥网络推广网络运营
go语言是谷歌开发第二款开源编程语言,可专门针对多处理器系统应用程序的编程进行优化,其运行速度快,而且更加安全,并支持并行进程。除此之外,还具有以下优点: 1. go语言部署简单。 go语言编译生成的是一个…...
![](https://img-blog.csdnimg.cn/img_convert/114f32a787a47fc5c6b9e8410b78aa41.png)
购物网站支付功能怎么做/在线网页制作
今天和大家分享一个能在手机上演示的高保真移动端元件库。 43页完整版案例(含页面跳转交互)预览地址:https://axhub.im/ax9/bace41c00c111653/#g1 135页元件库(只含单页交互)预览地址:https://axhub.im/a…...
![](https://img-blog.csdnimg.cn/img_convert/07c2dd918c3535227a59cb73f0e5775e.png)
做网站买主机还是服务器/还有哪些平台能免费营销产品
上证综合指数作为A股市场第一条股票指数,将于7月22日迎来重大优化。修订后的编制方案将剔除风险警示股票、延长新股计入时间,并计入科创板上市证券。上证综合指数等以样本股的发行股本数为权数进行加权计算,计算公式为: 报告期指…...
![](/images/no-images.jpg)
做网站得每年续费吗/揭阳seo快速排名
但凡使用mybatis,同时与spring集成使用时,接下来要说的这个问题是躲不了的。众所周知,mybatis的SqlSessionFactory在获取一个SqlSession时使用默认Executor或必须要指定一个Executor,这样一来,在同一个SqlSession的生命…...