BONUS: We have discussed this topic with an expert in the PHP community in our podcast:
There are several ways (architectures) in which applications can work, with the most notable being:
In this post, we’re going to look at what Shared-Nothing Architecture is, along with its benefits and downsides, concerning PHP and its impact on performance.
If these terms are new to you, let’s briefly step through them.
A Shared-Nothing Architecture
A Shared-Nothing Architecture is a distributed-computing architecture in which nodes do not share (independently access) memory or storage with any other. The intent is to eliminate contention among nodes.
A Shared-Disk Architecture
A Shared-Disk Architecture is quite similar to shared-nothing, except that every node interacts with a shared disk, typically a database (such as MySQL, PostgreSQL, and Oracle), or a shared filesystem typically provided by a storage area network (SAN) or network-attached storage (NAS).
A Shared-Memory Architecture
Similar to shared-disk, the Shared-Memory Architecture, as the name implies, is where each node makes use of a shared-memory resource. This could be a cache provided by Redis, Memcache or APCu.
A Shared-Everything Architecture
As the name implies, this is where each node shares all resources with every other node.
Shared Nothing = PHP By Default
If you’ve ever considered how PHP works, by default, then you’ll know that it is based around a shared-nothing model. This is because, for every request a node starts from scratch — with no memory shared from the prior request of the same node. It brings all the required objects into memory, performs the required processing, and then releases all the resources when the request has been fulfilled. This approach lies in stark contrast to languages such as Java, which persist objects across multiple requests.
However, why is this model a good one? Let’s consider the benefits. A Shared Nothing architecture has several key benefits; these are:
- It Eliminates Single Points of Failure
- Its Simpler to Scale
- It Makes Upgrades Simpler
- It’s a Drastically Simpler Programming Model
It Eliminates Single Points of Failure
As nodes don’t share any resources, applications can continue functioning even if one or more nodes fail. Yes, application performance drops with each node that fails, but the application can continue to function, as nodes don’t share any resources between themselves.
Its Simpler to Scale
As each node can serve requests to the application without having to deal with resource contention, then as many additional nodes as are required can be added, as and when necessary, to scale the application to provide sufficient capacity.
It Makes Upgrades Simpler
As with the previous point, individual nodes can be upgraded, or replaced, without shutting down the entire application. No node is aware of any other, so it doesn’t matter if one is removed, upgraded, or improved.
It’s a Drastically Simpler Programming Model
PHP developers don’t, often, have to think about memory too much. In most PHP applications, memory is used within a single, often very short-lived, request. Objects are initialized, used, and dropped. Consequently, developers, generally, don’t have to deal with the implications of objects that persist for a long time; such as with worker processes, or across multiple requests.
Is it A Practical Model?
Like many questions, the answer is: “it depends”, and is based on many factors. The prime among them is: “How is your application is designed and/or developed?” That design (or legacy development) may necessitate not strictly adhering to a shared-nothing architecture, but rather a combination of one or more of the others.
If it helps, cast your mind back to the earlier versions of PHP. In those days, PHP was, virtually, wedded at the proverbial hip with MySQL. Countless articles and tutorials detailed PHP apps storing all their data in a MySQL database.
Then, over the years as applications became larger and more complex, a greater emphasis was given to sessions and caching as well. Sessions were often stored on a shared filesystem or in a database and application objects, and its data were often cached in a high-performance, in-memory data store, such as Redis or Memcached. And let’s not forget the use of queueing servers, such as RabbitMQ, Beanstalkd, ActiveMQ, and Redis.
As a result of these, and other, changes, it’s very easy for PHP applications to more likely be a blend of shared-memory, shared-disk, or shared-everything.
However, if care’s given, each node can still, more or less, operate in a shared-nothing manner.
Is Shared-Nothing The Right Approach?
Before you seek out alternatives, it’s worth asking if you the benefits of not using PHP with Shared Nothing are worth it
As we’ve seen so far, shared-nothing offers a significant number of benefits. Additionally, PHP’s shared nothing design provides a significant performance advantage, and larger frameworks are built around this approach.
That said, there are individual use-cases that work better with sharing memory across requests, such as Websockets. What’s more, if you build an application based around shared-nothing, it’s not a trivial endeavor to move away from it. You can’t just flip the proverbial switch at a time of your choosing. So, I’d strongly encourage to you carefully consider if not using it truly is what you want to do.
Running PHP Without Shared Nothing
If you’re keen to build applications in PHP which don’t fully implement a shared-nothing architecture, then you may be interested in knowing that there are some frameworks available to help out. These are:
- Roadrunner: a high-performance PHP application server, load-balancer, and process manager written in Golang.
- Swoole: Enables PHP developers to write high-performance, scalable, concurrent TCP, UDP, Unix socket, HTTP, Websocket services in PHP programming language without too much knowledge about non-blocking I/O programming and low-level Linux kernel.
- ReactPHP: a low-level library for event-driven programming in PHP. At its core is an event loop, on top of which it provides low-level utilities, such as Streams abstraction, async DNS resolver, network client/server, HTTP client/server and interaction with processes.
In this article, we’ve taken a (brief) look at four of the most common application architectures, but given particular emphasis to one: shared-nothing. We’ve learned about its key benefits and their impact on application performance. We also got an overview of three of PHP’s most common shared-nothing frameworks, those being Roadrunner, Swoole, and ReactPHP.
I hope that this article’s helped give you a clearer picture of the architectural models available, and why PHP’s default is such a powerful one.