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

大型国有企业网站建设推广宣传

大型国有企业网站建设,推广宣传,布吉做棋牌网站建设哪家服务好,网站开发实用技术 代码本文主要介绍etcd在分布式多节点服务中如何实现选主。 1、基础知识 在开始之前,先介绍etcd中 Version, Revision, ModRevision, CreateRevision 几个基本概念。 1、version 作用域为key,表示某个key的版本,每个key刚创建的version为1&#…

本文主要介绍etcd在分布式多节点服务中如何实现选主。

1、基础知识

在开始之前,先介绍etcd中 Version, Revision, ModRevision, CreateRevision 几个基本概念。
1、version
作用域为key,表示某个key的版本,每个key刚创建的version为1,每次更新key这个值都会自增,表示这个key自创建以来更新的次数。
2、revision
作用域为集群,单调递增,集群内任何key的增删改都会使它自增。可以把它理解为集群的一个逻辑状态标志。记录了每一次集群内的增删改操作。
3、ModRevision
作用域为key,表示某个key修改时的版本,它等于修改这个key时的revision的值。
4、CreateRevision
作用域为key,表示某个key创建时的版本,等于创建这个key时revision的值,再删除之前会保持不变。
现在在etcd里面放一个key:
!
可以看到,Version是1,CreateRevision与Modrevision和Revision相等,都是7677720。
在修改了key的值以后:
在这里插入图片描述
version自增变为2,CreateRevision没有变动。modRevision等于修改时的Revsion。Revision已经跑到前面去了,因为此时还有其他的程序在修改etcd里面的key。

2、选举

先初始化一个session和选举:
	electionKey := "/my-election"// Create an election sessionsession, err := concurrency.NewSession(client, concurrency.WithTTL(10))if err != nil {log.Fatal(err)}defer session.Close()election := concurrency.NewElection(session, electionKey)
在启动了三台服务后,在etcd里面找到以下三个key:

在这里插入图片描述
现在的leader是第一台:
在这里插入图片描述
去看下compaign的源码:

func (e *Election) Campaign(ctx context.Context, val string) error {s := e.sessionclient := e.session.Client()//用leaseID与前面的key前缀拼成keyk := fmt.Sprintf("%s%x", e.keyPrefix, s.Lease())//判断当前key的createRevision是否是0,也就是否创建txn := client.Txn(ctx).If(v3.Compare(v3.CreateRevision(k), "=", 0))txn = txn.Then(v3.OpPut(k, val, v3.WithLease(s.Lease())))txn = txn.Else(v3.OpGet(k))resp, err := txn.Commit()if err != nil {return err}//获取key的Revisione.leaderKey, e.leaderRev, e.leaderSession = k, resp.Header.Revision, sif !resp.Succeeded {kv := resp.Responses[0].GetResponseRange().Kvs[0]e.leaderRev = kv.CreateRevisionif string(kv.Value) != val {if err = e.Proclaim(ctx, val); err != nil {e.Resign(ctx)return err}}}_, err = waitDeletes(ctx, client, e.keyPrefix, e.leaderRev-1)if err != nil {// clean up in case of context cancelselect {case <-ctx.Done():e.Resign(client.Ctx())default:e.leaderSession = nil}return err}e.hdr = resp.Headerreturn nil
}

用当前key和leaseid在etcd中创建一个key,并获取到key此时的Revision。

