锁组件

编辑该页面

警告:你浏览的文档欧宝体育电话欧宝娱乐app下载地址Symfony 4.1,不再维护。

这个页面的更新版本Symf欧宝娱乐app下载地址ony 6.2(当前的稳定版本)。

锁组件

锁组件创建并管理,一个机制来提供独家访问共享资源。

安装

1
美元作曲家需要symfony /锁欧宝娱乐app下载地址

或者,您可以克隆的https://github.com/欧宝娱乐app下载地址symfony/lock存储库。

请注意

如果你安装这个组件之外的Symfony应用程序,你必须要求欧宝娱乐app下载地址供应商/ autoload.php文件在你的代码,使作曲家提供的类加载机制。读这篇文章为更多的细节。

使用

锁是用来保证独占访问共享资源。例如在欧宝娱乐app下载地址Symfony应用程序中,您可以使用锁来确保一个命令不执行不止一次在同一时间(在相同或不同的服务器上)。

锁是使用创建的工厂类,这又需要另一个类来管理存储的锁:

1 2 3 4 5
使用欧宝娱乐app下载地址\组件\\工厂;使用欧宝娱乐app下载地址\组件\\商店\SemaphoreStore;美元商店=SemaphoreStore ();美元工厂=工厂(美元商店);

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

1 2 3 4 5 6 7 8 9
/ /……美元=美元工厂- >createLock (“pdf-invoice-generation”);如果(美元- >获得()){/ /资源“pdf-invoice-generation”是锁着的。/ /这里可以安全地计算并生成发票。美元- >release ();}

如果不能获得锁,方法返回。的获得()方法可以安全地调用多次,即使已经获得锁。

请注意

不像其他的实现,即使他们区分锁锁组件实例创建相同的资源。如果锁必须使用多个服务,他们应该共享相同的返回的实例工厂:createLock方法。

提示

如果不显式地释放锁,它将自动释放实例的破坏。在某些情况下,它可以帮助锁定资源跨多个请求。禁用自动释放行为,第三个参数的设置createLock ()方法

阻塞锁

默认情况下,当无法获得一个锁,收购方法返回立即。等到(无限期)锁可以创建,通过真正的的论点获得()方法。这被称为阻塞锁因为您的应用程序的执行停止,直到锁。

一些内置的商店类支持这一特性。当他们不,他们可以装饰着RetryTillSaveStore类:

1 2 3 4 5 6 7 8 9 10
使用欧宝娱乐app下载地址\组件\\工厂;使用欧宝娱乐app下载地址\组件\\商店\RedisStore;使用欧宝娱乐app下载地址\组件\\商店\RetryTillSaveStore;美元商店=RedisStore (\ Predis \客户端(“tcp: / / localhost: 6379”));美元商店=RetryTillSaveStore (美元商店);美元工厂=工厂(美元商店);美元=美元工厂- >createLock (“notification-flush”);美元- >获得(真正的);

到期的锁

锁创建远程很难管理,因为没有远程方式商店知道柜过程仍然活着。由于错误,致命错误或分割的缺点,它不能保证release ()方法将调用,这将导致资源无限。

在这种情况下是创建最好的解决方案到期的锁一段时间后,自动释放已通过(TTL呼吁生存时间)。这一次,在几秒钟内,第二个参数的配置createLock ()方法。如果需要,还可以释放这些锁的早期release ()方法。

使用锁定到期时最棘手的部分是选择合适的TTL。如果太短了,其他进程可以获得锁之前完成工作;如果太长和过程调用之前崩溃release ()方法,资源将保持锁定,直到超时:

1 2 3 4 5 6 7 8 9 10
/ /……/ /创建一个锁定到期,持续30秒美元=美元工厂- >createLock (“charts-generation”,30.);美元- >获得();试一试{/ /执行工作期间少于30秒}最后{美元- >release ();}

提示

为了避免让锁处于锁定状态,建议将工作在一个try / catch / finally块中总是试图到期释放锁。

在长时间运行的任务的情况下,最好开始不久TTL,然后使用refresh ()方法重置TTL到原来的值:

1 2 3 4 5 6 7 8 9 10 11 12 13 14
/ /……美元=美元工厂- >createLock (“charts-generation”,30.);美元- >获得();试一试{(!美元完成了){/ /执行工作的一小部分。/ /更新锁30秒钟。美元- >refresh ();}}最后{美元- >release ();}

提示

另一个有用的技术,长时间运行的任务是通过一个自定义的TTL作为参数refresh ()方法来改变默认的锁TTL:

1 2 3 4 5 6 7
美元=美元工厂- >createLock (“charts-generation”,30.);/ /……/ /刷新锁,持续30秒美元- >refresh ();/ /……/ /刷新锁定为600秒(下刷新()调用将再次30秒)美元- >刷新(600年);

