首页 > 其他分享 >分布式锁、分布式ID

分布式锁、分布式ID

时间:2023-08-25 20:55:24浏览次数:31  
标签:lock redis 获取 time ID 分布式

分布式锁、分布式ID

https://www.cnblogs.com/liuqingzheng/p/11080501.html

# 分布式系统中加锁-->悲观锁
	-mysql 行锁	性能不高
    -需要性能更高的分布式锁
# python 线程锁

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

# 三种方式实现
基于数据库实现分布式锁---mysql的行锁
基于缓存redis等实现分布式锁----redis官方提供
基于zookeeper实现分布式锁:分布式协调服务


#redis实现分布式锁----redlock(其实我们可以自己去实现,不需要使用官方提供的方法)



使用redis实现分布式锁

# pip install redlock-py
from redlock import Redlock
import time
dlm = Redlock([{"host": "localhost", "port": 6379, "db": 0}, ])

# 获得锁
my_lock = dlm.lock("my_resource_name",1000)

# 业务逻辑代码
print('sdfasdf')
time.sleep(20)

# 释放锁
dlm.unlock(my_lock)


# 这个代码可以放在任意的节点上,使用的是分布式锁,某个节点获取到锁后,别的节点获取不到,操作数据,释放锁后,别的节点的线程才能操作数据

自己基于redis实现分布式锁

# 选用redis实现分布式锁原因:
1.redis性能高
2.redis命令对分布式锁的比较支持,实现方便

# 使用的主要命令:在使用Redis实现分布式锁的时候,主要就会使用到这三个命令。
SETNX:
	-SETNX key val:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。
expire
	-expire key timeout:为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。
delete
	-delete key:删除key
    
#实现思想:
1.获取锁的时候,使用setnx加锁,并使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁,锁的value值为一个随机生成的UUID,通过此在释放锁的时候进行判断。
2.获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。
3.释放锁的时候,通过UUID判断是不是该锁,若是该锁,则执行delete进行锁释放。

################ 代码
import redis
import uuid
import time

from threading import Thread,get_ident

# 连接redis
redis_client = redis.Redis(host="localhost",
                           port=6379,
                           # password=password,
                           db=10)


# 获取一个锁
# lock_name:锁定名称
# acquire_time: 客户端等待获取锁的时间
# time_out: 锁的超时时间
def acquire_lock(lock_name, acquire_time=10, time_out=10):
    """获取一个分布式锁"""
    identifier = str(uuid.uuid4())
    end = time.time() + acquire_time
    lock = "string:lock:" + lock_name
    while time.time() < end:
        if redis_client.setnx(lock, identifier):
            # 给锁设置超时时间, 防止进程崩溃导致其他进程无法获取锁
            redis_client.expire(lock, time_out)
            return identifier
        elif not redis_client.ttl(lock):
            redis_client.expire(lock, time_out)
        time.sleep(0.001)
    return False


# 释放一个锁
def release_lock(lock_name, identifier):
    """通用的锁释放函数"""
    lock = "string:lock:" + lock_name
    pip = redis_client.pipeline(True)
    while True:
        try:
            pip.watch(lock)
            lock_value = redis_client.get(lock)
            if not lock_value:
                return True

            if lock_value.decode() == identifier:
                pip.multi()
                pip.delete(lock)
                pip.execute()
                return True
            pip.unwatch()
            break
        except redis.excetions.WacthcError:
            pass
    return False


def seckill():
    identifier = acquire_lock('resource')
    print(get_ident(), "获得了锁")
    release_lock('resource', identifier)


if __name__ == '__main__':
    for i in range(50):
        t = Thread(target=seckill)
        t.start()

分布式ID

# 在复杂的分布式系统中,要对系统中的大量数据和消息使用ID唯一标识。比如:用户一个ID只对应一个用户,商品ID仅对应件商品,订单号仅对应一个订单。

# 分布式ID的特点:
1.全局唯一:不能出现重复的ID号,既然是唯一标识,这是最基本的要求。  # uuid
2.趋势递增:在MySQL InnoDB引擎中使用的是聚集索引,由于多数RDBMS(关系型数据库)使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键保证写入性能。
3.单调递增:保证下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求。
4.信息安全:如果ID是连续的,恶意用户的扒取工作就非常容易做了,直接按照顺序下载指定URL即可;如果是订单号就更危险了,竞对可以直接知道我们一天的单量。所以在一些应用场景下,会需要ID无规则、不规则。

# 生成分布式锁的方案
	1.uuid:
    2.数据库自增:效率低
    3.redis生成ID:时间错+incr
