分布式锁分布式id
# 锁的作用:保证多线程并发情况下,数据的安全
-互斥锁
-递归锁
只能保证同一个进程下的线程
# django项目---》部署在多台机器上---》下单场景---》悲观锁--》同一时刻,必须获得锁才能进入下单流程,释放锁--》别人才能进入下单流程
-用mysql的表锁---》行锁
-分布式锁的一种方案
# 在分布式系统重,保证并发情况下的数据安全
# 分布式锁的实现方案
-mysql行锁表锁
-zookeeper(不聊)
-redis实现
-redis官方
-实现起来比较简单--》公司自己写
自己使用redis实现(redis实现分布式锁的原理)
# 连接redis
# 保证性能
# 保证不出死锁
import redis
from threading import Thread
import time
import uuid
redis_client = redis.Redis(host="localhost",
port=6379,
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(i):
identifier = acquire_lock('resource')
print("第%s个线程执行秒杀"%i)
release_lock('resource', identifier)
for i in range(50):
t = Thread(target=seckill,args=[i,])
t.start()
官方
#redlock 实现
pip install redlock-py
dlm = Redlock([{"host": "localhost", "port": 6379, "db": 0}, ])
要获得锁的地方
my_lock = dlm.lock("my_resource_name",1000)
要释放锁的地方
dlm.unlock(my_lock)
----------------------------------------
from redlock import Redlock
lock=Redlock([{"host": "localhost", "port": 6379, "db": 0}, ])
def task():
my_lock=lock.lock("my_resource_name",1000)
# 你的代码
# 下单---》操作好多数据
# 释放锁
lock.unlock(my_lock)
分布式id
# 下单场景订单号 任务id号
# 在不同机器上,生成永不重复的 id号-->效率尽量高,尽量有规律递增
# 可以的方案
1 uuid 规律递增,不会重复
2 mysql 自增 --》容易被猜到,存在漏洞,效率不高
3 redis 自增 ---》时间戳+机器id号+redis自增数字
4 雪花算法
5 美团 leaf算法
go 协程
# 进程
# 线程
------不能开启进程和线程----
---实现并发,go中有并发方案--》goroutine--》go协程
# 协程: 协程+线程池解决方案--》内部实现
gin框架
# 配置代理
# 下载
go get -u github.com/gin-gonic/gin
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func ping(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
}
func index(c *gin.Context) {
c.HTML(http.StatusOK, "index.html", gin.H{
"title": "lqz",
})
}
func demo(c *gin.Context) {
var name = "彭于晏"
c.String(http.StatusOK, "Hello %s", name)
}
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/ping", ping)
r.GET("/index", index)
r.GET("/demo", demo)
r.Run("0.0.0.0:8000") // 监听并在 0.0.0.0:8000 上启动服务
}