SELCC: Coherent Caching over Compute-Limited Disaggregated Memory
Ruihong Wang Jianguo Wang Walid G. Aref

plain 





  Purdue University
  
  
  
  

wang4996@purdue.edu




  Purdue University
  
  
  

csjgwang@purdue.edu




  Purdue University
  
  

aref@purdue.edu

§ ABSTRACT 


Disaggregating memory from compute offers the opportunity to better utilize  stranded memory in  data centers. It is important to cache data in the compute nodes and maintain cache coherence across  multiple compute nodes to save on round-trip communication cost between the disaggregated memory and the compute nodes. However, the limited computing power on the disaggregated memory servers makes it challenging to maintain  cache coherence among multiple compute-side caches over disaggregated shared memory.  This paper introduces SELCC; a Shared-Exclusive Latch Cache Coherence protocol that maintains cache coherence without imposing any computational burden on the remote memory side. SELCC builds on a one-sided shared-exclusive latch protocol by introducing lazy latch release and invalidation messages among the compute nodes so that it can guarantee both data access atomicity and cache coherence. SELCC minimizes communication round-trips by embedding the current cache copy holder IDs into RDMA latch words and prioritizes local concurrency control over global concurrency control. We instantiate the SELCC protocol onto compute-sided cache, forming an abstraction layer over disaggregated memory. This abstraction layer provides main-memory-like APIs to upper-level applications,  and thus enabling existing data structures and algorithms to function over disaggregated memory with minimal code change. To demonstrate the usability of SELCC, we implement a B-tree and three transaction concurrency control algorithms over SELCC's APIs. Micro-benchmark results show that the SELCC protocol achieves better performance compared to RPC-based cache-coherence protocols. Additionally, YCSB and TPC-C benchmarks indicate that applications over SELCC can achieve comparable or superior performance against 
competitors over disaggregated memory.


















SELCC: Coherent Caching over Compute-Limited Disaggregated Memory 





    Walid G. Aref
    Submitted December 13, 2023 / Accepted July 26, 2024
=========================================================================



printfolios=true


















§ INTRODUCTION











Memory disaggregation has emerged as an important trend in cloud databases 

in both 
academia, e.g., <cit.> and industry, e.g., <cit.>. The primary motivation behind disaggregated memory is to utilize the large amounts of stranded memory <cit.> in the data center. Stranded memory refers to 

memory that is inaccessible to the local server because all the available cores have been allocated to virtual machines <cit.>.
Memory disaggregation addresses this issue by physically decoupling the memory resources from compute servers, accessing the stranded memory via high-speed networks. 
By establishing disaggregated memory over stranded memory, cloud providers can significantly enhance memory utilization, and reduce the total cost of ownership (TCO). 
With this type of memory disaggregation, the memory nodes have near-zero computing power, and the CPU cycles used for data communication between compute and memory nodes should be minimized.
The key enabler 

for
memory disaggregation is the network advancement <cit.>, e.g., the Remote Direct Memory Access technology (RDMA), because it can fully bypass the CPU on the remote memory when transferring the data, 
and hence
achieving low latency[In this paper, we assume one-sided RDMA as the primary method for data transfer between compute and memory nodes, while allowing two-sided RDMA messages among compute nodes.]. 

Furthermore, disaggregated memory offers significant benefits to  cloud native databases <cit.>.
The independent provisioning of compute and memory resources introduces elasticity to applications <cit.>. More importantly,  memory disaggregation enables the sharing of main memory among multiple compute nodes, embracing the shared-memory architecture. This advancement facilitates the next generation of multi-primary 

architectures (e.g., PolarDB MP <cit.>), resolving the conflict among  the multiple writers distributively via 

one-sided RDMA rather than heavy-weight consensus algorithms (e.g., Paxos) <cit.> or centralized log servers <cit.>. 



However, developing database 
systems 
over disaggregated shared memory remains challenging, particularly due to the 

data synchronization
problems 

when involving 
multiple writer nodes.


Based on the existing literature on disaggregated memory, we identify two technical challenges in supporting concurrent writer nodes. Additionally, we recognize a common research limitation encountered in many existing studies. This paper aims to address these two technical challenges with a unified approach and proposes a research methodology to avoid the identified limitation.



Challenge 1: Access atomicity over RDMA.
The atomicity between concurrent one-sided RDMA reads and writes is not guaranteed by the network card that potentially results in corrupted data being returned by RDMA reads.
A common approach 
for 
addressing this challenge is using the one-sided shared-exclusive latch along with RDMA atomic operations.  Research suggests that RDMA atomic operations may suffer from low performance, and has proposed optimizations, e.g.,  versioning and checksum  <cit.> to resolve the read-write conflicts optimistically. However, recent study <cit.> revisits these optimizations, and indicates that some of those optimizations are problematic. It concludes that the one-sided shared-exclusive latch turns out to be the most efficient and reliable solution for ensuring RDMA access atomicity. However, the proposed shared exclusive latch is still a prototype with unresolved challenges, 

e.g.,
latch upgrade/downgrade and latch fairness. 

Its performance

is yet to be 
verified in a real disaggregated setup, e.g., in a disaggregated index or a disaggregated transaction engine. 



Challenge 2: Cache coherence among multiple compute nodes.
Given that the latency for RDMA is approximately 10 times 
slower
than main-memory access, minimizing RDMA round-trips in the critical paths of transactions becomes essential. Compute-side caching is an effective solution to reduce  RDMA round trips by leveraging  locality, but it introduces the cache coherence problem among the multiple participating compute nodes. 
Existing cache coherence protocols over RDMA, 

e.g.,
GAM <cit.> and 
the 
lock fusion module in PolarDB-MP <cit.>

use remote procedure calls (RPC), relying on the computing power of the memory nodes. 

These protocols 

become
bottlenecked by the limited computing power when applied to stranded memory.
In addition, some index studies simplify the cache coherence problem by only caching the metadata of a data structure (e.g., the internal nodes of a B-tree, the hash directory) <cit.>, but these caches are constrained in size, and are not adaptable to the size of available local memory. Furthermore, the implementation of metadata caching strongly depends on the specific data structure, limiting its generalizability. Therefore, there is significant need for a generative cache coherence protocol that eliminates the need for computing over remote memory.




















The need for a proper abstraction layer.


In realizing databases over disaggregated memory, existing academic research 

focuses only  on  specific data structures or algorithms.
Integrating these research outcomes into a unified DB system is challenging due to their heterogeneous, inefficient, and even unsafe designs in addressing the data synchronization problems.

In addition to 
optimizing individual data structures and algorithms, 

it is important to 

establish a high-performance and generative disaggregated memory abstraction layer that effectively addresses the two aformentioned technical challenges underneath. 

Subsequently, applications,  

e.g.,
indexes and transaction engines, can be built on top of this layer.