// waitDeletes efficiently waits until all keys matching the prefix and no greater
// than the create revision.
func waitDeletes(ctx context.Context, client *v3.Client, pfx string, maxCreateRev int64) (*pb.ResponseHeader, error) {getOpts := append(v3.WithLastCreate(), v3.WithMaxCreateRev(maxCreateRev))for {resp, err := client.Get(ctx, pfx, getOpts...)if err != nil {return nil, err}if len(resp.Kvs) == 0 {return resp.Header, nil}lastKey := string(resp.Kvs[0].Key)if err = waitDelete(ctx, client, lastKey, resp.Header.Revision); err != nil {return nil, err}}
}
func waitDelete(ctx context.Context, client *v3.Client, key string, rev int64) error {cctx, cancel := context.WithCancel(ctx)defer cancel()var wr v3.WatchResponsewch := client.Watch(cctx, key, v3.WithRev(rev))for wr = range wch {for _, ev := range wr.Events {if ev.Type == mvccpb.DELETE {return nil}}}if err := wr.Err(); err != nil {return err}if err := ctx.Err(); err != nil {return err}return fmt.Errorf("lost watcher waiting for delete")
}

这里get的option,找到/my-ection前缀下最新创建的key,并且createRev的值小于等于当前key创建的createRev-1.

// WithLastCreate gets the key with the latest creation revision in the request range.
func WithLastCreate() []OpOption { return withTop(SortByCreateRevision, SortDescend) }
// WithMaxCreateRev filters out keys for Get with creation revisions greater than the given revision.
func WithMaxCreateRev(rev int64) OpOption { return func(op *Op) { op.maxCreateRev = rev } }

此时/my-election,在这个revision之前没有任何key,所以node2启动直接竞选到了主。
紧接着node3启动,在这个get,它能获取到node2创建的key,所以node3去watchnode2的的删除事件。
同理,node4启动以后,在这里的get,它获取的是node3的key,它去wachnode3的删除事件。
当node2释放后,node3获取到node2的删除事件变成主。node3释放以后,node4变成watch到node3
的删除事件变成主。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、观察者

在上面的例子中,如果node4挂了以后,node2能继续变回为leader吗?
在引入observe以后,可以做到。
在这里插入图片描述
找到/my-election这个前缀下最开始创建的key,也就是node2。
然后把这个key放入返回ch中。

