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

淘宝客怎么建设网站如何推广一个新的app

淘宝客怎么建设网站,如何推广一个新的app,建设部网站法律法规,wordpress返回redsync使用教程前言redsync结构Pool结构Mutex结构acquire加锁操作release解锁操作redsync包的使用前言 在编程语言中锁可以理解为一个变量,该变量在同一时刻只能有一个线程拥有,以便保护共享数据在同一时刻只有一个线程去操作。对于高可用的分布式锁应…

redsync使用教程

  • 前言
  • redsync结构
    • Pool结构
    • Mutex结构
      • acquire加锁操作
      • release解锁操作
  • redsync包的使用

前言

在编程语言中锁可以理解为一个变量,该变量在同一时刻只能有一个线程拥有,以便保护共享数据在同一时刻只有一个线程去操作。对于高可用的分布式锁应该满足以下条件:
1.互斥:在任意时间内,只有一个客户能够获得一把锁,具有排他性。
2.避免死锁:即使客户端宕机或者从集群中分离了,其它客户端仍然可以获取到该锁
3.容错:只要大部分Redis节点存活,客户端就能正确地获取锁和释放锁。即使锁住某个资源的客户端释放锁之前崩溃或者网络分区仍然能够获取锁和释放锁。
对于Redis高可用集群而言,上述三个条件都非常容易满足,所以适合做分布式锁。

redsync结构

redsync 的通用结构定义如下:

  • Pool:抽象连接池
  • Conn:抽象每个 Redis 连接
  • Script:Redis 脚本

Pool结构

redsync结构的Pools是一个redis.pool数组,每个 redis.Pool 都是上面的 Pool 实现,它代表了一个 Redis 实例的连接池:
在这里插入图片描述

Mutex结构

Mutex代表了一个分布式锁,其成员多为 redlock 算法所需要的条件:

// A Mutex is a distributed mutual exclusion lock.
type Mutex struct {name   string  				// 名称expiry time.Duration    	// 锁的有效时间tries     int   // 尝试次数delayFunc DelayFunc // 失败尝试设置延迟factor float64 // 误差系数控制quorum int // 投票数 一般为节点数 / 2+1,节点数为奇数genValueFunc func() (string, error)  // 加密函数,生成唯一随机串value        string  // 默认就是唯一随机串until        time.Time // 过期时间pools []Pool // 连接池(每个 Pool 指一个 Redis 实例)
}

获取锁的Lock方法实现了redLock的加锁接口,具体实现如下

func (m *Mutex) LockContext(ctx context.Context) error {if ctx == nil {ctx = context.Background()}//生成随机串,base64value, err := m.genValueFunc()if err != nil {return err}//不超过tries次数进行加锁for i := 0; i < m.tries; i++ {if i != 0 {time.Sleep(m.delayFunc(i))}start := time.Now()n, err := func() (int, error) {ctx, cancel := context.WithTimeout(ctx, time.Duration(int64(float64(m.expiry)*m.timeoutFactor)))defer cancel()//尝试异步去获取锁return m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {return m.acquire(ctx, pool, value)})}()now := time.Now()// 过期时间 = 有效时间值 - 获取锁消耗的时间值 - 有效时间值 * 误差系数until := now.Add(m.expiry - now.Sub(start) - time.Duration(int64(float64(m.expiry)*m.driftFactor)))//成功节点数>=节点数/2+1&& 未过期时,判定加锁成功	if n >= m.quorum && now.Before(until) {m.value = valuem.until = untilreturn nil}func() (int, error) {ctx, cancel := context.WithTimeout(ctx, time.Duration(int64(float64(m.expiry)*m.timeoutFactor)))defer cancel()//获取锁失败,尝试异步去释放锁return m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {return m.release(ctx, pool, value)})}()if i == m.tries-1 && err != nil {return err}}return ErrFailed
}

time.Sleep(m.delayFunc(i))的失败重试逻辑是当客户端无法获取锁时会设置一个随机值来重试。这个随机值应当和申请锁时间错开,减少脑裂的可能性。此外,还调用了actOnPoolsAsync来实现非阻塞方式同时向多个Redis实例发送set请求。我们来看下actOnPoolsAsync是如何定义的。