The advantages of an abstraction layer over disaggregated memory are threefold: (1) It conceals the complexity of RDMA programming from developers. (2) It prevents developers from implementing intuitive yet problematic optimizations for data synchronization. As highlighted in <cit.>, guaranteeing the correctness of RDMA synchronization requires expertise in RDMA programming. (3) It manages various types of data, including data tables and indexes, within a unified cache framework, thereby simplifying the regulation of local memory for compute-side caching.
Existing abstraction layers over distributed shared memory (e.g., FaRM <cit.>, NAM <cit.>, GAM <cit.>) either do not leverage local caches to explore data locality or rely heavily on the computing power of the memory nodes.















Our approach.
This paper presents Shared-Exclusive Latch based Cache Coherence protocol (SELCC), an innovative solution for data synchronization problem over disaggregated shared memory.




By introducing lazy latch release and invalidation messages, the one-sided RDMA shared-exclusive latch protocol can be upgraded to address the cache coherence problem with sequential consistency. 
This unified protocol effectively guarantees RDMA access atomicity and cache coherence simultaneously, 

minimizing the RDMA round trips incurred when addressing data synchronization problems. Compared with the RPC-based solutions, SELCC does not involve any computing on the remote memory and potentially reduces RDMA round trips by converting two send-and-reply RDMA messages into one combined one-sided RDMA operation when fetching the data from disaggregated memory. To optimize performance, SELCC protocol embeds
cache directory entries into RDMA latch words and prioritizes local concurrency control over global concurrency control. Additionally, 

SELCC enhances the fairness of the RDMA spin latch protocol by attaching priority into invalidation messages. We implement the SELCC protocol within lightweight LRU caches on the compute nodes, establishing an efficient disaggregated memory abstraction layer. SELCC provides main-memory-like APIs to upper-level applications, facilitating the migration of data structures and algorithms and achieving performance comparable to 

competitors optimized for the disaggregated shared memory 

(More elaboration in these issues in  <ref> and <ref>).






























Contributions. This paper makes several key contributions: (1) It introduces SELCC, an upgraded one-sided RDMA latch protocol that simultaneously resolves the RDMA access atomicity and cache coherence issues. 


(2) It envisions an innovative approach to support multi-primary design via  disaggregated shared memory. Compared to the data synchronization approach in PolarDB-MP,  SELCC frees remote memory from performing computing during data synchronization, and thus making remote memory more suitable for stranded memory disaggregation. 



(3) This paper instantiates the SELCC protocol into 
an abstraction layer that provides main-memory-like APIs. It facilitates the seamless migration of data structures and algorithms from local memory to disaggregated memory, and thus, simplifying  database systems research and development over disaggregated shared memory. 


(4) It presents a thorough experimental study of SELCC, demonstrating its performance benefits, and identifying its favorable workload patterns.






§ BACKGROUND















RDMA Technology.  Remote Direct Memory Access (RDMA) is a high-speed inter-memory communication method with low latency. It allows direct access to the memory of a remote node <cit.>. RDMA bypasses the host operating system when transferring data to avoid extra data copy. RDMA's kernel-bypassing and low-latency features make it applicable to high-performance data centers <cit.>.

ibverbs is a C++ library for RDMA programming that provides low-level implementation of RDMA primitives. There are five types of primitives in ibverbs: RDMA send, RDMA receive, RDMA write, RDMA read, and RDMA atomic <cit.>. The memory buffer involved in the RDMA primitives needs to be registered into the RDMA network card in advance by .


RDMA write and RDMA read are one-sided RDMA primitives that directly access the remote server's memory without involving the remote server's CPU. Two-sided RDMA primitives (including RDMA send and RDMA receive) involve both sides of the compute and memory servers. 
RDMA atomic 

includes
two primitives:  () and  (). These primitives ensure the atomicity of a group of operations on data of at most 8 bytes. Additionally,  and  can be leveraged to implement shared-exclusive latch over RDMA (SEL), guaranteeing atomicity among RDMA reads and writes <cit.>. 






Cache-Coherence Protocols.
Cache coherence is a concept in multiprocessor systems ensuring that multiple copies of data in various CPU caches remain consistent <cit.>. In traditional multiprocessor systems,  consistency is ensured via hardware-level cache-coherence protocols. However, in the context of disaggregated memory systems, 

these
hardware-level protocols are not present. Consequently, a software-level cache-coherence mechanism becomes necessary when local caches are deployed in compute nodes.

Although quorum-based protocols, e.g., <cit.>, can maintain strong data consistency, they are primarily designed for data replication rather than data caching. These protocols broadcast messages to all compute nodes for every read and write, which contradicts the fundamental principle of caching: minimizing network access by exploring data locality. Consequently, they are not the optimal solution for the cache coherence problem in disaggregated memory. 

An effective approach to addressing  cache coherence should follow the methods used in multiprocessor systems.  Cache coherence protocols, e.g., MSI, MESI, and MOESI <cit.> in multiprocessor systems maintain cache consistency by tracking the state of each memory block and enforcing rules for read and write operations. These protocols fall into two primary categories based on how compute nodes are informed of operations from other processors: snoop-based protocols and directory-based protocols. 
Snoop-based protocols monitor a common bus to detect whether a cache block is being read or written by another processor, while directory-based protocols utilize a directory to keep track of which caches have copies of each memory block, sending messages only to the processors with valid cache copies.















§ SYSTEM OVERVIEW






In the proposed abstraction layer, all compute nodes share the same disaggregated memory space,  provided by a group of memory servers. Data within this space can be addressed using an 8-byte global pointer (NodeID, offset), where NodeID is the unique identifier of the memory server and offset specifies the memory offset inside the server.  Compute nodes interact with  remote memory via compute-side caching, leveraging access locality to minimize unnecessary RDMA round trips.

As in Figure <ref>, the disaggregated memory space is divided into blocks of configurable sizes, referred to as Global Cache Lines (GCLs). GCL serves as the fundamental data manipulation unit between the compute and memory nodes and comprises 3 components: A one-sided global latch word, a user-defined header, and the data region. The global latch word (8 bytes) is a crucial element, ensuring one-sided RDMA access atomicity and cache coherence. 

The user-defined header is an application-specific header, similar to  page headers in traditional databases. Finally, the data region stores data objects,

e.g.,
tuples for data tables and key-value pairs for indexes.










SELCC exposes a straightforward interface to upper-level applications (See Table <ref>).
Users can allocate or deallocate global cache lines by calling . Each data access is conducted via the local cache, and is protected by an SELCC latch that consists of a hierarchical data structure containing a local latch in the cache entry and a global latch in the remote memory. 

The acquisition of a SELCC latch () ensures that both the local and global latch are obtained, thereby guaranteeing access atomicity and cache coherence across compute nodes. Upon acquisition, the API returns a cache handle pointing to the local copy of the target GCL. The release of the SELCC latch () ensures the immediate release of the local latch while deferring the release of the global latch until another compute node accesses the same GCL. Additionally, SELCC provides APIs for global atomic operations that can be utilized to generate global timestamps or sequential numbers.
This layer of abstraction allows 

