python实现rpc的几种方式(SimpleXMLRPCServer 自带的、第三方ZeroRPC)、连接linux远程开发分布式锁、分布式id

[1 python实现rpc的几种方式](#1 python实现rpc的几种方式)
[1.1 SimpleXMLRPCServer 自带的](#1.1 SimpleXMLRPCServer 自带的)
[1.2 第三方ZeroRPC](#1.2 第三方ZeroRPC)

[2 连接linux远程开发](#2 连接linux远程开发)
[3 分布式锁](#3 分布式锁)
[4 分布式id](#4 分布式id)

1 python实现rpc的几种方式

python 复制代码
# 远程过程调用
	-1 借助于rabbitmq,可以跨语言
  -2 SimpleXMLRPCServer 自带的
  -3 ZeroRPC
  -4 GRPC:跨语言的  https://zhuanlan.zhihu.com/p/425725192

1.1 SimpleXMLRPCServer 自带的

python 复制代码
### 服务端
from xmlrpc.server import SimpleXMLRPCServer

# 通信使用xml格式
class RPCServer(object):
    def add(self,a,b):


        return a+b

# SimpleXMLRPCServer
server = SimpleXMLRPCServer(('localhost', 4242), allow_none=True)
server.register_introspection_functions()
server.register_instance(RPCServer())
server.serve_forever()


#### 客户端
import time
from xmlrpc.client import ServerProxy


# rpc 调用和http什么关系
'''
1 rpc 不是一种协议,它是一个概念:远程过程调用的概念,中间通过网络,底层可以基于tcp,也可以基于http,基于tcp自定制协议
2 有的rpc框架用了http协议
2 有的rpc框架直接使用tcp

'''
# SimpleXMLRPCServer  底层使用了http协议,速度稍微慢一些
def xmlrpc_client():
    print('xmlrpc client')
    c = ServerProxy('http://localhost:4242')
    res=c.add(3,4)
    print('通过rpc执行结果是:',res)

if __name__ == '__main__':
    xmlrpc_client()
    

 # 速度慢: 1 基于http  2 交互使用的xml格式

1.2 第三方ZeroRPC

python 复制代码
### 服务端
import zerorpc

class RPCServer(object):
    def add(self,a,b):
        print('a+b',a+b)
        return a+b
# zerorpc
s = zerorpc.Server(RPCServer())
s.bind('tcp://0.0.0.0:4243')
s.run()



#### 客户端
import zerorpc
import time


# zerorpc
def zerorpc_client():
    print('zerorpc client')
    c = zerorpc.Client()
    c.connect('tcp://127.0.0.1:4243')

    print(c.add(88, 77))


if __name__ == '__main__':
    zerorpc_client()
    

2 连接linux远程开发

python 复制代码
# 咱么开发的环境
	-1 win 开发,linux上线
  -2 linux开发,Linux上线
  	-乌班图-》台式机--》装乌班图--》乌班图开发
  -3 mac系统,linux上线
  	-mac环境跟linxu很像
 

# 只有win机器,没有linux,项目要在linux下开发---》远程连接到linux中开发---》解释器用了远程linux的



# 使用pycharm远程连接linxu开发
	-本地代码传到linux
  -使用linux的解释器运行代码---》配置远端解释器
  -以后 在本地右键运行,实际上等同于,连到linux机器,执行


  
# win---》远端docker容器中开发

3 分布式锁

python 复制代码
# 分布式系统中加锁---》悲观锁
	-mysql  行锁   性能不高
  -性能更高的分布式锁
  
# python 线程锁


# 分布式锁具备条件
1、在分布式系统环境下,一个方法在同一时间只能被一个机器的一个线程执行;
2、高可用的获取锁与释放锁;
3、高性能的获取锁与释放锁;
4、具备可重入特性;
5、具备锁失效机制,防止死锁;
6、具备非阻塞锁特性,即没有获取到锁将直接返回获取锁失败
	
  
# 三种方式实现
基于数据库实现分布式锁---》行锁
基于缓存(Redis等)实现分布式锁;----redis官方提供
基于Zookeeper实现分布式锁:分布式协调服务
python 复制代码
# pip3 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)


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

3.1 自己基于redis实现分布式锁

python 复制代码
#  redis 分布式锁底层如何实现的
	SETNX:当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做
  expire:超过这个时间锁会自动释放,避免死锁
  delete:Redis实现分布式锁的时候删除锁
  
  
  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()

4 分布式id

python 复制代码
# 在复杂分布式系统中,往往需要对大量的数据和消息进行唯一标识

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

-数据自增:性能第

-Redis生成ID
	时间戳+incr
 
-snowflake(雪花算法)方案:pysnowflake
	雪花算法的使用场景就很明确了,用于确保全局唯一的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算法
相关推荐
新之助小锅9 小时前
java版连接汇川PLC,发送数据,读取数据,保持重新链接,适用安卓
android·java·python
海琴烟Sunshine9 小时前
leetcode 383. 赎金信 python
python·算法·leetcode
大聪明-PLUS13 小时前
如何使用 Docker 打包一个简单的应用程序:简易指南
linux·嵌入式·arm·smarc
serve the people14 小时前
Prompts for Chat Models in LangChain
java·linux·langchain
李昊哲小课14 小时前
Ubuntu 24.04 MariaDB 完整安装与配置文档
linux·ubuntu·mariadb
惊讶的猫15 小时前
LSTM论文解读
开发语言·python
测试老哥16 小时前
软件测试之单元测试知识总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
buvsvdp50059ac16 小时前
如何在VSCode中设置Python解释器?
ide·vscode·python
人间打气筒(Ada)16 小时前
zerotier内网穿透部署(rockylinux部署本地服务器)超详细~~~
linux·内网穿透·内网·公网·zerotier·穿透
njxiejing16 小时前
Python进度条工具tqdm的安装与使用
开发语言·python