func (m *Mutex) actOnPoolsAsync(actFn func(redis.Pool) (bool, error)) (int, error) {type result struct {Node   intStatus boolErr    error}ch := make(chan result)for node, pool := range m.pools {go func(node int, pool redis.Pool) {r := result{Node: node}r.Status, r.Err = actFn(pool)ch <- r}(node, pool)}n := 0var taken []intvar err errorfor range m.pools {r := <-chif r.Status {n++} else if r.Err != nil {err = multierror.Append(err, &RedisError{Node: r.Node, Err: r.Err})} else {taken = append(taken, r.Node)err = multierror.Append(err, &ErrNodeTaken{Node: r.Node})}}if len(taken) >= m.quorum {return n, &ErrTaken{Nodes: taken}}return n, err
}

acquire加锁操作

func (m *Mutex) acquire(ctx context.Context, pool redis.Pool, value string) (bool, error) {conn, err := pool.Get(ctx)if err != nil {return false, err}defer conn.Close()reply, err := conn.SetNX(m.name, value, m.expiry)if err != nil {return false, err}return reply, nil
}

release解锁操作

func (m *Mutex) release(ctx context.Context, pool redis.Pool, value string) (bool, error) {conn, err := pool.Get(ctx)if err != nil {return false, err}defer conn.Close()//调用Eval,以脚本方式释放锁status, err := conn.Eval(deleteScript, m.name, value)if err != nil {return false, err}return status != int64(0), nil
}

redsync包的使用

该包的使用很简单,具体步骤如下:

  • 首先,创建一个Redis的客户端连接;
  • 将该客户端连接加入到Redis的Pool中;
  • redsync基于该Redis Pool进行实例化;
  • 通过redsync实例的NewMutex就可以基于一个具体的key新建一个分布式锁,
    该包进行实例化时有基于Redis的单机模式和集群模式两种使用方式,在使用上主要有两种区别:
  • Redis的客户端是以集群模式还是单机模式创建;
  • 在导入redsync包时,集群模式需要导入goredis/v8的版本
    具体例子如下:
func main() {//创建redis的客户端连接cli := goredislib.NewClient(&goredislib.Options{Addr: "localhost:6379",})pool := goredis.NewPool(cli)rs := redsync.New(pool)mutexname := "test-global-mutex"mutex := rs.NewMutex(mutexname)if err := mutex.Lock(); err != nil {panic(err)}if ok, err := mutex.Unlock(); !ok || err == nil {panic("unlock failed")}}
http://www.15wanjia.com/news/34718.html

相关文章:

  • 我想注册一个做门窗的网站应该怎样做保定seo排名外包
  • 宝安区网站建设免费软文发布平台
  • 网页特效经典300例保定seo推广公司
  • h5设计制作seo是什么姓
  • 三乡有做网站的师傅吗深圳网站推广公司
  • 网站前台设计厦门百度公司
  • 男的怎么做直播网站全国十大婚恋网站排名
  • Wordpress网站调用代码免费建站平台
  • 如何做网站推广赚钱如何做免费网站推广
  • 网站开发技术参考文献seo优化服务
  • 阿里巴巴国际站怎么做网站模版网站提交收录入口链接
  • 北京智能网站建设哪里好十大品牌营销策划公司
  • 新乡彩票网站建设新手电商运营从哪开始学
  • 阿拉尔建设局网站爱网站关键词挖掘
  • 淘宝客做网站链接竞价推广托管服务
  • 做游戏装备网站可以吗企业站seo价格
  • 第一次做怎么放进去视频网站全网推广方案
  • 什么浏览器好用可以看任何网站新型网络营销方式
  • 外贸购物网站制作站内seo内容优化包括
  • 深圳市建筑工务署关键词优化报价推荐
  • 企业网站的重要性百度软件市场
  • 网站开发培训合肥如何建立一个网站
  • 网站使用网络图片做素材 侵权东莞谷歌推广
  • 网站营销信息广州seo黑帽培训
  • n加1网站建设开发新客户的十大渠道
  • 解析网站接口怎么做百度在线搜索
  • 在线黑科技网站百度推广搜索排名
  • 苏州 网站制作公司网图识别在线百度
  • 石家庄网站建设企业磁力狗在线引擎
  • 官方网站找oem做洗发水厂家宁波seo外包推广平台