users to disregard the intricacies of RDMA programming.  Many data structures and algorithms 

for 
monolithic servers can be migrated onto SELCC seamlessly ( <ref>), as the RDMA access atomicity and cache coherence problem has already been resolved underneath the abstraction. 











§ THE SELCC PROTOCOL


In this section, we

introduce the SELCC Protocol; 
Shared-Exclusive Latch-based Cache Coherence protocol (SELCC), addressing the two fundamental issues over disaggregated shared memory: (1) Cache coherence across compute-side caches in the compute nodes, and (2) Atomicity for concurrent RDMA read and write operations. The main idea is to upgrade the existing shared-exclusive latch protocol (SEL) to solve the cache coherence problem. 

SELCC
follows the design principle of disaggregated memory to use one-sided RDMA solely for data transfer between the compute and memory layers while allowing two-sided RDMA for communication among the compute nodes. 

This principle ensures high scalability, as the protocol does not rely on the computing power of the memory nodes. Furthermore, 

SELCC adheres
to design guidelines <cit.> that ensure  correctness and efficiency of RDMA programming.















 §.§ Main Idea





The SELCC protocol is developed based on the one-sided shared-exclusive latch protocol (SEL)

that 
ensures RDMA access atomicity <cit.>. To address the cache-coherence problem, we draw inspiration from the MSI protocol <cit.>, a cache coherence protocol for multi-processor systems. MSI maintains cache-entry states, and employs a state machine to ensure the freshness of data reads and writes. In Figure <ref>, the MSI protocol comprises 3 states: Modified, Shared, and Invalid, with state transitions triggered by local processor read and write (PrRd and PrWr) operations, or by bus messages from other processors (BusRd, BusWr, or BusUpgr). Cache coherence is maintained as long as the cache state adheres to the state machine depicted in Figure <ref>c.




Interestingly, we observe that the states of the MSI protocol have similar semantic meanings to those of the SEL protocol. In SEL protocol, the Exclusive state implies a locally modified copy, the Shared state denotes a locally shared copy, and the Latch Off states represents that the local copy is invalid. However, the conditions for state machine transitions differ. The compute node eagerly releases the RDMA latch once local access is complete, resulting in invalidated data copies immediately,


whereas MSI invalidates cache states lazily upon receiving bus signals from the other processors. By representing cache states with latch states and aligning the SEL protocol's state machine with that of the MSI protocol, the cache coherence problem can be resolved.


To achieve the state machine alignment, SELCC introduces the concept of lazy latch release and the invalidation messages (PeerRd, PeerWr, PeerUpgr) in Figure <ref>b among compute servers. An invalidation message is issued when a compute node fails to acquire the global latch. Compute nodes do not immediately release the latch after completing the access; instead, they defer latch release until receiving an invalidation message from a peer compute node or until the cache entry is being evicted. Consequently, SELCC's state machine mirrors that of the MSI protocol, as in Figures <ref>b and <ref>c. When a compute node successfully acquires the latch, it stores the fetched copy in the local cache, and uses latch states to represent corresponding cache states. 


























 
 
 
 





















 §.§ Distributing Cache Directory into Latch Words

With lazy latch release, when a compute node accesses disaggregated memory that is latched by other nodes, invalidation messages must be sent to those nodes. The biggest challenge 

is how to determine the target server to send the invalidation message efficiently.
Broadcasting messages for every operation would exhaust network bandwidth. Thus, a cache directory is essential on the disaggregated memory to track the status of each global cache line, including the cache state and cache copy holder IDs.

However, maintaining 

this
directory in disaggregated memory is challenging, particularly when no extra RDMA round trip is expected.  

Observe
that traditional a one-sided RDMA latch does not fully utilize the 64 bits of the latch word. Thus, it is feasible to distribute and embed the cache directory entries into the RDMA latch words of the global cache lines (see Figure <ref>). The benefits of this approach are twofold: (1) No additional RDMA round trips are introduced to maintain the cache directory, and (2) The atomicity of directory changes is naturally ensured. When a compute node fails to find a valid cache entry in local cache, it 

attempts
to acquire the latch by RDMA atomic operations. If  lock acquisition fails, the compute node can acquire the server IDs of the current cache copy holders through the RDMA atomic operation's return, enabling the determination of invalidation message recipients.






In Figure <ref>, a latch word consists of 64 bits; the maximum data length supported by an RDMA atomic operation. We divide these 64 bits into two parts: (1) An exclusive latch holder's ID (8 bits), and (2) A reader holders' ID bitmap (56 bits). With this new latch word structure, the RDMA latch can record both shared and exclusive latch holder IDs. This protocol can support up to 56 compute nodes, exceeding the 32 compute nodes typically supported by modern cloud-native databases <cit.>. With multi-cores  on each compute node, a system using SELCC can support thousands of cores.














 §.§ Revisiting RDMA Latch Procedures

As the latch data structure has been changed  in SELCC, it is necessary to revisit the procedures for acquiring and releasing RDMA shared-exclusive latches.
This subsection illustrates the steps for acquiring and releasing  shared-exclusive latches using the new proposed latch structure. 

Initially, the global latch is off, represented by (0, 0b00...0). Each reader or writer in the compute nodes must acquire the global latch, read the cache line in a single combined RDMA round trip, and then access the data locally.

(a) Exclusive latch acquisition. 
When acquiring the exclusive latch, the writer atomically compares the entire latch word against the value (0, 0b00...0) and swaps it with (NodeID, 0b00...0)

If the  fails, the latch word before the operation is returned to the compute node, from which the compute node parses the shared/exclusive latch holders' IDs, and sends the invalidation messages. This procedure is repeated until the  succeeds.


(b) Shared latch acquisition. When acquiring the shared latch, readers atomically fetch the value of the latch word, and sets its bitmap by value (1 << NodeID) via . The reader checks the return of the  to see whether there is a writer holding the latch. If so, the latch acquisition 

fails.
It sends an invalidation message according to the returned exclusive latch holder ID, and resets its bit in the bitmap by another .   
These procedures  are repeated until the  return implies that no exclusive latch holder exists.

(c) Shared/exclusive latch release.
In SELCC, global latches are not released until an invalidation occurs or the cache entry is evicted from the cache. RDMA latch release is handled by background threads dedicated to processing invalidation messages. When releasing the exclusive latch, the compute node atomically fetches and subtracts the latch word by (NodeID, 0b00...0). We do not 

adopt
the method in <cit.> for releasing the exclusive latch via , as write releases could spuriously fail due to concurrent read lock operations, resulting in livelock. When releasing the reader latch, the compute node resets its bit in the bitmap via .


