当前位置:首页 > 黑客服务 > 正文内容

php分布式框架(PHP分布式框架有哪些官网)

访客3年前 (2021-09-27)黑客服务681

分布式锁的实现方式有三种:1。基于数据库实现分布式锁;2.实现基于缓存的分布式锁(Redis等)。);3.基于Zookeeper实现分布式锁。从性能角度(从高到低):“缓存模式Zookeeper模式=数据库模式”。

操作环境:windows系统,redis 6.0,thinkpad t480电脑。

分布式锁的三种实现方法;

1.基于数据库实现分布式锁;2.实现基于缓存的分布式锁(Redis等)。);3.基于Zookeeper实现分布式锁;

1、基于数据库实现分布式锁定

1.悲观锁

使用select … where …更新排他锁

注:其他附加功能与实现1基本相同。这里要注意“凡名=锁”。名称字段必须建立索引,否则表将被锁定。在某些情况下,例如,如果表不大,mysql优化器将不会采用这个索引,从而导致锁定表的问题。

2.乐观锁定

所谓的乐观锁和前者最大的区别是基于CAS,不互斥,不会造成锁等待,消耗资源。在操作过程中,认为不存在并发冲突,只有更新版本失败后才能注意到。我们利用这种认识来防止我们的抢购和尖峰信号的超卖。乐观锁定是通过增加增量版本号字段来实现的

第二,基于缓存(Redis等。)来实现分布式锁

1.使用命令介绍:(1)SETNXSETNX key val:当且仅当key不存在时,设置一个key为val的字符串并返回1;如果键存在,则什么也不做并返回0。(2)expireexpire key timeout:为key设置一个超时,单位为秒,之后锁会自动释放,避免死锁。(3)deletedelete键:delete键

使用Redis实现分布式锁时,主要使用这三个命令。

2.实现思路:(1)获取锁时,使用setnx锁定,使用expire命令为锁添加超时时间,之后锁会自动释放,锁的值是随机生成的UUID,可以用来判断何时释放锁。(2)获取锁时,设置一个获取超时时间,超过这个时间就放弃获取锁。(3)开锁时,由UUID判断是否是锁,如果是,执行delete开锁。

3.分布式锁的简单实现代码:

/** *分布式锁的简单实现代码*/ public class DistributedLock {

私有最终JedisPool jedisPool

公共分布式锁(JedisPool jedisPool) { this.jedisPool = jedisPool }

/** *锁定 * @param lockName锁的密钥 * @param acquireTimeout获取超时值 * @param超时锁定超时 * @返回锁id */ 公共字符串锁定超时(字符串锁定名称,长获取超时,长超时){ Jedis conn = null 字符串重标识符=空; 尝试{ //获取连接 conn = JedisPool . GetResource; //随机生成一个值 字符串标识符= UUID.randomUUID。toString; //锁名,即键值 string LockKey = lock:+LockName; //超时时间,锁定后,锁会自动解除。 int lockExpire =(int)(time out/);

//获取锁的超时时间。如果超过这个时间,放弃获取锁。 long end = system . current timemillis+acquire time out; while(system . CurrentMemillis& lt;end) { if (conn.setnx(lockKey,identifier)=){ conn.expire(lockKey,LockExpire); //返回值,用于确认锁的释放时间 retIdentifier =标识符; 返回重新标识符; } //return-表示key没有设置超时,而是为key设置了超时。 if(conn . TTL(LockKey)=-){ conn.expire(lockKey,LockExpire); }

尝试{ thread . sleep; } catch(中断异常e) { Thread.currentThread。interrupt; } } } catch (JedisException e) { e . printstacktrace; }最后{ if (conn!= null) { conn . close; } } 返回重新标识符; }

