分布式(一)分布式缓存、分布式锁

文章目录[x]
  1. 1:分布式
  2. 1.1:分布式缓存
  3. 1.2:分布式锁

分布式

分布式缓存

一致性哈希算法

布隆算法

布隆算法是为了解决缓存穿透问题而设置的布隆过滤器原理

1.将全部数据库当中的ID值进行hash函数计算,结果范围为[0,m]之间

2.将结果存入一个长度为m的二进制当中

存入方案

  • 假设ID=1的一个数据通过hash计算的结果为2

  • 那么长度为m的二进制数据为0010......

  • 假设再存入一个数据ID=10,通过hsah计算结果为4

  • 那么长度为m的二进制数据为0010100......

  • 如果计算结果重复,那么当前位置的值不变

原则:

  • 如果客户端发送过来数据ID计算结果的二进制位为1,表示存在,但是实际结果不一定存在

  • 如果客户端发来数据ID计算结果在二进制上为0,表示不存在,那么实际结果一定不存在

降低错误率:

1.可以增大二进制长度,降低hash碰撞概率

2.增加多个hash函数,多个函数计算结果分别标志1,由多个标志的1决定一个ID是否存在

代码实现:

package main

import "fmt"

var bitmap []byte

func main() {
  s := "test"
  Blood(8, s, 8)
  fmt.Println(bitmap)
}

func Blood(n int, key string, prime int) {
  bitmap = make([]byte, n)
  bitmap[hash(key, prime)] = 1
}
func hash(key string, prime int) int {
  var ha int = len(key)
  for i := 0; i < len(key); i++ {
    ha = ha + int(key[i])
  }
  return ha % prime
}

分布式锁

分布式锁实现三种方式:

  • 基于数据库实现分布式锁;

  • 基于缓存(Redis等)实现分布式锁;(实现方法)

  • 基于Zookeeper实现分布式锁;

分布式锁应该具备哪些条件

1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行; 2、高可用的获取锁 与释放锁; 3、高性能的获取锁与释放锁; 4、具备可重入特性; 5、具备锁失效机制,防止死锁; 6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败。

为了防止单机情况下,某一台redis宕机,采用Redlock分布式锁

Redlock实现

在Redis的分布式环境中,我们假设有N个Redis master。这些节点完全互相独立,不存在主从复制或者其他集群协调机制。我们确保将在N个实例上使用与在Redis单实例下相同方法获取和释放锁。现在我们假设有5个Redis master节点,同时我们需要在5台服务器上面运行这些Redis实例,这样保证他们不会同时都宕掉。

为了取到锁,客户端应该执行以下操作:

  • 获取当前Unix时间,以毫秒为单位。

  • 依次尝试从5个实例,使用相同的key和具有唯一性的value(例如UUID)获取锁。当向Redis请求获取锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务器端没有在规定时间内响应,客户端应该尽快尝试去另外一个Redis实例请求获取锁。

  • 客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间。当且仅当从大多数(N/2+1,这里是3个节点)的Redis节点都取到锁,并且使用的时间小于锁失效时间时,锁才算获取成功

  • 如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的结果)。

  • 如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时间不能被重新获取锁)。

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像