(d) Latch up/downgrading.
According to the state machine in Figure <ref>, the exclusive latch may need to be downgraded to a shared latch based on an invalidation message from a peer reader. To achieve this, the compute node atomically compares and swaps the latch words from (NodeID, 0b0000) to (0, 1 << NodeID). Conversely, the compute node may need to upgrade its local latch from a shared to an exclusive latch. To achieve this, the compute node first attempts to atomically compare and swap the latch words from (0, 1 << NodeID) to (NodeID, 0b0000). However, a deadlock could occur if two nodes try to upgrade the same global latch simultaneously. To resolve this, after several attempts of atomic upgrade, upgrading the latch falls back to a two-step process consisting of shared latch release and exclusive latch acquisition.




§ OPTIMIZATIONS









We instantiate the SELCC protocol into the compute-side cache over the disaggregated memory, 

creating a high-performance abstraction layer. The local cache is a lightweight hash table with LRU replacement policy and is sharded to support highly concurrent local access. Even though the SELCC protocol can theoretically address the cache coherence problem, 

several implementation challenges remain for its instantiation: (1) Efficiently implementing invalidation messages across compute nodes, (2) Coordinating local concurrency control and global concurrency control efficiently, given that each compute node can support many local threads concurrently accessing the local cache, (3) Avoiding latch starvation to maintain fairness among the compute nodes.



 §.§ Efficient Invalidation Messages



Invalidation messages play an crucial role in the SELCC protocol. Poor design can result in slow or blocked read/write over the shared data. Invalidation messages are realized by RPC through RDMA, and contains information,

e.g.,
the global address of the target Global Cache Line (GCL) and  type of invalidation message (PeerWr, PeerRd or PeerUpgr). Note that the RPC only exists between compute servers, while the communication between compute and memory servers is purely one-sided.
Each pair of compute nodes is interconnected via a limited number of RDMA queue pairs. 
Whenever a thread fails to acquire the global latch for a cache line, it issues invalidation messages to prompt the current latch holders to release the latch (shared/exclusive) and write back any dirty data if applicable.
These messages are handled by background threads, 

termed 
RPC handlers, on the receiver side that release the global latch on behalf of the sender.   Before releasing the global latch, the background threads acquire the local latch to synchronize with local accessors. Invalidation messages may be dropped by the RPC handlers if the cached entry has already been invalidated by other compute nodes or if the target cache line has already been evicted. Therefore, a resending mechanism for invalidation message is necessary to address message dropping.

Efficiently processing invalidation messages involves three main challenges: (1) Preventing RPC handling threads from being blocked that can lead to blocked reads and writes at the sender if the local read/write thread holds the local latch for too long; (2) Avoiding excessive resending messages that could saturate network bandwidth; and (3) Ensuring that each message is processed only once, as duplicate processing of invalidation messages can reduce cache hit rates and overload the invalidation message handler.


To address the first challenge, the invalidation message handler uses  to acquire the local latch before processing messages. The  function is non-blocking, ensuring that the RPC handler is never blocked. If the  fails, the handler drops the message, and processes the next one.  
To prevent network saturation from excessive resending of messages, there is a time interval T between each resend,  inversely related to the total number of global latch retries. During the interval between resending messages, the message sender retries the global latch to obtain the latest information on the valid cache copies, and adjusts the targets for the next invalidation messages accordingly.
To guarantee the messages being processed at most once, each invalidation message is assigned a unique ID (cache line ID + cache line version), allowing the handler to verify if the message has already been processed.















 §.§ Coordinating 2-Level Concurrency Control






The next challenge is efficiently coordinating concurrency control between local and global accesses.
This complexity arises from the two-level hierarchy, as illustrated in Figure <ref>.  The first level, local concurrency control, resolves access conflicts 

within a single compute node using local latches. The second level, global concurrency control, addresses RDMA conflicts on global cache lines among compute nodes using global latches. 
The hierarchical concurrency control design aims to minimize RDMA network traffic by effectively leveraging local concurrency control. RDMA network traffic primarily stems from two sources: RDMA lock acquisition and invalidation messages.

As  in <cit.>, RDMA atomic operations encounter bottlenecks under highly contended workloads. To mitigate the network traffic associated with RDMA lock acquisition, we utilize the local cache to store not only the cache line but also the global cache states (Modified, Shared, or Invalid) that correspond to the global latch state. This enables local threads to verify both data freshness and the global latch state through the local cache entry. Moreover, a local shared-exclusive mutex is installed on each cache entry to ensure the atomicity of local read and write operations. This approach,  in Figure <ref>, reduces RDMA round trips on the global latch by resolving the conflicts locally.




To prevent network bandwidth saturation from excessive invalidation messages, we optimize the protocol for its worst-case scenario.
A cache coherence protocol could perform poorly under highly skewed workloads due to the large volume of invalidation messages exchanged among compute nodes. To address this issue, we prioritize local concurrency control over global concurrency control, ensuring that conflicts within the same compute node are resolved by local latches first. 

To achieve this, the invalidation message handling threads use "" to acquire the latch for the cache entry. 
Since  fails immediately when there is a conflict, rather than waiting as a normal  operation, the invalidation message handler has a lower priority in acquiring the local latch compared to the front-end accessors.

As in Figure <ref>, this approach can significantly reduce the number of invalidation messages for accessing the same data. 
However, prioritizing local access over global access can potentially prevent invalidation messages from taking effect under highly skewed workloads, potentially lead to global starvation on other compute nodes. The solution to this starvation problem is presented in  <ref>.













 §.§ Fairness of One-Sided RDMA Latches



Fairness is a significant challenge for the SELCC protocol, as it is based on a shared-exclusive spinlock. The read and write latency on a particular server can become extremely long if that server experiences starvation during latch acquisition. In monolithic servers, the latch fairness problem is often addressed by maintaining a FIFO queue for each latch. However, in the context of disaggregated memory, maintaining such a queue without incurring extra RDMA round trips is extremely difficult. A new efficient mechanism is required to enhance  latch fairness over disaggregated memory.  This section starts from the root causes of latch starvation over SELCC, and proposes the 

relevant 
solutions accordingly. Due to the two-level hierarchy of the system, two root causes of latch starvation can be identified, each requiring distinct resolution techniques.





Root Cause 1: Asymmetric Local Latch Acquisition. As stated in  <ref>,  
to minimize the volume of invalidation messages traffic, local front-end accessors have higher priority than invalidation message handlers when acquiring the local latch. 
A compute node can experience global latch starvation for a particular data object if a peer compute node with a valid copy continuously receives local access requests from multiple threads for that data object. In this scenario, the local accessors continuously hold the local latch, causing the invalidation message handler's  requests to fail continuously, leading to global latch starvation. This type of starvation, caused by the asymmetric chances of acquiring the local latch between local front-end accessors and background invalidation message handlers, can be resolved through a lease mechanism on local latch within a single compute node.