/** *松开锁 * @param lockName锁的密钥 * @param标识符释放锁的标识符 * @返回 */ 公共布尔释放锁(字符串锁名,字符串标识符){ Jedis conn = null string LockKey = lock:+LockName; boolean retFlag = false 尝试{ conn = JedisPool . GetResource; while (true) { //监控锁,准备开始交易 conn . watch(LockKey); //通过前面返回的值判断是否是锁。如果是,删除它并释放它 if(identifier . equals(conn . get(LockKey))){ transaction transaction = con . multi; transaction . del(LockKey); 列表&lt。object results = transaction . exec; if (results == null) { 继续; } retFlag = true } conn . unwatch; 打破; } } catch (JedisException e) { e . printstacktrace; }最后{ if (conn!= null) { conn . close; } } 返回retFlag } }4.测试刚刚实现的分布式锁

在该示例中,50个线程用于模拟杀死一个商品,而–运算符用于减少商品。是否锁定,从结果的有序性可以看出。

模拟尖峰服务,其中配置了jedis线程池,该线程池被传输到分布式锁,供其在初始化期间使用。

公共级服务{

私有静态JedisPool池= null

私有分布式锁=新分布式锁(池);

int n = 500

静态{ JedisPoolConfig = new JedisPoolConfig; //设置最大连接数 config . SetMaxTotaL(200); //设置最大空闲数 config . SetMaxidle(8); //设置最大等待时间 config . setmaxwaitmillis(1000 * 100); //当您请求jedis实例时,是否需要验证?如果为真,则所有jedis实例都可用 config . settestonborrow(true); pool = new JedisPool(config,127.0.0.1,6379,3000); }

public void seckill { //释放锁时返回锁的值以供判断 字符串标识符= lock.lockWithTimeout(资源,5000,1000); 系统。out.println(线程。currentthread。getname+得到了锁); system . out . println(-n); lock.releaseLock(资源,标识符); } }为spike服务模拟线程;

公共类ThreadA扩展Thread { 私人服务;

公共线程(服务){ this.service = service }

@覆盖 public void run { service . seckill; } }

公共类测试{ 公共静态void main(String[] args) { 服务服务=新服务; for(int I = 0;i &lt。50;i++) { ThreadA threadA = new ThreadA(服务); threada . start; } } }结果如下,结果有序:

如果您注释掉使用锁的部分:

public void seckill { //释放锁时返回锁的值以供判断 //String identifier = lock . lockhittime out(资源,5000,1000); 系统。out.println(线程。currentthread。getname+得到了锁); system . out . println(-n); //lock.releaseLock(resource,identifier); }从结果可以看出,其中一些是异步的:

第三,基于动物园管理员实现分布式锁

ZooKeeper是一个开源组件,为分布式应用程序提供一致的服务。其内部是分层的文件系统目录树结构,规定同一目录下只能有一个唯一的文件名。基于ZooKeeper实现分布式锁的步骤如下:

(1)创建目录mylock;(2)如果线程a想要获取锁,它在mylock目录中创建一个临时序列节点;(3)获取mylock目录下的所有子节点,然后获取比自己小的兄弟节点。如果不存在,则表示当前线程序号最小,获得锁;(4)线程B获取所有节点,判断不是最小节点,设置一个小于自身的节点;(5)线程A处理完毕后,删除自己的节点,线程B监控变化事件,判断是否是最小节点,如果是,获取锁。

在这里我们推荐一个Apache开源库馆长,是ZooKeeper的客户端。馆长提供的进程间互斥是分布式锁的实现。获取方法用于获取锁,释放方法用于释放锁。

实现源代码如下:

import lombok . extern . SLF 4j . SLF 4j; import org . Apache . comes . lang . Stringuils; import org.apache .策展人. org.apache.curator.framework.CuratorFramework import org.apache .策展人. framework . curatorframeworkFactory; import org.apache .策展人. retry . retry ntimes; import org . Apache . zoo keeper . create mode; import org . Apache . zoo keeper . data . Stat; import org . spring framework . beans . factory . annotation . value; import org . spring framework . context . annotation . Bean; import org . spring framework . stereotype . component;

/** *分布式锁Zookeeper实现 * */ @Slf4j @组件 公共类ZkLock实现分布式锁{ private String ZkADdress = ZK _ adress; 私有静态最终字符串根=包根; 私有CuratorFramework zkClient

私有最终字符串LOCK _ PREFX =/LOCK _;

@豆 public DistributionLock InitzkLock{ if (StringUtils.isBlank(root)) { 抛出新的RuntimeException(zoo keeper & # 39;根& # 39;can & # 39t为空); } zkClient = CuratorFrameworkFactory 。构建器 。连接字符串(zkAddress) 。retryPolicy(新RetryNTimes(2000,20000)) 。命名空间(根) 。build; zkclient . start; 归还这个; }

公共布尔tryLock(字符串锁名){ lockName = LOCK _ PREFIX+lockName; 布尔锁定=真; 尝试{ Stat stat = zkClient.checkExists。for path(LockName); if (stat == null) { log.info(tryLock:{},lockName); stat = zkClient.checkExists。for path(LockName); if (stat == null) { 独立线程 。创建 。creatingParentsIfNeeded 。withMode(创建模式。短命) 。forPath(lockName,1 . GetBytes); } else { log.warn(双击stat.version:{},stat . GetVersion); locked = false } } else { log.warn(check stat.version:{},stat . GetVersion); locked = false } }捕获(例外e) { locked = false } 返回锁定; }

公共布尔tryLock(字符串键,长超时){ 返回false }

公共无效释放(字符串锁名){ lockName = LOCK _ PREFIX+lockName; 尝试{ 独立线程 。删除 。保证 。deletingChildrenIfNeeded 。for path(LockName); log.info(发布:{},lockName); }捕获(例外e) { log.error (delete,e); } }

public void setZkAddress(String zkAddress){ this.zkAddress = zkAddress } }优点:具有高可用性、重入性和阻塞锁的特点,可以解决无效死锁问题。

缺点:由于节点需要频繁创建和删除,性能不如Redis。

第四,对比

数据库分布式锁实现的缺点;

1.db操作性能差,有锁表的风险。2.非阻塞操作失败后,需要轮询,占用cpu资源;3.长时间不提交或长时间轮询可能会占用更多的连接资源

Redis分布式锁实现的缺点;

1.锁删除失败的到期时间难以控制。2.非阻塞,操作失败后,需要轮询,占用cpu资源;

ZK分布式锁实现的缺点:它的性能不如redis实现,主要是因为所有的写操作(获取锁和释放锁)都需要在Leader上执行,然后同步到follower。

总之,ZooKeeper的性能和可靠性更好。

从易于理解的角度来看(从低到高),数据库缓存Zookeeper

从实现的复杂度来看(从低到高),Zookeeper = cache数据库

缓存管理员=从性能角度看的数据库(从高到低)

动物园管理员从可靠性角度(从高到低)缓存数据库

扫描二维码推送至手机访问。

版权声明:本文由黑客接单发布,如需转载请注明出处。

本文链接:https://therlest.com/71361.html

分享给朋友:

“php分布式框架(PHP分布式框架有哪些官网)” 的相关文章

吃鸡鸭的屁股会有病吗?我非常爱吃鸡鸭的屁股,但经常吃会有病吗?另

吃鸡鸭的屁股会有病吗?我非常爱吃鸡鸭的屁股,但经常吃会有病吗?另 鸡鸭的肛门附近组织,布满大大小小的腺体,各类秽物与毒素都在这些腺体囤积;鸡鸭的肛门也有非常高密度的大肠杆菌,所以鸡鸭的屁股不是少吃的问题,而是不能吃.吃得少可能没觉出怎样,多了问题就显出来了.而且鸡鸭屁股的大肠杆菌会随着蛋生出来的时...

铁盖子可以放入高压锅蒸吗?装酱料的铁盖子,外面的涂层有些剥落,好

铁盖子可以放入高压锅蒸吗?装酱料的铁盖子,外面的涂层有些剥落,好 铁盖子可以放入高压锅蒸吗? 装酱料的铁盖子,外面的涂层有些剥落,好象也没锈,可以拿它盖严瓶子入高压锅蒸吗? 绝对不行!既危险又不卫生。盖住的瓶子在高压锅中加热,很容易形成压力差而爆炸;铁在高压锅中的水蒸汽作用下极易变成四氧化三...

山东价格协会(山东物流网)

东北等北方地区,可以去那里看一下。自己挑合适的,发往,我刚开一家物流公司,56888的软件配货,不知道物流价格是怎么算的. 衣服,哦,4008111111着是顺风快递的电话。而且显示正在备货。免费的东西总是会有不足的地方,在烟台住,济宁到济南一个)普通件,山东省服务标准化技术委员会物流分技术委员会于...

图说兰州清真寺之兰州水上清真寺

圖說蘭州清真寺之蘭州水上清真寺讀書啊,我信赖但有朗朗書聲出破廬,遲早有一日有萬鯉躍龍門之奇象。 圖說蘭州清真寺是本人在2011年開始走訪,並在中穆網蘭州社區陸續發佈的走訪蘭州清真寺之系列。不知不覺六七年過去瞭,有的清真寺有瞭很大的變化,以是在此基礎上本人再次整理發佈,希望大傢足不出戶瞭解蘭州的...

查开放房软件app(免费查开放房的软件)

  你仅仅坚持不懈和女孩儿入睡。假如你发觉仅有大家2个,你应该坚持不懈再开一个。可是你的迟疑说明你還是想和他发生关系。留意防护措施。   线上查询对外开放门户网应用软件,并查询对外开放门户网应用软件系统软件下载   在哪儿申请办理公共性租用住宅?   我与男友在网络上了解的。我北京市找他。他为我开过...

公安系统里的开房记录会保存多久

王浩信谢芷蕙绯闻是真的吗 王浩信妻子陈自瑶为何不离婚 王浩信和谢芷蕙的绯闻是真的吗?王浩信现今的妻子是陈自瑶,2人在2011年的时候结婚了,而王浩信和谢芷蕙之间的事情,就是2人准备婚礼的时候发生的,并且还有网友晒出了谢芷蕙和王浩信2人有关系的证据,甚至还有消息称,谢芷蕙当时已经怀了王浩信的孩子等。...

评论列表

离鸢婼粥
2年前 (2022-08-08)

lockName;尝试{独立线程。删除。保证。deletingChildrenIfNeeded。for path(LockName);log.info(发布:{},lockName);}捕获(例外e)

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。