####重点#### 雪花算法
	-使用第三方模块snowflake
    雪花算法的使用场景就很明确了,用于确保全局唯一的id。还有一个从名字无法看出的特点就是,还能保证id的自增属性。

    Snowflake 以 64 bit 来存储组成 ID 的4 个部分:

    1、最高位占1 bit,值固定为 0,以保证生成的 ID 为正数;

    2、中位占 41 bit,值为毫秒级时间戳;

    3、中下位占 10 bit,值为工作机器的 ID,值的上限为 1024;

    4、末位占 12 bit,值为当前毫秒内生成的不同 ID,值的上限为 4096;
    -美团leaf算法

标签:lock,redis,获取,time,ID,分布式
From: https://www.cnblogs.com/yedayangboke/p/17657900.html

相关文章

  • 跨平台通信:数字化工厂中基于OPC UA的分布式IO模块介绍
    背景近年来,为了提升在全球范围内的竞争力,制造企业希望自己工厂的机器之间协同性更强,自动化设备采集到的数据能够发挥更大的价值,越来越多的传统型工业制造企业开始加入数字化工厂建设的行列,实现智能制造。数字化改造推动工厂越来越“聪明”1数字化车间的概述简单来讲,相较于传统工厂......
  • redis 实现分布式锁原理
    通过原子操作实现redis锁redis内部是通过key/value的形式存储的,核心原理是设置一个唯一的key,如果这个key存在,说明有服务在使用具体实现方式:首先判断redis中是否存在某个key,并且为某个值如果这个key不存在,说明当前没有服务在使用,设置key如果这个key存在,说明当前有服......
  • 【MySQL 8.0】在线开启与关闭GTID复制
    在线开启GTID复制(root@node01)>setglobalenforce_gtid_consistency=warn;QueryOK,0rowsaffected(0.04sec)(root@node02)>setglobalenforce_gtid_consistency=warn;QueryOK,0rowsaffected(0.07sec)(root@node01)>setglobalenf......
  • bh006- Blazor hybrid / Maui 使用NFC快速教程
    1.建立工程bh006_NFC_tag源码https://github.com/densen2014/BlazorHybrid/tree/master/bh100days/bh006_NFC_tag?WT.mc_id=DT-MVP-50050782.添加nuget包<PackageReferenceInclude="BlazorHybrid.Maui.Permissions"Version="0.0.3"/><Packag......
  • 解放生产力orm并发更新下应该这么处理求求你别再用UpdateById了
    合集-easy-query(7) 1.献给转java的c#和java程序员的数据库orm框架05-222.javaer你还在手写分表分库?来看看这个框架怎么做的干货满满05-263.你没见过的分库分表原理解析和解决方案(一)06-074.你没见过的分库分表原理解析和解决方案(二)06-305.我真的不想再用mybatis和其......
  • 使用MediatR和FluentValidation实现CQRS应用程序的数据验证
    本文将重点介绍如何通过MediatR的管道功能将FluentValidation集成到项目中实现验证功能。什么是CQRS?CQRS(CommandQueryResponsibilitySegregation)也叫命令查询职责分离,是近年来非常流行的应用程序架构模式。CQRS背后的理念是在逻辑上将应用程序的流程分成两个独立的流程,即命......
  • 网络请求-Android篇(Okhttp和Retrofit)
    一.OkHttp的介绍和基本用法OkHttp是一个流行的开源Java和Android应用程序的HTTP客户端。它由SquareInc.开发,提供了一种简单高效的方式来进行应用程序中的HTTP请求。要在Java或Android项目中使用OkHttp,您需要将OkHttp依赖项添加到您的build.gradle文件中。然后,您可以创建一个......
  • 吃透这份阿里P7大佬整理的《Android Framework源码笔记》,还怕找不到工作?
    前言随着Android开发行业的快速发展,市场需求也在不断提升,导致低端Android开发市场就业大环境不好、行业趋势下滑,使得不少初中级的Android开发开始失业,找不到工作。对于大部分的开发者来说,找不到工作的一大部分原因,是因为AndroidFramework无法做到精通。想要成为真正的高级Androi......
  • fiddler抓包手机端HTTPS协议:安卓或鸿蒙端-小程序/APP
    问题描述:fiddler抓包安卓或者鸿蒙端的HTTPS协议时,fiddler日志报错:AuthenticationException调用SSPI失败;访问app时提示:Trustanchorforcertificationnotfound原因:    1)安卓端下载使用了fiddler自带的HTTPS证书,导致与手机版本不兼容    2)andriod7以后,用户......
  • ID最新版下载和安装步骤 InDesign设计 永久安装包
    AdobeIndesign中文免费版是由Adobe公司推出的专业型排版设计软件,软件功能非常强大,具有创建和发布书籍,数字杂志,电子书,海报,交互式PDF等所需的一切,可提供专业的布局和排版工具,且拥有丰富的排版、图形、图形、表格等素材,能够满足用户的各种需求。软件地址:看置顶贴InDesign最新版软件功......