锁组件

编辑本页

锁组件

锁组件创建和管理,一种提供对共享资源的独占访问的机制。

如果您正在使用Symfony框架,请阅读ob娱乐下载ob娱乐下载Symfony框架锁文档欧宝官网下载app

安装

1
作曲家需要symfony/lockob娱乐下载

请注意

如果在Symfony应用程序外部安装此组件,则必须要求ob娱乐下载供应商/ autoload.php文件,以启用Composer提供的类自动加载机制。读这篇文章欲知详情。

使用

锁用于保证对某些共享资源的独占访问。例如,ob娱乐下载在Symfony应用程序中,您可以使用锁来确保一个命令不会在同一时间(在相同或不同的服务器上)执行多次。

类创建锁LockFactory类,这又需要另一个类来管理锁的存储:

1 2 3 4 5
使用ob娱乐下载组件LockFactory使用ob娱乐下载组件商店SemaphoreStore商店SemaphoreStore ();工厂LockFactory (商店);

方法创建锁createLock ()方法。它的第一个参数是表示锁定资源的任意字符串。然后,调用获得()方法将尝试获取锁:

1 2 3 4 5 6 7 8 9
/ /……工厂->createLock (“pdf-creation”);如果->获得()){// pdf-creation资源被锁定。//您可以在这里安全地计算和生成发票。->release ();}

如果无法获取锁,则该方法返回.的获得()方法可以安全地重复调用,即使已经获得了锁。

请注意

与其他实现不同的是,即使是为同一资源创建的锁实例,Lock Component也能区分它们。这意味着对于给定的作用域和资源,可以多次获取一个锁实例。如果一个锁必须被多个服务使用,那么它们应该共享同一个锁实例返回的LockFactory: createLock方法。

提示

如果您没有显式地释放锁,它将在实例销毁时自动释放。在某些情况下,跨多个请求锁定一个资源可能很有用。属性的第三个参数,可禁用自动释放行为createLock ()方法

序列化锁

关键控件的状态并且可以序列化。这允许用户通过获取锁在一个进程中开始一个长任务,并使用相同的锁在另一个进程中继续该任务:

12 3 4 5 6 7 8 9 10 11 12 13
使用ob娱乐下载组件关键使用ob娱乐下载组件关键键(“文章”。文章->getId ());锁(关键->商店,300/ / ttl/ /生成);->获得(真正的);->公共汽车->调度(RefreshTaxonomy (文章关键));

请注意

别忘了设置生成参数构造函数,以避免在调用析构函数时释放锁。

并不是所有的存储都与序列化和跨进程锁兼容:例如,内核将自动释放由线程获取的信号量SemaphoreStore商店。如果使用不兼容的存储(请参见锁店对于受支持的存储),当应用程序试图序列化该键时将抛出异常。

阻塞锁

缺省情况下,当无法获取锁时,将使用收购方法返回立即。要等待(无限期地)直到可以创建锁,请通过真正的作为论证获得()方法。这叫做阻塞锁因为在获得锁之前,应用程序的执行会停止:

1 2 3 4 5 6 7 8
使用ob娱乐下载组件LockFactory使用ob娱乐下载组件商店RedisStore商店RedisStore (\ Predis \客户端(“tcp: / / localhost: 6379”));工厂LockFactory (商店);工厂->createLock (“pdf-creation”);->获得(真正的);

当存储区不支持阻塞锁时,可以实现BlockingStoreInterface界面(见锁店对于受支持的商店)类将以非阻塞的方式重试获取锁,直到获得锁为止。

5.2

在Symfony 5.2中引入了重试获取非阻塞锁的默认逻辑。ob娱乐下载在5.2之前,您需要封装一个不支持阻塞锁的存储RetryTillSaveStore

到期的锁

远程创建的锁很难管理,因为没有远程的方法商店以了解储物柜进程是否仍然存在。由于bug,致命错误或分割错误,不能保证release ()方法,这将导致资源被无限锁定。

在这种情况下,最好的解决办法就是创造到期的锁,在经过一段时间后自动释放(对于活着的时间).属性的第二个参数,单位为秒createLock ()方法。方法也可以提前释放这些锁release ()方法。

处理过期锁时最棘手的部分是选择正确的TTL。如果它太短,其他进程可能会在完成任务之前获得锁;如果时间过长,进程在调用release ()方法,资源将保持锁定直到超时:

12 3 4 5 6 7 8 9 10 11 12
/ /……//创建一个持续30秒的过期锁(默认为300.0)工厂->createLock (“pdf-creation”ttl:30.);如果(!->获得()){返回;}试一试//在30秒内完成一个任务最后->release ();}

提示

为了避免锁处于锁定状态,建议将作业封装在try/catch/finally块中,以便始终尝试释放即将到期的锁。

对于长时间运行的任务,最好从一个不太长的TTL开始,然后使用refresh ()方法将TTL重置为原始值:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/ /……工厂->createLock (“pdf-creation”ttl:30.);如果(!->获得()){返回;}试一试(!完成了){//完成工作的一小部分。//更新锁30秒。->refresh ();}}最后->release ();}

提示

类的参数传递自定义TTL,这是长时间运行任务的另一个有用技术refresh ()方法修改默认锁TTL:

1 2 3 4 5 6 7
工厂->createLock (“pdf-creation”ttl:30.);/ /……//刷新锁30秒->refresh ();/ /……//刷新锁600秒(下一次refresh()调用将再次为30秒)->刷新(600);

该组件还提供了两个与过期锁相关的有用方法:getRemainingLifetime ()(返回或者一个浮动作为秒)和isExpired ()(返回一个布尔值)。

自动释放锁

当锁的Lock对象被销毁时,锁会自动释放。这是在进程间共享锁时非常重要的实现细节。在下面的例子中,pcntl_fork ()创建了两个进程,当一个进程结束时,锁就会自动释放:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/ /……工厂->createLock (“pdf-creation”);如果(!->获得()){返回;}pid= pcntl_fork ();如果-1===pid){//无法分叉退出1);}elseifpid){//父进程睡眠(30.);}其他的//子进程回声“现在解锁了。”退出0);}/ /……

若要禁用此行为,请设置生成的观点LockFactory: createLock ().这将使锁获得3600秒或直到锁::释放()被称为:

1 2 3 4 5
工厂->createLock (“pdf-creation”3600/ / ttl/ /生成);

共享锁

5.2

共享锁(以及相关联的acquireRead ()方法和SharedLockStoreInterface)是在Symfony 5.2中引入的。ob娱乐下载

共享的或readers-writer锁是一个同步原语,允许对只读操作进行并发访问,而写操作需要独占访问。这意味着多个线程可以并行地读取数据,但写入或修改数据需要一个排他锁。例如,它们用于不能自动更新且在更新完成之前无效的数据结构。

使用acquireRead ()方法获取只读锁,并且获得()方法获取写锁:

1 2 3 4
工厂->createLock (“用户- - - - - -”用户->id);如果(!->acquireRead ()) {返回;}

类似于获得()方法,通过真正的作为论证acquireRead ()使用实例以阻塞方式获取锁。

1 2
工厂->createLock (“用户- - - - - -”用户->id);->acquireRead (真正的);

请注意

优先政策Symob娱乐下载fony的共享锁取决于底层存储(例如,Redis存储优先考虑读取器和写入器)。

方法获取只读锁时acquireRead ()方法,是可能的促进方法,并将其更改为写锁获得()方法:

1 2 3 4 5 6 7 8 9
工厂->createLock (“用户- - - - - -”用户标识);->acquireRead (真正的);如果(!->shouldUpdate (用户标识)) {返回;}->获得(真正的);//将锁提升为写锁->更新(用户标识);

同样的,也有可能降级方法将其更改为只读锁acquireRead ()方法。

方法时,所提供的存储区没有实现SharedLockStoreInterface界面(见锁店对于受支持的商店)类将回退到写锁获得()方法。

锁的主人

对象第一次获得的锁为[1]_获取它的实例。如果需要检查电流是否实例仍然是锁的所有者,您可以使用isAcquired ()方法:

1 2 3
如果->isAcquired ()) {//我们仍然拥有这把锁

因为一些锁存储有到期的锁,实例可能会失去它自动获得的锁:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
//如果我们自己无法获取,就意味着其他进程已经在处理它了如果(!->获得()){返回;}->beginTransaction ();//执行一个很长的进程,可能超过锁的生存时间如果->isAcquired ()) {//一切正常,在此期间没有其他实例获得锁,我们是安全的->commit ();}其他的/ /懒汉!我们的锁显然已经超过了TTL,另一个进程已经开始//在此期间,所以它对我们来说是不安全的。->rollback ();异常“过程失败”);}

谨慎

一个常见的缺陷可能是使用isAcquired ()方法检查某个锁是否已被任何进程获取。正如你在这个例子中看到的,你必须使用获得()对于这个。的isAcquired ()方法用于检查锁是否已由当前进程只有。

..[1]从技术上讲,锁的真正所有者是那些共享相同实例的人关键
.但从用户的角度来看,关键是内部的,您可能只与实例,这样更容易想到实例作为锁的所有者。

可用的商店

在其中创建和管理锁商店,它们是实现的类PersistingStoreInterface可选地,BlockingStoreInterface

该组件包括以下内置存储类型:

商店 范围 阻塞 即将到期的 分享
FlockStore 当地的 是的 没有 是的
MemcachedStore 远程 没有 是的 没有
MongoDbStore 远程 没有 是的 没有
PdoStore 远程 没有 是的 没有
DoctrineDbalStore 远程 没有 是的 没有
PostgreSqlStore 远程 是的 没有 是的
DoctrineDbalPostgreSqlStore 远程 是的 没有 是的
RedisStore 远程 没有 是的 是的
SemaphoreStore 当地的 是的 没有 没有
ZookeeperStore 远程 没有 没有 没有

提示

一个特殊的InMemoryStore可用于在进程期间将锁保存在内存中,并可用于测试。

FlockStore

FlockStore使用本地计算机上的文件系统创建锁。它不支持过期,但是当锁对象超出作用域时,锁会自动释放,并由垃圾收集器释放(例如当PHP进程结束时):

1 2 3 4 5
使用ob娱乐下载组件商店FlockStore//参数是创建锁的目录的路径//如果没有,则在内部使用sys_get_temp_dir()。商店FlockStore (/ var /商店的);

谨慎

注意,某些文件系统(例如某些类型的NFS)不支持锁定。在这些情况下,最好使用本地磁盘驱动器或远程存储上的目录。

MemcachedStore

MemcachedStore将锁保存在Memcached服务器上,它需要一个Memcached连接来实现\ Memcached类。这个存储不支持阻塞,并期望TTL来避免锁被卡住:

1 2 3 4 5 6
使用ob娱乐下载组件商店MemcachedStorememcached\ Memcached ();memcached->addServer (“localhost”11211);商店MemcachedStore (memcached);

请注意

Memcached不支持TTL小于1秒。

MongoDbStore

5.1

MongoDbStore在Symfony 5.1中引入。ob娱乐下载

MongoDbStore在MongoDB服务器上保存锁> = 2.2,它需要一个\ MongoDB \集合\ MongoDB \客户mongodb / mongodb或者一个MongoDB连接字符串.该存储不支持阻塞,并期望TTL来避免锁被卡住:

1 2 3 4 5 6 7 8 9 10 11
使用ob娱乐下载组件商店MongoDbStore蒙戈mongodb: / / localhost /数据库?收集=锁'选项= (“gcProbablity”= >0.001“数据库”= >“myapp”“收集”= >“锁”“uriOptions”= > [],“driverOptions”=> [],];商店MongoDbStore (蒙戈选项);

MongoDbStore执行以下操作选择美元(取决于第一个参数类型):

选项 描述
gcProbablity 是否应该创建一个TTL索引,表示为从0.0到1.0的概率(默认为0.001
数据库 数据库的名称
集合 集合的名称
uriOptions 的URI选项数组MongoDBClient: __construct
driverOptions 的驱动程序选项数组MongoDBClient: __construct

当第一个参数为a时:

MongoDB \集合

  • 美元的选项(“数据库”)被忽略
  • 美元的选项(“收集”)被忽略

MongoDB \客户

  • 美元的选项(“数据库”)是强制性的
  • 美元的选项(“收集”)是强制性的

MongoDB连接字符串:

  • 美元的选项(“数据库”)用于其他情况/路径从DSN,至少一个是强制性的
  • 美元的选项(“收集”)用于其他情况收集? =从DSN,至少一个是强制性的

请注意

集合查询字符串参数不是MongoDB连接字符串定义。它用于构造MongoDbStore使用一个数据源名称(DSN)没有选择美元

PdoStore

PdoStore将锁保存在SQL数据库中。它与DoctrineDbalStore相同,但需要一个PDO连接或数据源名称(DSN).这个存储不支持阻塞,并期望TTL来避免锁被卡住:

1 2 3 4 5
使用ob娱乐下载组件商店PdoStore//通过PDO进行延迟连接的PDO或DSNdatabaseConnectionOrDSN“mysql:主机= 127.0.0.1;dbname =应用'商店PdoStore (databaseConnectionOrDSN, (“db_username”= >“myuser”“db_password”= >“我的密码”]);

请注意

此商店不支持TTL低于1秒。

类的第一次调用时自动创建存储值的表save ()方法。方法显式创建此表不知道()方法。

5.4

使用PdoStore在Symfony 5.4中,DBAL已弃用。ob娱乐下载使用DoctrineDbalStore代替。

DoctrineDbalStore

DoctrineDbalStore将锁保存在SQL数据库中。它与PdoStore相同,但需要一个原则DBAL连接,或原则DBAL URL.这个存储不支持阻塞,并期望TTL来避免锁被卡住:

1 2 3 4 5
使用ob娱乐下载组件商店DoctrineDbalStore// a Doctrine DBAL连接或DSNconnectionOrURL“mysql: / / myuser: mypassword@127.0.0.1 /应用程序商店DoctrineDbalStore (connectionOrURL);

请注意

此商店不支持TTL低于1秒。

类的第一次调用时自动创建存储值的表save ()方法。还可以通过调用将该表添加到模式中configureSchema ()方法显式创建此表不知道()方法。

5.4

DoctrineDbalStore在Symfony 5.4中被引入来取ob娱乐下载代PdoStore当与DBAL原则一起使用时。

PostgreSqlStore

PostgreSqlStore和DoctrineDbalPostgreSqlStore使用咨询锁由PostgreSQL提供。它与DoctrineDbalPostgreSqlStore相同,但需要PDO连接或数据源名称(DSN).它支持本地阻塞,以及共享锁:

1 2 3 4 5
使用ob娱乐下载组件商店PostgreSqlStore//通过PDO进行延迟连接的PDO实例或DSNdatabaseConnectionOrDSN“pgsql:主机= localhost;端口= 5634;dbname =应用'商店PostgreSqlStore (databaseConnectionOrDSN, (“db_username”= >“myuser”“db_password”= >“我的密码”]);

相对于PdoStore,PostgreSqlStore不需要表来存储锁,而且不会过期。

5.2

PostgreSqlStore在Symfony 5.2中引入。ob娱乐下载

5.4

使用PostgreSqlStore在Symfony 5.4中,DBAL已弃用。ob娱乐下载使用DoctrineDbalPostgreSqlStore代替。

DoctrineDbalPostgreSqlStore

DoctrineDbalPostgreSqlStore使用咨询锁由PostgreSQL提供。它与PostgreSqlStore相同,但需要一个原则DBAL连接或者一个原则DBAL URL.它支持本地阻塞,以及共享锁:

1 2 3 4 5
使用ob娱乐下载组件商店DoctrineDbalPostgreSqlStore// a Doctrine Connection或DSNdatabaseConnectionOrDSN“postgresql +咨询:/ / myuser: mypassword@127.0.0.1:5634 /锁”商店DoctrineDbalPostgreSqlStore (databaseConnectionOrDSN);

相对于DoctrineDbalStore,DoctrineDbalPostgreSqlStore不需要表来存储锁,并且不会过期。

5.4

DoctrineDbalPostgreSqlStore在Symfony 5.4中被引入来取ob娱乐下载代PostgreSqlStore当与DBAL原则一起使用时。

RedisStore

RedisStore将锁保存在Redis服务器上,它需要一个Redis连接来实现\复述,\ RedisArray\ RedisCluster\ Predis类。这个存储不支持阻塞,并期望TTL来避免锁被卡住:

1 2 3 4 5 6
使用ob娱乐下载组件商店RedisStore复述,\复述();复述,->连接(“localhost”);商店RedisStore (复述,);

SemaphoreStore

SemaphoreStore使用PHP信号量函数要创建锁:

1 2 3
使用ob娱乐下载组件商店SemaphoreStore商店SemaphoreStore ();

CombinedStore

组合商店是为高可用性应用程序设计的,因为它同步管理多个商店(例如,几个Redis服务器)。当获得锁时,它将调用转发给所有托管存储,并收集它们的响应。如果绝大多数商店都获得了该锁,则认为该锁已获得:

12 3 4 5 6 7 8 9 10 11 12 13
使用ob娱乐下载组件商店CombinedStore使用ob娱乐下载组件商店RedisStore使用ob娱乐下载组件策略ConsensusStrategy商店= [];foreach([“server1”server2的“server3”作为服务器){复述,\复述();复述,->连接(服务器);商店[] =RedisStore (复述,);}商店CombinedStore (商店ConsensusStrategy ());

而不是简单多数策略(ConsensusStrategy)一个UnanimousStrategy可用于要求在所有商店中获取锁:

1 2 3 4
使用ob娱乐下载组件商店CombinedStore使用ob娱乐下载组件策略UnanimousStrategy商店CombinedStore (商店UnanimousStrategy ());

谨慎

为了在使用时获得高可用性ConsensusStrategy时,最小集群大小必须为3台服务器。这允许集群在单个服务器出现故障时继续工作(因为此策略要求为超过一半的服务器获取锁)。

ZookeeperStore

ZookeeperStore保存锁动物园管理员服务器。它需要一个ZooKeeper连接来实现\动物园管理员类。这个store不支持阻塞和过期,但是当PHP进程终止时,锁会自动释放:

1 2 3 4 5 6 7
使用ob娱乐下载组件商店ZookeeperStore动物园管理员\管理员(“localhost: 2181”);//使用以下命令定义高可用性集群:// $zookeeper = new \ zookeeper ('localhost1:2181,localhost2:2181,localhost3:2181');商店ZookeeperStore (动物园管理员);

请注意

Zookeeper不需要TTL,因为用于锁定的节点是短暂的,当PHP进程终止时就会死亡。

可靠性

只要以以下方式使用该组件,该组件就保证同一资源不会被锁定两次。

远程存储

远程存储(MemcachedStoreMongoDbStorePdoStorePostgreSqlStoreRedisStore而且ZookeeperStore)使用唯一令牌来识别锁的真正所有者。标记存储在关键对象在内部使用

每个并发进程必须存储在同一个服务器上。否则两台不同的机器可能允许两个不同的进程获得相同的数据

谨慎

为了保证同一台服务器始终是安全的,不要在LoadBalancer、集群或轮询DNS后面使用Memcached。即使主服务器关闭,也不能将调用转发到备份或故障转移服务器。

到期的商店

即将到期的储存区(MemcachedStoreMongoDbStorePdoStore而且RedisStore)保证只在规定的时间内获得锁。如果任务需要更长的时间才能完成,那么锁可以由存储释放,并由其他人获取。

提供几种检查其运行状况的方法。的isExpired ()方法检查其生命周期是否结束getRemainingLifetime ()方法返回以秒为单位的时间。

使用上述方法,一个健壮的代码将是:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ /……工厂->createLock (“pdf-creation”30.);如果(!->获得()){返回;}(!完成了){如果->getRemainingLifetime () < =5){如果->isExpired ()) {//锁丢失,执行回滚或发送通知\ RuntimeException (“锁在整个过程中丢失”);}->refresh ();}//执行耗时小于5分钟的任务

谨慎

明智地选择你的一生并检查其剩余的生存时间是否足够执行任务。

谨慎

存储通常需要几毫秒,但网络条件可能会大大增加这个时间(最多几秒)。在选择正确的TTL时要考虑到这一点。

按照设计,锁存储在具有定义的生命周期的服务器上。如果机器的日期或时间发生了变化,锁可能会比预期更快地释放。

谨慎

为了保证日期不会改变,NTP服务应该被禁用,并且在服务停止时应该更新日期。

FlockStore

通过使用文件系统,这商店只要并发进程使用相同的物理目录存储锁,它就可靠。

进程必须运行在同一台机器、虚拟机或容器上。更新Kubernetes或Swarm服务时要小心,因为在短时间内,可能会有两个容器并行运行。

目录的绝对路径必须保持不变。小心可能随时改变的符号链接:Capistrano和蓝/绿部署经常使用这个技巧。当到该目录的路径在两次部署之间发生变化时要小心。

某些文件系统(例如某些类型的NFS)不支持锁定。

谨慎

所有并发进程必须使用相同的物理文件系统,运行在同一台机器上,并使用到锁目录的相同绝对路径。

使用一个FlockStore在HTTP上下文中与多个前端服务器不兼容,除非确保同一资源始终锁定在同一台机器上,或者使用配置良好的共享文件系统。

文件系统中的文件可以在维护操作时删除。例如,清理/ tmp目录或重新启动计算机后使用的目录tmpfs.如果在进程结束时释放锁,这不是问题,但如果发生在请求之间重用。

谨慎

如果需要在多个请求中重用volatile文件系统上的锁,则不要将它们存储在volatile文件系统上。

MemcachedStore

Memcached的工作方式是将项存储在内存中。这意味着通过使用MemcachedStore锁不是持久的,并且可能在任何时候错误地消失。

如果Memcached服务或承载它的机器重新启动,每个锁都将丢失,而不会通知正在运行的进程。

谨慎

为了避免重启后被其他人获得锁,建议延迟服务启动,等待时间至少等于最长锁TTL。

默认情况下,当服务需要空间来添加新项时,Memcached使用LRU机制删除旧项。

谨慎

必须控制存储在Memcached中的项的数量。如果不可能,应该禁用LRU,并将Lock存储在专用的Memcached服务中,远离Cache。

当Memcached服务被共享并用于多个用途时,锁可能会被错误地删除。例如PSR-6的一些实现clear ()方法使用Memcached的冲洗()清除和删除所有内容的方法。

谨慎

该方法冲洗()不能被调用,或者锁应该存储在专用的Memcached服务中,远离Cache。

MongoDbStore

谨慎

锁定资源名在_id锁集合的字段。注意,在MongoDB中索引字段的值可能是长度不超过1024字节包括结构开销。

必须使用TTL索引来自动清除过期的锁。这样的索引可以手动创建:

1 2 3 4
db.lock。方法createIndex ({“expires_at”1}, {“expireAfterSeconds”0})

或者,方法MongoDbStore::createTtlIndex(int $expireAfterSeconds = 0)可以在数据库设置期间调用一次来创建TTL索引。阅读更多通过设置TTL使集合中的数据过期在MongoDB。

提示

MongoDbStore将尝试自动创建一个TTL索引。建议设置构造函数optiongcProbablity0.0如果已手动处理TTL索引创建,则禁用此行为。

谨慎

此存储依赖于所有PHP应用程序和数据库节点具有同步时钟,以便在正确的时间发生锁过期。确保锁不会过早过期;锁的TTL应该被设置为有足够的额外时间expireAfterSeconds考虑节点之间的时钟漂移。

writeConcern而且readConcern没有被MongoDbStore指定,这意味着集合的设置将生效。readPreference主要的对于所有查询。阅读更多副本设置读写语义在MongoDB。

PdoStore

PdoStore依赖SQL引擎属性。

谨慎

在配置了多个主的集群中,确保同步地将写操作传播到每个节点,或者始终使用相同的节点。

谨慎

一些SQL引擎(如MySQL)允许禁用唯一约束检查。确保不是这种情况设置unique_checks = 1;

为了清除旧锁,该存储使用当前datetime来定义过期日期引用。该机制依赖于所有服务器节点具有同步时钟。

谨慎

确保锁不会过早过期;ttl应该设置足够的额外时间,以考虑节点之间的任何时钟漂移。

PostgreSqlStore

PdoStore依赖咨询锁PostgreSQL数据库属性。这意味着通过使用PostgreSqlStore锁将在会话结束时自动释放,以防客户端因任何原因无法解锁。

如果PostgreSQL服务或承载它的机器重新启动,每个锁都会丢失,而不会通知正在运行的进程。

如果TCP连接丢失,PostgreSQL可能在不通知应用程序的情况下释放锁。

RedisStore

Redis的工作方式是将项目存储在内存中。这意味着通过使用RedisStore锁不是持久的,并且可能在任何时候错误地消失。

如果Redis服务或承载它的机器重新启动,每个锁都将丢失,而不通知正在运行的进程。

谨慎

为了避免重启后被其他人获得锁,建议延迟服务启动,等待时间至少等于最长锁TTL。

提示

Redis可以配置为将项目持久化在磁盘上,但是这个选项会减慢对服务的写操作。这可能与服务器的其他用途相冲突。

当Redis服务被共享并用于多个用途时,锁可能会被错误地删除。

谨慎

命令FLUSHDB必须不被调用,或者锁应该存储在一个专用的Redis服务远离缓存。

CombinedStore

合并存储允许跨多个后端存储锁。认为锁定机制会更可靠是一个常见的错误。这是错误的。的CombinedStore最好的情况下,将与所有托管存储中最不可靠的存储一样可靠。一旦某个托管存储返回错误信息,则CombinedStore不可靠。

谨慎

所有并发进程必须使用相同的配置,具有相同数量的托管存储和相同的端点。

提示

与其使用Redis或Memcached服务器集群,不如使用CombinedStore每个托管存储都有一个服务器。

SemaphoreStore

信号量由内核级处理。为了保证可靠性,进程必须运行在同一台机器、虚拟机或容器上。更新Kubernetes或Swarm服务时要小心,因为在短时间内,可能会有两个并行运行的容器。

谨慎

所有并发进程必须使用同一台机器。在新机器上启动并发进程之前,请检查旧机器上的其他进程是否已停止。

谨慎

使用非系统用户和选项在systemd上运行时RemoveIPC = yes(默认值),当用户注销时,systemd将删除锁。检查进程是否使用系统用户(UID <= SYS_UID_MAX)运行SYS_UID_MAX中定义的/etc/login.defs,或设置该选项RemoveIPC =了/etc/systemd/logind.conf

ZookeeperStore

zookeeper的工作方式是将锁作为服务器上的临时节点来维护。这意味着通过使用ZookeeperStore锁将在会话结束时自动释放,以防客户端因任何原因无法解锁。

如果ZooKeeper服务或承载它的机器重新启动,每个锁都会丢失,而不会通知正在运行的进程。

提示

为了使用ZooKeeper的高可用性特性,你可以设置多个服务器的集群,这样在其中一个服务器宕机的情况下,大多数服务器仍然是正常的,并为请求服务。集群中的所有可用服务器都将看到相同的状态。

请注意

由于此存储不支持多级节点锁,因此清理中间节点成为一种开销,因此所有锁都在根级别维护。

整体

更改存储的配置应该非常谨慎。例如,在部署新版本期间。当具有旧配置的旧进程仍在运行时,不能启动具有新配置的进程。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。
ob娱乐下载Symfony 5.4支持通过私人Packagist