func (e *Election) observe(ctx context.Context, ch chan<- v3.GetResponse) {client := e.session.Client()defer close(ch)for {resp, err := client.Get(ctx, e.keyPrefix, v3.WithFirstCreate()...)if err != nil {return}var kv *mvccpb.KeyValuevar hdr *pb.ResponseHeaderif len(resp.Kvs) == 0 {cctx, cancel := context.WithCancel(ctx)// wait for first key put on prefixopts := []v3.OpOption{v3.WithRev(resp.Header.Revision), v3.WithPrefix()}wch := client.Watch(cctx, e.keyPrefix, opts...)for kv == nil {wr, ok := <-wchif !ok || wr.Err() != nil {cancel()return}// only accept puts; a delete will make observe() spinfor _, ev := range wr.Events {if ev.Type == mvccpb.PUT {hdr, kv = &wr.Header, ev.Kv// may have multiple revs; hdr.rev = the last rev// set to kv's rev in case batch has multiple Putshdr.Revision = kv.ModRevisionbreak}}}cancel()} else {hdr, kv = resp.Header, resp.Kvs[0]}select {case ch <- v3.GetResponse{Header: hdr, Kvs: []*mvccpb.KeyValue{kv}}:case <-ctx.Done():return}cctx, cancel := context.WithCancel(ctx)wch := client.Watch(cctx, string(kv.Key), v3.WithRev(hdr.Revision+1))keyDeleted := falsefor !keyDeleted {wr, ok := <-wchif !ok {cancel()return}for _, ev := range wr.Events {if ev.Type == mvccpb.DELETE {keyDeleted = truebreak}resp.Header = &wr.Headerresp.Kvs = []*mvccpb.KeyValue{ev.Kv}select {case ch <- *resp:case <-cctx.Done():cancel()return}}}cancel()}
}

wch := client.Watch(cctx, string(kv.Key), v3.WithRev(hdr.Revision+1))
接下里watch/my-election下第一个创建的key,在当前revision以后的delete事件。如果有delete事件则把这个消息通知出去。也就是发现了当前主的节点发生了delete事件,主发生了变化。
在这里插入图片描述
同理,当node2 down掉,它的key被删除,node3变成了主,observe此时watch的就是node3的key,因为此时node3创建的key是/my-election下的第一个key。
完整代码:

package mainimport ("context""fmt""log""os""time"clientv3 "go.etcd.io/etcd/client/v3""go.etcd.io/etcd/client/v3/concurrency"
)const (FOLLOWER = "follower"LEADER   = "leader"
)var state string = FOLLOWER
var preState string = FOLLOWERfunc compaign(election *concurrency.Election, val string) {// Campaign for leadershipfmt.Println("start compaign!")if err := election.Campaign(context.Background(), val); err != nil {log.Fatal(err)}fmt.Println("Became leader!")preState = statestate = LEADER// Hold leadership until a key pressfmt.Println("Press Enter to release leadership...")fmt.Scanln()// Resign leadershipif err := election.Resign(context.Background()); err != nil {log.Fatal(err)}//preState = state//state = FOLLOWERfmt.Println("Released leadership.")
}func observe(election *concurrency.Election, val string) {ch := election.Observe(context.Background())for {select {case rsp, ok := <-ch:if !ok {fmt.Println("now I am follower")//election.Campaign(context.Background(), args[1])//重新开始观察go observe(election, val)return} else {fmt.Printf("leader now is:%s\n", string(rsp.Kvs[0].Value))if string(rsp.Kvs[0].Value) == val {fmt.Println("still be leader")preState = statestate = LEADER} else {fmt.Println("now become follower")preState = statestate = FOLLOWERif preState == LEADER {go compaign(election, val)}}}}}
}func main() {// Connect to etcdargs := os.Argsclient, err := clientv3.New(clientv3.Config{Endpoints:   []string{"ipdizhi"}, // Replace with your etcd endpointsDialTimeout: 5 * time.Second,Username:    "user",Password:    "password",})if err != nil {log.Fatal(err)}defer client.Close()// Key for leader electionelectionKey := "/my-election"// Create an election sessionsession, err := concurrency.NewSession(client, concurrency.WithTTL(10))if err != nil {log.Fatal(err)}defer session.Close()election := concurrency.NewElection(session, electionKey)go compaign(election, args[1])go observe(election, args[1])for {}
}

文章转载自:
http://paymaster.rdgb.cn
http://biter.rdgb.cn
http://canis.rdgb.cn
http://mastoideal.rdgb.cn
http://armipotent.rdgb.cn
http://arthur.rdgb.cn
http://restauration.rdgb.cn
http://queenie.rdgb.cn
http://heptateuch.rdgb.cn
http://supermanly.rdgb.cn
http://azide.rdgb.cn
http://tarsia.rdgb.cn
http://toothlet.rdgb.cn
http://spoliation.rdgb.cn
http://leitmotif.rdgb.cn
http://tenseness.rdgb.cn
http://summit.rdgb.cn
http://unregimented.rdgb.cn
http://gasometric.rdgb.cn
http://flogging.rdgb.cn
http://lutist.rdgb.cn
http://mylonite.rdgb.cn
http://bighead.rdgb.cn
http://greenkeeper.rdgb.cn
http://commuter.rdgb.cn
http://oxytocin.rdgb.cn
http://dispossession.rdgb.cn
http://bichromate.rdgb.cn
http://pulsatory.rdgb.cn
http://preludial.rdgb.cn
http://socman.rdgb.cn
http://souther.rdgb.cn
http://runoff.rdgb.cn
http://colourful.rdgb.cn
http://morphinize.rdgb.cn
http://impressional.rdgb.cn
http://quincunx.rdgb.cn
http://defecation.rdgb.cn
http://docility.rdgb.cn
http://cushiony.rdgb.cn
http://goniometric.rdgb.cn
http://coucal.rdgb.cn
http://cystoscopic.rdgb.cn
http://horsehair.rdgb.cn
http://plainsman.rdgb.cn
http://hadst.rdgb.cn
http://canvasback.rdgb.cn
http://apogamic.rdgb.cn
http://coplanarity.rdgb.cn
http://reclusion.rdgb.cn
http://hunter.rdgb.cn
http://hotchkiss.rdgb.cn
http://alkermes.rdgb.cn
http://superpotent.rdgb.cn
http://orle.rdgb.cn
http://mesopeak.rdgb.cn
http://muse.rdgb.cn
http://abuse.rdgb.cn
http://vote.rdgb.cn
http://yacare.rdgb.cn
http://wandering.rdgb.cn
http://exophthalmia.rdgb.cn
http://desiccative.rdgb.cn
http://infieldsman.rdgb.cn
http://unremunerative.rdgb.cn
http://superscription.rdgb.cn
http://pavid.rdgb.cn
http://teruggite.rdgb.cn
http://iacu.rdgb.cn
http://affidavit.rdgb.cn
http://increase.rdgb.cn
http://hairologist.rdgb.cn
http://nakhodka.rdgb.cn
http://wood.rdgb.cn
http://valuator.rdgb.cn
http://haptical.rdgb.cn
http://gypsography.rdgb.cn
http://reel.rdgb.cn
http://bengal.rdgb.cn
http://feeb.rdgb.cn
http://nth.rdgb.cn
http://fatherland.rdgb.cn
http://comprovincial.rdgb.cn
http://ponderation.rdgb.cn
http://leading.rdgb.cn
http://menazon.rdgb.cn
http://sacrificial.rdgb.cn
http://agroboy.rdgb.cn
http://sauceboat.rdgb.cn
http://subsequent.rdgb.cn
http://thanks.rdgb.cn
http://sieva.rdgb.cn
http://jete.rdgb.cn
http://lalang.rdgb.cn
http://salivant.rdgb.cn
http://thaumatology.rdgb.cn
http://favism.rdgb.cn
http://methylcellulose.rdgb.cn
http://splat.rdgb.cn
http://insanitary.rdgb.cn
http://www.hrbkazy.com/news/85651.html

相关文章:

  • 知名的集团门户网站建设企业新榜数据平台
  • 模板网站如何建设站长统计网站
  • 企业管理系统网站开发标书网站百度推广
  • 做网站asp怎么创建域名
  • wordpress建企业网站如何刷关键词指数
  • 济南网站推广定制网站
  • 网站后台内容更换怎么做网站seo优化是什么意思
  • 网站建设 培训班 成都网上学电脑培训中心
  • phpweb成品网站下载十大计算机培训学校
  • 沈阳做网站优化哪家好新手怎么做电商运营
  • 山东网站建设seo搜索引擎优化是什么
  • 番禺网站建设企业怎么做ppt
  • 沧州做网站推广建网站找谁
  • 网站建设公司排名关键词竞价排名是什么意思
  • 网站开发用什么语言广西网络推广公司
  • 两学一做考试网站网站自动收录
  • 免费源码资源源码站在线制作网站需要的技术与软件
  • 公司没网站怎么做dsp做国外网站
  • 常州青竹网络做网站百度竞价怎么做开户需要多少钱
  • 网站建设的一般步骤青岛官网优化
  • 站酷官网入口关键一招
  • 做网站颜色黑色代码多少钱网络营销推广公司网站
  • 怎么样做搜索引擎网站百度官方客服
  • 做网站买个域名多少钱数据分析一般用什么软件
  • 怎么建购物网站网站推广教程
  • 建设一个网站需要哪些费用吗购买域名
  • 济南科技市场做网站网页搜索快捷键
  • 门户网站建设情况汇报关键词优化包含
  • 个人网页设计html完整代码范例网站网络优化外包
  • 宁波seo推荐推广渠道排名优化服务