结合Laravel与Dragonfly使用

Dragonfly是一款旨在以更少的服务器数量实现远超Redis性能的替代方案。单个节点能处理每秒数百万次查询,并可存储高达1TB的内存数据。本文将探讨如何将Dragonfly与Laravel这一广受欢迎且知名的Web框架结合使用。

Dragonfly完全兼容Redis接口,这意味着Laravel开发者可以无需修改任何代码,将其作为缓存和队列驱动进行集成。这种无缝集成提供了轻松升级的途径,并带来显著的益处。

因此,无论你是经验丰富的Laravel老手还是初学者,都请跟随我们一起探索Dragonfly与Laravel的世界。

开始入门

首先,让我们设置一个新的Dragonfly实例。访问我们的文档这里下载镜像或二进制文件,并迅速启动并运行一个Dragonfly实例。一旦Dragonfly实例运行并可访问,将其与Laravel项目集成就变得非常简单。幸运的是,Laravel已全面支持Redis,因此所有驱动都可以复用。要在Laravel应用中使用Dragonfly,请首先更新.env文件,配置如下内容。

对于缓存和会话管理:

CACHE_DRIVER=redis
SESSION_DRIVER=redis

若要将Dragonfly也作为队列驱动集成:

QUEUE_CONNECTION=redis

尽管我们使用redis作为驱动值,但Dragonfly旨在直接替代Redis,因此无需额外安装驱动程序。设置好驱动后,下一步是确保Laravel能够与Dragonfly实例通信。这需要再次更新.env文件,填写正确的连接详情:

  • REDIS_HOST:Dragonfly服务器的域名或IP地址。
  • REDIS_PORT:Dragonfly实例运行的端口。
  • REDIS_PASSWORD:如果设置了的话,Dragonfly实例的密码。

以下是一个配置示例:

REDIS_HOST=127.0.0.1 # Replace with Dragonfly host
REDIS_PORT=6379      # Replace with Dragonfly port
REDIS_PASSWORD=null  # Replace with Dragonfly password if applicable

更新这些设置后,通过在Laravel中运行简单的INFO命令来验证连接。如果遇到任何连接问题,请仔细检查主机、端口和密码值。同时确保Dragonfly服务器正在运行,并且可以从Laravel应用程序的环境中访问。

use Illuminate\Support\Facades\Redis;

// 运行INFO命令并打印Dragonfly版本。
Redis::info()["dragonfly_version"];

作为缓存的高效率

缓存频繁访问的值是像Dragonfly和Redis这样的内存数据库的主要用途之一,因为它们响应迅速。正是在这种情况下,Dragonfly表现出色,特别是在涉及大量键和客户端的场景中,例如作为多节点系统或微服务的中枢缓存。

A standout feature of Dragonfly is the cache mode, designed specifically for scenarios where maintaining a lean memory footprint is as crucial as performance. In this mode, Dragonfly evicts the least recently accessed values when it detects low memory availability, ensuring efficient memory usage without sacrificing speed. You can read more about the eviction algorithm in the Dragonfly Cache Design blog post.

启用缓存模式非常简单。以下是运行Dragonfly在此模式下的标志,内存上限为12GB:

./dragonfly --cache_mode --maxmemory=12G

考虑一个场景,您的应用程序需要处理大量请求并处理庞大的数据集。在这种情况下,Dragonfly缓存模式能够高效管理内存使用,同时提供快速的数据访问,确保您的应用程序保持响应迅速且灵活。

从API角度看,Laravel Cache门面的所有功能都应得到支持。例如,要存储一个具有特定过期时间的键值对,可以使用以下代码片段:

use Illuminate\Support\Facades\Cache;

// 存储一个值,过期时间为10分钟。
Cache::put("key", "value", 600);

内存使用

使用Dragonfly作为缓存的一大优势是,在多数用例中,它的内存使用量明显更低。让我们进行一个简单的实验,向Redis和Dragonfly填充随机字符串,并测量填充数据后它们的总内存使用量。

Dataset Dragonfly Redis
3 Million Values of Length 1000 2.75GB 3.17GB
15 Million Values of Length 200 3.8GB 4.6GB