4.1

该功能通过一个定制的TTL作为参数refresh ()方法是在Symfony 4.1中引入的。欧宝娱乐app下载地址

可用的商店

锁是创建和管理商店类,实现StoreInterface。内置存储组件包括以下类型:

商店 范围 阻塞 即将到期的
FlockStore 当地的 是的 没有
MemcachedStore 远程 没有 是的
RedisStore 远程 没有 是的
SemaphoreStore 当地的 是的 没有

FlockStore

FlockStore使用本地计算机上的文件系统创建锁。它不支持过期,但锁是PHP时自动释放过程终止:

1 2 3 4
使用欧宝娱乐app下载地址\组件\\商店\FlockStore;/ /参数是锁的目录的路径美元商店=FlockStore (sys_get_temp_dir ());

谨慎

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

MemcachedStore

MemcachedStore保存锁在Memcached服务器上,它需要一个Memcached连接实现\ Memcached类。这家商店不支持阻塞,并预计TTL避免停滞锁:

1 2 3 4 5 6
使用欧宝娱乐app下载地址\组件\\商店\MemcachedStore;美元memcached=\ Memcached ();美元memcached- >addServer (“localhost”,11211年);美元商店=MemcachedStore (美元memcached);

请注意

Memcached不支持TTL低于1秒。

RedisStore

RedisStore保存复述,服务器上的锁,它需要复述,连接实现\复述,,\ RedisArray,\ RedisCluster\ Predis类。这家商店不支持阻塞,并预计TTL避免停滞锁:

1 2 3 4 5 6
使用欧宝娱乐app下载地址\组件\\商店\RedisStore;美元复述,=\复述();美元复述,- >连接(“localhost”);美元商店=RedisStore (美元复述,);

SemaphoreStore

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

1 2 3
使用欧宝娱乐app下载地址\组件\\商店\SemaphoreStore;美元商店=SemaphoreStore ();

CombinedStore

CombinedStore是专为高可用性的应用程序,因为它管理几个店铺同步(例如,几个复述,服务器)。锁被收购时,它将调用转发给所有的存储管理,并收集他们的反应。如果一个简单多数的商店获得锁,然后被认为是获得锁;否则就不会获得:

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

而不是简单多数的策略(ConsensusStrategy)一个UnanimousStrategy可用于需要获得锁所有的商店。

谨慎

为了得到高可用性时使用ConsensusStrategy,最低必须三个服务器集群大小。这允许集群继续工作当一个服务器失败(因为这个策略需要锁在超过一半的服务器)。

可靠性

组件保证相同的资源不能被锁两次只要组件中使用以下方式。

远程存储

远程商店(MemcachedStoreRedisStore)使用一个独特的锁牌识别真正的所有者。这令牌存储在关键对象和内部使用的,因此这个键不能在进程之间共享(会话、缓存、叉……)。

谨慎

之间不共享一个关键过程。

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

谨慎

保证相同的服务器总是安全的,不使用Memcached loadbalance后面,一个集群或循环DNS。即使主服务器,调用不能转发到一个备份或故障转移服务器。

到期的商店

到期的商店(MemcachedStoreRedisStore)保证了锁只对定义的持续时间。如果任务花费的时间完成,然后锁可以存储和发布的被别人收购。

提供了几个方法来检查它的健康。的isExpired ()方法检查是否已经结束,生命getRemainingLifetime ()方法返回的时间住在秒。

使用上面的方法,一个更健壮的代码是:

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

谨慎

做出明智的选择的生命周期并检查其剩余时间离开是否足以执行任务。

谨慎

存储通常需要几毫秒,但网络环境可能会增加时间(几秒钟)。选择正确的TTL时考虑。

通过设计,锁都存储在服务器上定义的生命周期。如果机器的日期或时间变化,锁被释放的时间可能早于预期。

谨慎

保证日期不会改变,国家结核控制规划服务应该禁用和日期应该在服务停止时更新。

FlockStore

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

过程必须运行在同一台机器上,虚拟机或容器。更新Kubernetes或群体服务的时候要小心,因为很短的时间内,可以有两个并行运行的容器。

目录的绝对路径必须是相同的。小心随时可以改变的符号链接:Capistrano和蓝色/绿色部署经常使用这个技巧。该目录路径改变时要小心两个部署。

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

谨慎

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

根据定义,使用的FlockStore在一个HTTP上下文与多个前端服务器不兼容,除非以确保相同的资源总是被锁定在同一台机器上或者使用一个共享文件系统配置。

文件系统上的文件可以删除在维护操作。例如,清理/ tmp目录或重新启动机器后,一个目录使用tmpfs。这不是一个问题,如果释放锁过程结束后,但在请求之间重用。