Root Cause 2: Asymmetric Global Latch Acquisition. It is not necessary to have symmetric hardware configurations across all the compute nodes. Consequently, some compute nodes with weak CPU or network resources may experience latch starvation due to the low frequency of RDMA latch retries. Additionally, if there are continuous global read requests for a particular data object, a write request for that data object may struggle to acquire the exclusive latch because peer compute nodes continuously hold the shared latch, preventing the writer from obtaining the exclusive latch. These types of starvation, stemming from asymmetric chances of acquiring the global latch among multiple compute nodes, require an effective global coordination mechanism among multiple compute nodes to resolve.










  §.§.§ Addressing Local Latch Starvation


To address local latch starvation, we implement a lease mechanism that forces the compute node to release the global latch when a data object has been continuously accessed by local front-end threads for an extended period. 
To interrupt these continuous local accesses at an appropriate time, two counters, the read access counter (R_c) and the write access counter (W_c), are maintained in each cache entry. These counters are activated only when an invalidation message is dropped due to the ongoing local access and is deactivated when a thread acquires the latch without spinning, indicating that the data is no longer heavily accessed.
The counters are incremented by 1 when a local access waits for the latch. Synthetic access times for the cache entry are calculated by 

H_times = R_c/P + W_c, where P represents the number of front-end threads on the compute node. When the synthetic access times exceed a predefined threshold θ, the local thread proactively release the global latch and reset the counters.













  §.§.§ Addressing Global Latch Starvation


To address global latch starvation, we adopt a priority aging mechanism, originally devised to solve the starvation problem in CPU scheduling <cit.>. In SELCC, each latch is assigned a priority that is positively correlated to the number of retries a compute node has conducted for a particular RDMA latch.

The main idea is to ensure that global latch ownership is always handed over to the compute node with the highest latch priority. To achieve this, we implement 3 mechanisms. First, as stated in  <ref>, there is a manually injected time interval between each latch retry for a particular latch. This interval decreases as the priority of latch acquisition increases. Thus, compute servers having prolonged wait times are more likely to successfully acquire the latch through more frequent latch retries.





Second, we develop a deterministic global latch handover mechanism based on latch priority. The exclusive latch holder, receiving invalidation messages from all conflicted servers, acts as a centralized decision-maker for global latch ownership transfer. The latch acquisition priority is attached to the invalidation message, providing the exclusive latch holder with information on which compute node is experiencing latch starvation. During the continuous local access  (Sec. <ref>), the invalidation message handler keeps receiving invalidation messages from other compute nodes, and stores the message with the highest priority value in the cache entry. When releasing the global latch,