实验后我们观察到,在相似条件下,Dragonfly的内存使用量比Redis低多达20%。这意味着您可以在相同的内存需求下存储更多的有效数据,使缓存更高效,覆盖面更广。您可以在《Redis与Dragonfly的可扩展性和性能博客文章》中了解更多关于Dragonfly的吞吐量基准测试和内存使用情况

快照功能

除了降低内存使用外,Dragonfly在快照过程中也展现出了稳定性。快照,尤其是在繁忙实例中,对内存管理是一个挑战。使用Redis时,在高活跃度实例上进行快照可能会导致内存使用量增加,因为Redis需要复制内存页,即使是那些仅部分被覆盖的页,这会导致内存使用量激增。

相比之下,Dragonfly根据传入请求调整快照顺序,有效避免了内存使用的意外激增。这意味着即使在如快照这样的密集操作期间,Dragonfly也能保持稳定的内存占用,确保性能一致,避免突然的内存峰值。关于Dragonfly快照算法的更多信息,可参阅《平衡与不平衡》博客文章

关键粘性

Dragonfly还引入了一个新功能,即自定义STICK命令。该命令在缓存模式下运行的实例中尤为有用,它允许将特定键标记为不可逐出的,无论其访问频率如何。

此功能特别适合存储访问频率不高但重要的数据。例如,您可以可靠地保存辅助信息,如动态配置值,直接存储在Dragonfly实例中。这消除了对单独数据存储的需求,简化了不常用但关键数据的管理流程。

// 在Dragonfly实例中存储具有粘性的值。
Redis::transaction(function (Redis $redis) {
    $redis->set('server-dynamic-configuration-key', '...');
    $redis->command('STICK', 'server-dynamic-configuration-key');
});

// ...

// 由于键不可被驱逐,将始终返回值。
$redis->get('server-dynamic-configuration-key');

队列管理中的吞吐量增强

与Redis类似,Dragonfly擅长管理队列和任务。如您所料,使用Dragonfly进行此操作无需代码修改,过渡无缝。以Laravel中调度播客处理任务为例:

use App\Jobs\ProcessPodcast;

$podcast = Podcast::create(/* ... */);
ProcessPodcast::dispatchSync($podcast);

Dragonfly和Redis都能轻松处理每秒数万个任务。

对于追求性能最大化的用户,值得注意的是,使用单一任务队列不会带来显著性能提升。要真正发挥Dragonfly的潜力,应采用多个队列。这种方法将负载分散到多个Dragonfly线程,从而提高整体吞吐量。

然而,当同一队列的键分布到不同线程时,常常会遇到一个共同挑战,即导致延迟增加。为解决这一问题,Dragonfly提供了在队列名称中使用标签的功能。这些标签确保同一队列(使用相同标签)的任务自动分配给特定线程,类似于Redis集群环境中的操作,从而降低延迟并优化性能。欲深入了解标签,请查阅《使用Dragonfly运行BullMQ博客文章》,其中详细阐述了标签及其优势,同时Dragonfly作为消息队列系统的后备存储。

快速示例,为优化使用Dragonfly的队列管理,首先启动Dragonfly时需指定启用基于标签锁定和模拟集群模式的标志:

./dragonfly --lock_on_hashtags --cluster_mode=emulated

一旦Dragonfly按这些设置运行,便在Laravel中队列名称中融入标签。示例如下:

ProcessPodcast::dispatch($podcast)->onQueue('{podcast_queue}');

通过在队列名称中使用标签,确保Dragonfly中属于同一队列的所有消息由同一线程处理。此方法不仅保持相关消息集中,提升效率,还允许Dragonfly通过跨多个线程分配不同队列来最大化吞吐量。

此方法对于依赖Dragonfly作为消息队列后端存储的系统尤为有效,它利用了Dragonfly的多线程架构,能更高效地处理大量消息。

结论

Dragonfly以其处理大规模工作负载时内存消耗低和多线程架构的优势,成为现代网络应用的诱人选择。本文中,我们探讨了Dragonfly如何与Laravel无缝集成,无论是缓存、会话管理还是队列管理,所需代码改动极少甚至无需改动。

Source:
https://dzone.com/articles/using-laravel-with-dragonfly