the invalidation handler thread checks the stored invalidation messages in the cache entry. If there is a stored invalidation message from Server B with a priority greater than that the others, it will deliberately handover the latch from Server A to Server B by conducting RDMA CAS onto the latch word (Compare:(A, 0b00...0), Swap: (B, 0b00...0). 

After the deterministic latch ownership transfer, Server A clears the stored invalidation message, and resets all relevant states in the cache entry.

Finally, to prevent the write starvation caused by continuous global reads, all global readers  create a time window during which no concurrent reader holds the target shared latch, allowing the concurrent writer to acquire the exclusive latch.

To realize this, when 

latch starvation 
is
detected, we 

inject a spinning wait between the forced shared latch release and the next shared latch acquisition on the same data object. The spin duration is designed as T_spin = P_inv× T_r, where P_inv is the priority level of the received invalidation message and T_r is the time elapse of RDMA round trips. 

































§ READ AND WRITE SUPPORT OVER SELCC










As outlined in  <ref>, data access over SELCC is protected by the SELCC latch. Before conducting  write or read operations on the GCL in local cache, the accessors have to acquire the SELCC latch via the  APIs to get access permission. After completing the access, the thread must release the corresponding SELCC latch via the  APIs to allow other accessors,  local or global, to access the GCL. SELCC latches refer not only to the RDMA latch in disaggregated memory, but also to the local latch in the compute-side cache. The interactions among the local caches and the remote RDMA latches are complex and need of further illustration. 
In this section, we detail the procedures behind the SELCC APIs to  explain the read and write operations.

























 §.§ Reads with SELCC_SLock










Algorithm <ref> illustrates the procedure for acquiring the SELCC shared Latch. 

First, the algorithm searches  local cache for the entry corresponding to gaddr, and retrieves the handle h (Line 2). If h is not null, the local shared latch on the cache entry is acquired (Line 4). Then, we check the global latch state of the cache entry (Line 5). If the state is either Shared or Exclusive, indicating a cache hit, the handle is returned (Line 6).
If the cache entry is not found, a new cache entry is created and inserted into the local cache (Line 8), and the local shared latch is acquired (Line 9).
If the cache entry is invalid or not found, we try to acquire the shared latch on the global cache line via RDMA in a loop (Lines 10-13). This involves issuing an combined RDMA request with CAS and read operations, and check the operation returned to verify whether the GCL has been exclusively latched by another compute node. If so, the algorithm sends invalidation messages to the current exclusive latch holder. This process repeats until the shared latch is successfully acquired, after which the handle to the cache entry is returned.









 §.§ Writes with SELCC_XLock










Algorithm <ref> outlines the procedure for acquiring the SELCC exclusive latch (SELCC_XLock). Similar to SELCC_SLock, the global address is  searched in the local cache (Line 2). If a valid entry is found with global exclusive state, the handle is returned (Line 6). Else, the exclusive global latch must be acquired or upgraded from the shared global latch. To upgrade the shared latch, the accessor uses RDMA CAS to attempt an atomic upgrade the latch from  shared to exclusive. This attempt may fail if there are shared copies in other compute nodes. Moreover, there is potential deadlock if there is another concurrent accessor trying at the same time to upgrade its SELCC shared latch to be exclusive.
To handle potential deadlocks, the procedure (Lines 8-13) is repeated up to 
N  times (N ≥ 2). If deadlock is detected, we abandon the atomicity of latch upgrade, and falls back to a two-step process: Releasing the shared latch (Line 14), and then acquiring the exclusive latch (Lines 18-21). If the cache entry is found invalid, the valid state is re-acquired by obtaining the global exclusive latch (Lines 18-21). If the cache entry is missed, a new entry is created, and both the local and global latches are acquired before returning the handle (Lines 16-21).

























 §.§ Unlocking SELCC Read and Write Locks

After completing the access, the SELCC latch must be released. The unlatching procedure involves two steps. First, the cache entry handle is released, indicating that the cache entry is ready for eviction. Second, the local latch in the cache entry is released, allowing other threads or the invalidation message handler to operate on this cache line. Notably, the global latch remains unchanged due to the lazy release mechanism.






























§ SELCC'S CONSISTENCY MODEL













SELCC guarantees the strongest achievable consistency level, sequential consistency. 

Every compute node should observe operations from different compute nodes in the same sequential order <cit.>. 


Sequential consistency is essential for a generative cache framework because many applications, 

e.g.,
banking and financial services, rely on strong consistency to provide reliable and accurate services to users. 



















The primary reason for SELCC achieving sequential consistency 

is its latch-based design with eager invalidation. The latch acquired before reads or writes, serves as a barrier between operations, preventing read-write reordering within a thread. Eager invalidation ensures that before a compute node modifies  data in the disaggregated memory, it must invalidate all cache copies. This forces all subsequent reads to fetch the latest data from the disaggregated memory. This mechanism guarantees that all compute nodes can observe a write simultaneously when the writer releases the SELCC exclusive latch.




Consequently, there is a total order of writes observed by all compute nodes, determined by the moment the writer releases the SELCC exclusive latch.
As  in Figure <ref>, there are four updates to the disaggregated shared memory occurring from left to right in chronological order. The total order of the operations is (X = 1 → Y = 1 → Y = 2 → X = 2) that is determined by the moment the disaggregated memory completes the RDMA latch release. This is different from the real order of write operations (Y = 1 → X = 1 → X = 2 → Y = 2) on the timeline.  
No reader thread can observe values to 
X and Y that violate the sequential order determined by the moment of RDMA latch release. 

















































































 By default, SELCC guarantees strong consistency. It is feasible to relax the consistency of SELCC for improved performance. For instance, we can relax the read-write ordering by enabling asynchronous writes. Instead of completing the exclusive latch acquisition and sending invalidation messages for each write operation, the writer can push the modified value and the target global cache line ID into a work request queue, and let dedicated background threads perform the write operations in FIFO order. 

This approach results in a protocol with FIFO consistency <cit.>, enhancing performance by allowing asynchronous execution of writes.




§ APPLICATIONS OVER SELCC






As  in  <ref>, SELCC provides a main-memory-like programming model/API for users to develop data structures and algorithms using pessimistic concurrency control. SELCC APIs do not support optimistic concurrency control, as it is less reliable in terms of correctness (See <cit.> Consideration #3 Pessimistic synchronization is more “future proof”). Below, we demonstrate  how to re-implement two of the most crucial database components: indexes and transaction engines, 

using SELCC APIs.



















 §.§ Index Support over SELCC

Migrating the index from a monolithic server over SELCC involves two main steps. The first step is organizing the basic data structure into Global Cache Lines (GCL). For data structures that already organize multiple data objects into blocks, e.g., B-trees, R-trees, ART trees, and hash tables, this process is simplified by aligning the node structures onto GCL. In cases where the original data structure is in-memory and does not organize multiple data objects into blocks (e.g., skip lists), there are two options: Reorganizing multiple data objects into blocks based on their locality, or adjusting the global cache line size to match a single data object. The former approach minimizes space overhead, while the latter requires no code modifications. The second step involves replacing local shared-exclusive latches in the algorithm with .  SELCC  ensures  both read-write atomicity and cache coherence globally. A concurrent B-link tree is reimplemented. In  <ref>, we compare   its performance  with optimized B-trees over disaggregated shared memory; Sherman <cit.> and DEX <cit.>.








 §.§ Transaction Support over SELCC








Migrating concurrency control algorithms from a monolithic server to SELCC involves three primary steps. First, tuples should be properly organized into GCLs. Second, local shared-exclusive latches are replaced with SELCC_XLock / SELCC_SLock locks. Finally, algorithms that require monolithic timestamps utilize  provided by SELCC API to perform RDMA Fetch-and-Add (FAA) operations on a global timestamp generator to obtain monotonically increasing timestamps. 
Three types of algorithms have been implemented over SELCC: two-phase locking with no wait strategy (2PL), timestamp ordering (TO), and optimistic concurrency control (OCC). Tuples are organized in a heap style, meaning they are placed in GCLs by the chronological order of insertion. To ensure atomicity of tuple accesses, these accesses must be protected by   locks.

For two-phase locking, SELCC latches on the GCLs are reused for locking purposes, minimizing the RDMA round trips required by the transaction concurrency control. To support durability in disaggregated memory, durable storage media is leveraged for write-ahead logging. Since all transactions are executed within the same compute node via RDMA,  transaction support over SELCC does not require two-phase commit protocols.












§ EVALUATION

Overview. 

First, we run micro-benchmarks to show the scalability and performance benefits of SELCC as a cache coherence protocol ( <ref>). Second, we use the YCSB benchmark to explore how 

the index over SELCC performs compared to the state-of-the-art btrees over disaggregated memory ( <ref>). Third, We use the TPC-C benchmark to study how the transaction engines over SELCC perform under OLTP workloads ( <ref>).










Testbed.  Experiments are conducted on a cluster of 16 nodes in Cloudlab <cit.>. The chosen instance type is c6220 that features two Xeon E5-2650v2 processors (8 cores each, 2.6GHz) and 64GB (8GB × 8) of memory per node. The cluster is interconnected using 56 Gbps Mellanox ConnectX-3 FDR Network devices. Each server runs Ubuntu 18.04.1, and the NICs are driven by Mellanox OFED-4.9-0.1.7.
The 16 servers are split into 8 compute servers and 8 memory servers. The compute servers can utilize all the CPU cores but have a limited local cache (8GB by default). The memory agents on the memory servers have access to all the memory but are restricted to utilizing a limited number of CPU cores (1 core by default).


















 §.§ Micro-benchmark





First, we evaluate the scalability of SELCC as an abstraction layer supporting multiple primary servers, and then demonstrate the advantages of  SELCC  as a cache coherence protocol.



Baselines. 
To show the efficiency of SELCC, we compare SELCC against two abstraction layers over disaggregated memory.


The first baseline is GAM, an RPC-based cache coherence protocol designed for distributed shared memory. 




We test GAM with different consistency models: total store order consistency and sequential consistency, corresponding to GAM (TSO) and GAM (SEQ) in the figures.

A notable RPC-based cache coherence protocol is the lock-fusion model in PolarDB MP. GAM can roughly represent its performance with limited remote compute power.
The second baseline is SEL, a one-sided access framework that operates without compute-side caching. While it employs the SELCC protocol to ensure RDMA access atomicity, it circumvents the cache coherence problem by disabling caching. SEL shares the same APIs as SELCC, allowing applications developed for SELCC to run seamlessly on SEL. 












Benchmarks. We test the competitors by the micro-benchmark tool that allows for adjustments in sharing ratios, read/write ratios, data skewness and access locality. 

In this micro-benchmark, each compute server issues 16 million accesses over 24 million allocated Global Cache Lines (48GB in total). 

The overall throughput with different read ratios, 100% (Read only), 95% (Read intensive), 50% (Write intensive), 0% (Write only) are tested.





  §.§.§ Evaluating the Scalability of SELCC


To evaluate the scalability of the SELCC protocol, we conduct a benchmark test under a uniformly distributed workload while varying the number of compute nodes.



To avoid 

bottlenecks due to memory nodes' RDMA bandwidth, 

we scale the number of memory nodes in proportion to the number of compute nodes. Each compute node executes 16 local threads.

We compare SELCC under 

various
sharing ratios (sr), following the methodology in <cit.>. The sharing ratio (sr) indicates the percentage of allocated data accessible by all compute nodes, while the remainder is accessed privately. When the sharing ratio is zero, the system essentially operates as a sharding-based system over disaggregated memory.







Experimental results are given in Figure <ref>. The point values represent the overall throughput while the bar values indicate the proportion of operations requiring invalidation messages in the 100% shared case.
For the read-only and read-intensive workloads, SELCC demonstrates strong scalability regardless of the sharing ratio, 

as there is very little cache coherence overhead introduced in the system. SELCC with 100% sharing ratio exhibits slightly super-linear scalability under read-only workloads, because the increased number of memory node results in less NIC Translation Buffer (TLB) misses. For write-intensive and write-only workloads, SELCC scalability   deteriorates with increased shared data ratio and larger local cache sizes (Figure <ref> c and d). The reason is that a higher shared data ratio and larger cache size increase the likelihood of two compute nodes caching the same data, resulting in a higher volume of invalidation messages. Compared to the fully partitioned SELCC (0% shared ratio), the fully shared SELCC (100% shared) shows a 16.0%/14.3% (8GB cache) and 38.3%/36.0% (16GB cache) performance degradation at 8 nodes in write-intensive and write-only workloads, respectively. 

This performance degradation mainly results from the invalidation messages for cache coherence. 

Despite the overhead from maintaining cache coherence, SELCC still shows good scalability under write-intensive workloads. Compared to the single compute node deployment, the eight-node SELCC increases throughput by 6.67×/6.85×/(8GB cache) and 4.96×/4.77×(16GB cache) corresponding to the write-intensive and write-only workloads.









  §.§.§ Workloads with Access Locality 






To illustrate  performance benefits of SELCC under workloads with access locality, we conduct a uniformly distributed micro-benchmark with 50% locality, where each operation has a 50% probability of accessing the same GCL as the previous one. The benchmark is executed with 8 compute nodes fully sharing data, using varying numbers of threads per node. Scalability becomes sub-linear between 64 and 128 threads due to the saturation of the ConnectX-3 NIC's network bandwidth.



Compared with SEL, due to the local cache, SELCC shows significant performance gains in read-intensive and read-only  workloads (Figures <ref>a and <ref>b), with improvements of 1.68× and 2.18× at 128 threads, respectively. 

However, the performance advantage of SELCC diminishes in write-intensive and write-only workloads (Figure <ref>c), where about 35%/33% of operations require invalidation messages and remote dirty page reads, reducing the local cache's effectiveness. 



Compared with GAM (TSO) and GAM (SEQ), SELCC demonstrates superior performance across all four read ratios, achieving 3.60×/3.48×, 2.85×/3.41×, 5.12×/5.61×, and 3.63×/4.08× the throughput, respectively.

GAM exhibits limited thread scalability, especially in write-only and write-intensive workloads with a high number of compute-side threads (Figures <ref>c and <ref>d). This bottleneck primarily results from  overloading the computing resource in the memory nodes.







  §.§.§ Workloads with Access Skewness 



To illustrate the performance benefits of SELCC under a workload with access skewness, we run the micro-benchmark with a Zipfian distribution. The skewness parameter, θ, 

is set to
0.99, with no access locality applied. Other parameters 

are
configured 

in the same way as that of the previous subsection.


For read-intensive and read-only workloads, SELCC exhibits significant performance gains, achieving throughput 5.89×/5.40× over that of SEL at 128 threads. These gains result from the high cache hit ratios (60.6% and 84.4%, respectively) of skewed workloads. 

However, for write-intensive and write-only workloads, SEL shows better performance than SELCC initially when thread count 

is
low,


as SELCC suffers from a large number of invalidation messages triggered by the data hotspot.


As the thread count increases, SEL experiences significant performance degradation (over 7× in write-intensive workloads),

primarily due to the high contention in RDMA atomic operations over the data hotspot. In contrast, SELCC demonstrates better thread scalability, as the conflicts are resolved in the local cache first.


Finally, SELCC outperforms GAM(TSO) and GAM(SEQ) by 2.13×/8.23×, 1.96×/5.00×, 4.11×/2.57×, and 13.15×/4.04× for workloads with 128 threads, highlighting the superiority of SELCC as a cache coherence protocol over disaggregated shared memory. 

































 §.§ Evaluating Index Performance over SELCC



Although the micro-benchmark demonstrates the performance benefits of SELCC under certain workload patterns, it does not accurately represent the real-world workload that an application using SELCC would encounter. We construct an index following the methodology outlined in  <ref>, and evaluate its performance using 

YCSB <cit.>. 






Baselines. Three B-tree baselines are evaluated in this experiment. The first baseline is the B-tree over SEL, following the same methodology as the B-tree over SELCC. The second baseline is Sherman, an optimized index over disaggregated shared memory. We address the correctness issues in Sherman's optimistic synchronization following <cit.>. The final baseline is DEX, a sharding-based B-tree over disaggregated memory. Unlike the other shared-memory baselines, DEX employs a sharding mechanism to bypass the cache coherence problem. 




Benchmarks & Configurations. We benchmark the indexes using YCSB, following methodologies established in the existing literature <cit.>. Each index is loaded with 50 million key-value records and tested under varying read ratios and data skewness (θ = 0.99). The experiments are conducted over 8 compute nodes, with 8 threads per node. The local cache of SELCC is set to 128MB. 




  §.§.§ Results



Uniform Workload. The b-tree over SELCC outperforms that over SEL by factors of 3.75×/4.09×/5.92×/6.28×, respectively (See Figure <ref>a). Unlike the results  in the micro-benchmark, the high performance advantage of SELCC over SEL persists even in the write-intensive workload because most of the internal nodes are cached immutable. Compared to Sherman, the b-tree over SELCC outperforms Sherman in read-intensive and read-only workloads by 1.79× and 1.89×, respectively, because Sherman's optimistic synchronization requires one more RDMA round trip than the pessimistic synchronization used in  SELCC. Finally, the b-tree over SELCC slightly loses to DEX under uniform workloads. This result is expected, as the sharding mechanism in DEX fully bypasses the cache coherence problem and includes many index-specific optimizations, whereas 

the
b-tree over SELCC serves as a demonstration without data structure-dependent optimizations.




Skewed Workload. 


The
B-tree over SELCC outperforms both SEL and Sherman by factors of 11.0×/9.89×/3.22×/11.86× and 3.07×/1.70×/1.16×/4.44×, respectively, because the local cache in SELCC can hold most of the hot data. The B-tree over SEL has very limited performance under skewed workloads due to the excessive RDMA round trips required for traversing the tree. Sherman exhibits weaker performance than the B-tree over SELCC, because its leaf nodes cannot be cached locally, resulting in high RDMA atomic traffic contention over the hot spots. In contrast, SELCC can mitigate this traffic by pre-resolving conflicts in the local cache. DEX demonstrates extremely fast performance as it completely avoids concurrency control and caches data locally. B-tree over SELCC outperforms DEX by 1.18× when handling read-only workloads, as the data hot spots can be effectively managed by all eight compute nodes.

While DEX shows superior performance as a key-value store, it has limitations when serving as an index component in a full-fledged multi-primary database due to the overhead of cross-shard transactions (See  <ref>).











 §.§ Evaluating Transaction Support over SELCC



We construct a transactional engine using various representative concurrency control algorithms: two-phase locking (2PL) with no-wait deadlock-avoidance strategy, timestamp ordering (TO), and optimistic concurrency control (OCC), following the methodology described in  <ref>. Additionally, we build a 2 Phase Commit (2PC) engine over partitioned SELCC. We evaluate the performance of transaction engines using the TPC-C benchmark.



Baselines.
First, we build transaction engines over the SEL abstraction layer to explore the benefits of SELCC over SEL under OLTP workloads.
Second, we construct a distributed transaction engine with 2 Phase Commit over partitioned SELCC. By comparing the performance of fully-shared SELCC against partitioned SELCC, we aim to demonstrate the advantages of fully-shared SELCC for bypassing the two-phase commit (2PC) protocol.


Benchmark & Configuration.
A database is loaded with 256 warehouses, occupying approximately 64GB of disaggregated memory. The benchmark suite includes five queries: three update queries (Q1, Q2, and Q4) and two read queries (Q3 and Q5) [The order of Q1-Q5 corresponds to the sequence of queries introduced in the TPC-C specification <cit.>.]. The experiment is conducted in two parts. First, we evaluate SELCC against SEL using the three concurrency control algorithms, with all data fully-shared. The five queries are first evaluated individually, and then are evaluated in an evenly mixed manner. Write-ahead logging is disabled to clearly highlight performance discrepancies. In the second part, we compare fully-shared SELCC against partitioned SELCC using the same database setup. The transaction concurrency control algorithm is set to 2PL, and write-ahead logging is enabled to fully demonstrate the overhead of the 2-Phase Commit protocol.







  §.§.§ Results

SELCC vs. SEL. As  in Figure <ref>, concurrency control algorithms over SELCC offer significant performance benefits compared to those over SEL when handling workloads generated by TPC-C. SELCC achieves up to 28.2× throughput with read queries, 6.12× with update queries, and 3.39× in mixed scenarios.
SELCC maintains a considerable advantage over SEL even for update queries, because there are still numerous reads on immutable data (e.g., index traversal and reading immutable tables).

Additionally, the performance of concurrency control algorithms varies when dealing with different queries. TO algorithm over SELCC exhibits poor performance in read-only queries (Q3 and Q5) because read operations require updating the read timestamp, resulting in cache invalidation. However, TO outperforms the 2PL algorithm in update queries due to its lower abort rate.




OCC generally shows slower performance than 2PL because it requires acquiring the SELCC latch for the GCL twice per tuple—once during the read phase and again during the invalidate phase that results in a higher volume of cache invalidation messages.

Fully-shared vs. Partitioned. For partitioned SELCC, we partition the data according to warehouse IDs. Q1 and Q2 are evaluated with varying distribution ratios, representing the percentage of cross-shard transactions. As  in Figure <ref>, partitioned SELCC outperforms fully-shared SELCC when the distribution ratio is 0. The gap between fully-shared and partitioned SELCC is not apparent primarily due to slow log flush onto hard disk,

shifting the bottleneck from RDMA access to disk writes. This gap will be more significant given high-speed durable devices, e.g., persistent memory. However, as the number of cross-shard transactions increases, the performance of partitioned SELCC decreases significantly. This decline is primarily due to communication overhead and, more importantly, the excessive disk synchronization required for both the prepared and commit stages, which heavily consumes disk bandwidth. In contrast, the fully-shared SELCC that bypasses the two-phase commit (2PC) protocol, remains unaffected by the distribution ratio.














§ RELATED WORK

Abstraction layers over distributed shared memory.
Abstraction layers and unified memory models over distributed shared memory have long been a focus of research <cit.>. Traditionally, network latency has been a significant issue, leading many systems to install local caches with relaxed consistency models to mitigate network costs <cit.>. Recently, advancements in networking technologies, e.g., RDMA <cit.> and programmable switches <cit.>, have revitalized interest in distributed shared memory, enabling stronger consistency models for local caching. However, the interaction between local servers and remote memory relies on RPC-based communication that can saturate the limited computing resources on disaggregated memory, particularly for systems built on stranded memory.
In addition, many abstraction layers (e.g., FaRM <cit.>, NAM <cit.>) leverage one-sided RDMA as the primary method to transfer data between the local servers and the remote memory. Due to the complexity of maintaining cache coherence without RPC, these systems  do not apply compute-side caching to exploit data locality. The SELCC protocol addresses this gap by providing a cache coherence protocol with zero computing involvement on the memory node. 


Database systems techniques over disaggregated memory.
Approaches to database research over disaggregated memory differ significantly between academia and industry. Academic research focuses on redesigning specific database components, e.g., indexes <cit.> and transaction concurrency control algorithms <cit.> over the disaggregated memory. SELCC converges the individual DB component research tracks by providing a layer of abstraction.
In contrast, industry, 

e.g.,
PolarDB of Alibaba, conducts research in  full-fledged system support over disaggregated memory <cit.>. PolarDB migrates the buffer pool onto disaggregated memory, achieving higher cache hit ratio <cit.>, instant failure recovery <cit.>, elasticity resource provisioning <cit.>, and multiple primary nodes <cit.>. 






























CXL-based disaggregated memory

CXL is an emerging technology addressing resource disaggregation from a hardware perspective <cit.>. In the context of CXL 3.0, cache coherence among compute servers will be guaranteed at the hardware level <cit.>. However, the CPU cache is limited in size and is manipulated in small granularity (64 Bytes). Frequent updates over a large memory region could trigger too many invalidation signals and remote memory access over the CXL network. Therefore, it is still beneficial to implement software-level cache in near memory with larger cache line granularity to reduce overhead over CXL networks. In these scenarios, the latch protocol over the CXL-based disaggregated memory can still be upgraded to guarantee  cache coherence among CXL-enabled disaggregated memory and the software-level cache in local memory. 

























§ CONCLUDING REMARKS

This paper addresses a longstanding challenge for database systems over disaggregated memory: maintaining cache coherence without involving remote computing power. SELCC provides a disaggregated memory abstraction that facilitates further research in various areas, including data structures, transaction concurrency control, and multi-primary buffer management. 
Additionally, the SELCC protocol can be leveraged by cloud-native DBs to achieve multi-primary designs.



§ ACKNOWLEDGEMENTS

Walid Aref acknowledges the support of the National Science Foundation under Grant Number IIS-1910216.
Jianguo Wang acknowledges the support of the National Science Foundation under Grant Number IIS-2337806.






ACM-Reference-Format


