TierBase: A Workload-Driven Cost-Optimized Key-Value Store
Extracted source text · arXiv 2505.06556
% !TEX program = pdflatex
\pdfoutput=1
% VLDB template version of 2020-08-03 enhances the ACM template, version 1.7.0:
% https://www.acm.org/publications/proceedings-template
% The ACM Latex guide provides further information about the ACM template
\documentclass[sigconf, nonacm]{acmart}
%% The following content must be adapted for the final version
% paper-specific
\newcommand\vldbdoi{XX.XX/XXX.XX}
\newcommand\vldbpages{XXX-XXX}
% issue-specific
\newcommand\vldbvolume{14}
\newcommand\vldbissue{1}
\newcommand\vldbyear{2020}
% should be fine as it is
\newcommand\vldbauthors{\authors}
\newcommand\vldbtitle{\shorttitle}
% leave empty if no availability url should be set
\newcommand\vldbavailabilityurl{URL_TO_YOUR_ARTIFACTS}
% whether page numbers should be shown or not, use 'plain' for review versions, 'empty' for camera ready
\newcommand\vldbpagestyle{plain}
\usepackage{algorithmic}
\usepackage{graphicx}
\usepackage{textcomp}
\usepackage{xcolor}
\usepackage{multirow}
\usepackage{pgfplots}
\usepackage{tikz}
\usepackage{lipsum}
\usepackage{float}
\usepackage{pgfplotstable}
\usepgfplotslibrary{groupplots}
\usepackage{multirow}
\usepackage{tabularx}
\usepackage{subfigure}
\usepackage{graphicx}
\usepackage{textcomp}
\usepackage{color}
\usepackage{listings}
\usepackage{booktabs}
\usepackage{makecell}
\usepackage{balance}
\usetikzlibrary{patterns}
\usepackage{tikz}
\usepackage{pgfplots}
% \usepackage{pgfplotstable} % 如果需要
\usetikzlibrary{patterns}
% \usepackage{graphicx} % 如果需要
\usepackage{multirow}
\usepackage{graphicx} % 这是为了使用 \resizebox
%\usepackage{array} % 这是为了使用 m{...}
% \usepackage{subcaption} % Required for creating subfigures
\usepackage{svg} %矢量图
\usepackage{multirow}
\usepackage[normalem]{ulem}
\useunder{\uline}{\ul}{}
\usepackage{array}
%\usepackage{titlesec}
\usepackage{pgfplots}
\usepackage{subcaption}
\pgfplotsset{compat=1.17}
\usepackage{caption}
\usepackage{adjustbox}
\usepackage{calc}
\usepackage{multirow}
\usepackage{algorithm}
% \usepackage{algpseudocode}
%reduce caption distance to figure
\usepackage[font=small,skip=0pt]{caption}
\captionsetup{belowskip=-12pt}
% reduce space before item
\usepackage{enumitem}
\setlist[itemize]{noitemsep, topsep=2pt}
\usepackage{amsmath} % 确保加载 amsmath 包
\DeclareMathOperator*{\argmin}{arg\,min} % 定义 \argmin
% 设置pgfplots为兼容模式,确保与旧版本的兼容性
\pgfplotsset{compat=1.16} % 请根据你的pgfplots版本进行调整
\usetikzlibrary{patterns}
\definecolor{c1}{RGB}{42,99,172} %
\definecolor{c2}{RGB}{255,88,93}
\definecolor{c3}{RGB}{255,181,73}
\definecolor{c4}{RGB}{119,71,64} %
\definecolor{c5}{RGB}{228,123,121} %
\definecolor{c6}{RGB}{208,167,39} %
% \definecolor{c6}{RGB}{136,88,180}
\definecolor{c7}{RGB}{0,51,153}
\definecolor{c8}{RGB}{56,140,139} % Fast2D
\definecolor{c9}{RGB}{0,0,0} %black
%底色
\definecolor{color1}{HTML}{FFF4D8}
\definecolor{color2}{HTML}{FF7163}
%标记颜色
\definecolor{Blood}{HTML}{860309}
\definecolor{Olive}{HTML}{807805}
\definecolor{Topaz}{HTML}{F5C678}
\definecolor{American Yellow}{HTML}{F3AA07}
\definecolor{Giants Orange}{HTML}{FF5C1E}
\definecolor{Persian Plum}{HTML}{6C1D2A}
\definecolor{Pearl Aqua}{HTML}{85D6B2}
\definecolor{Moonstone}{HTML}{3F9EBD}
\definecolor{Blue Jeans}{HTML}{5BBCF0}
\definecolor{St. Patrick's Blue}{HTML}{2B2D7C}
\definecolor{Green}{HTML}{159879}
\definecolor{Green2}{HTML}{31D683}
\definecolor{Purple}{HTML}{C1689C}
% 983B7B
% FF58AF
\pgfdeclarepatternformonly{myCrossHatch}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{3pt}{3pt}}{\pgfqpoint{4pt}{4pt}}%
{
\pgfsetlinewidth{1pt} % 增加线条粗细
\pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
\pgfpathlineto{\pgfqpoint{4pt}{4pt}}
\pgfpathmoveto{\pgfqpoint{4pt}{0pt}}
\pgfpathlineto{\pgfqpoint{0pt}{4pt}}
\pgfusepath{stroke}
}
\pgfdeclarepatternformonly{myDots}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{2.5pt}{2.5pt}}{\pgfqpoint{2.5pt}{2.5pt}}%
{
\pgfpathcircle{\pgfqpoint{1pt}{0.8pt}}{0.8pt} % 圆点大小
\pgfusepath{fill}
}
\pgfdeclarepatternformonly{myDenseLines}{\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{2pt}{2pt}}{\pgfqpoint{1.8pt}{1.8pt}}%
{
\pgfsetlinewidth{1pt} % 设置线条粗细
\pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
\pgfpathlineto{\pgfqpoint{4pt}{4pt}}
\pgfusepath{stroke}
}
\pgfdeclarepatternformonly{myDenseLines2}{\pgfqpoint{0pt}{0pt}}{\pgfqpoint{10pt}{10pt}}{\pgfqpoint{10pt}{10pt}}%
{
\pgfsetlinewidth{0.5pt} % 设置线条粗细
\pgfpathmoveto{\pgfqpoint{0pt}{2pt}}
\pgfpathlineto{\pgfqpoint{10pt}{10pt}}
\pgfusepath{stroke}
}
\pgfdeclarepatternformonly{myContinuousLine}{\pgfqpoint{-2pt}{-2pt}}{\pgfqpoint{4pt}{4pt}}{\pgfqpoint{2pt}{2pt}}%
{
\pgfsetlinewidth{1pt} % 设置线条粗细
\pgfpathmoveto{\pgfqpoint{-2pt}{-2pt}}
\pgfpathlineto{\pgfqpoint{6pt}{6pt}}
\pgfusepath{stroke}
}
% \newcommand{\tbase}{ \textit{TierBase}}
\newcommand{\tbase}{TierBase }
\newcommand{\tbased}{data instance }
\newcommand{\note}{\textcolor{blue}{note }}
\newcommand{\sstitle}[1]{\vspace{0ex} \noindent\underline{{\it #1}}}
\newcommand{\cost}{ \textit{XXX}}
\theoremstyle{definition}
\newtheorem{definition}{Definition}
\def\BibTeX{{\rm B\kern-.05em{\sc i\kern-.025em b}\kern-.08em
T\kern-.1667em\lower.7ex\hbox{E}\kern-.125emX}}
\begin{document}
\title{ TierBase: A Workload-Driven Cost-Optimized Key-Value Store [Extended Version] }
%%
%% The "author" command and its associated commands are used to define the authors and their affiliations.
\author{
Zhitao Shen$^{\dagger}$, Shiyu Yang$^{\S}$, Weibo Chen$^{\S \dagger }$, Kunming Wang$^{\S \dagger}$, Yue Li$^{\dagger}$, Jiabao Jin$^{\dagger}$, Wei Jia$^{\dagger}$, Junwei Chen$^{\dagger}$, Yuan Su$^{\dagger}$, Xiaoxia Duan$^{\dagger}$, Wei Chen$^{\dagger}$, Lei Wang$^{\dagger}$, Jie Song$^{\dagger}$, Ruoyi Ruan$^{\dagger}$, Xuemin Lin$^{\ddagger}$ \\
}
\renewcommand{\shortauthors}{Shen et al.}
\affiliation{$^\dagger$Ant Group ; ~ $^\S$Guangzhou University ; ~ $^{\ddagger}$ Shanghai Jiao Tong University}
\affiliation{ \{zhitao.szt,~ chenweibo.cwb,~ wangkunming.wkm,~ ly321766,~ jinjiabao.jjb, ~ jw94525,~ weisong.cjw,~ stevensu.sy,~ \\
xiaoxia.dxx,~ cw281808,~ wl177541,~ peter.sj,~ ruoyi.ruanry\}@antgroup.com; syyang@gzhu.edu.cn; xuemin.lin@sjtu.edu.cn}
%%
%% The abstract is a short summary of the work to be presented in the
%% article.
\input{abstract}
\maketitle
%%% do not modify the following VLDB block %%
%%% VLDB block start %%%
% \pagestyle{\vldbpagestyle}
% \begingroup\small\noindent\raggedright\textbf{PVLDB Reference Format:}\\
% Shen etl. \vldbtitle. PVLDB, \vldbvolume(\vldbissue): \vldbpages, \vldbyear.\\
% \href{https://doi.org/\vldbdoi}{doi:\vldbdoi}
% \endgroup
\begingroup
\renewcommand\thefootnote{}\footnote{\noindent
%This work is licensed under the Creative Commons BY-NC-ND 4.0 International License. Visit \url{https://creativecommons.org/licenses/by-nc-nd/4.0/} to view a copy of this license. For any use beyond those covered by this license, obtain permission by emailing \href{mailto:info@vldb.org}{info@vldb.org}. Copyright is held by the owner/author(s). Publication rights licensed to the VLDB Endowment. \\
%\raggedright Proceedings of the VLDB Endowment, Vol. \vldbvolume, No. \vldbissue\ %
%ISSN 2150-8097. \\
%\href{https://doi.org/\vldbdoi}{doi:\vldbdoi} \\
}\addtocounter{footnote}{-1}\endgroup
%%% VLDB block end %%%
%%% do not modify the following VLDB block %%
%%% VLDB block start %%%
% \ifdefempty{\vldbavailabilityurl}{}{
% \vspace{.3cm}
% \begingroup\small\noindent\raggedright\textbf{PVLDB Artifact Availability:}\\
% The source code, data, and/or other artifacts have been made available at \url{\vldbavailabilityurl}.
% \endgroup
% }
%%% VLDB block end %%%
\input{intro}
%\input{architecture}
\input{costmodel-part1}
\input{overview}
\input{features}
%\input{costmodel}
\input{costmodel-part2}
\input{evaluation}
\input{related}
\input{conclusion}
%\clearpage
\bibliographystyle{plain} %ACM-Reference-Format
\bibliography{references}
\end{document}
\endinput
\begin{abstract}
In the current era of data-intensive applications, the demand for high-performance, cost-effective storage solutions is paramount. This paper introduces a Space-Performance Cost Model for key-value store, designed to guide cost-effective storage configuration decisions. The model quantifies the trade-offs between performance and storage costs, providing a framework for optimizing resource allocation in large-scale data serving environments. Guided by this cost model, we present TierBase, a distributed key-value store developed by Ant Group that optimizes total cost by strategically synchronizing data between cache and storage tiers, maximizing resource utilization and effectively handling skewed workloads. To enhance cost-efficiency, TierBase incorporates several optimization techniques, including pre-trained data compression, elastic threading mechanisms, and the utilization of persistent memory. We detail TierBase's architecture, key components, and the implementation of cost optimization strategies. Extensive evaluations using both synthetic benchmarks and real-world workloads demonstrate TierBase's superior cost-effectiveness compared to existing solutions. Furthermore, case studies from Ant Group's production environments showcase TierBase's ability to achieve up to 62\% cost reduction in primary scenarios, highlighting its practical impact in large-scale online data serving.
\end{abstract}
\section{Introduction}
In the current era of data-intensive applications, the demand for high-performance, cost-effective storage solutions is paramount. Key-value store, with their promise of scalability, flexibility, and rapid data access, have emerged as a pivotal component in this landscape. Renowned key-value stores such as Redis \cite{redis}, Memcached \cite{memcached}, Cassandra \cite{Cassandra}, and HBase \cite{hadoop} have set industry benchmarks, offering solutions designed for diverse use cases ranging from in-memory caching to persistent storage.
At Ant Group, we face numerous challenges in managing our online data serving systems. These challenges stem from the intrinsic nature of our services and the evolving demands of our vast user base. We handle \textbf{\textit{the immense volume of data}} generated by billions of users, necessitating robust, low-latency, and cost-effective storage solutions. The diverse scenarios and applications lead to \textbf{\textit{a wide spectrum of workloads}} with varying needs for reliability, durability, and latency. Additionally, \textbf{\textit{significant skewness in data access patterns}}, with dynamically changing hot spots, complicates data access and caching strategies.
Furthermore, in order to handle these workloads, we have to maintain an extremely large number of machines, which leads to a \textbf{\textit{non-trivial configuration decision}} challenge. This challenge demands a cost model to accurately quantify the cost-performance trade-offs.
To address these challenges, we introduce TierBase, a distributed key-value store developed by Ant Group since 2017. Initially Redis-compatible, TierBase has evolved to support advanced functions such as CAS operations, wide-columns, and vector searching. Extensively utilized within Ant Group, TierBase maintains sub-millisecond access latency even under peak loads of hundreds of millions of queries per second (QPS), crucial for delivering seamless user experiences during events like the Double 11 shopping festival.
\begin{figure}[t]
\centering
\begin{tikzpicture}[scale=0.6]
\begin{axis}[
width=14cm, % 设置图的宽度
height=5cm, % 设置图的高度
bar width=5cm, % 柱的宽度
ymin=0,
ymax=1.1, % y轴最大值
bar width=0.8cm, % 柱的宽度
% enlarge x limits=0.3, % 增加x轴的宽度
ylabel={Normalized Cost}, % y轴标签
symbolic x coords={TierBase-Raw, TierBase-PMem, TierBase-PBC, TierBase-wb-5X, TierBase-wt-5X}, % x轴类别
xtick=data, % 根据数据生成x轴刻度
legend style={at={(0.5,0.8)}, anchor=south,legend columns=-1}, % 图例位置
ymajorgrids=true, % y轴网格线
ylabel style={font=\Large},
xlabel style={font=\huge},
x tick label style={font=\large, rotate=10, xshift=-5pt}, %
y tick label style={font=\large}, % 增大y轴刻度标签字体
grid style=dashed,
tick style={draw=none} % 去掉x和y轴上的刻度
]
% 绘制柱状图 SC
\addplot[ybar, fill=Giants Orange, bar shift=-0.4cm, area legend, opacity=0.6] coordinates {
(TierBase-Raw, 1.0) (TierBase-PMem, 0.695421468) (TierBase-PBC, 0.403577926) (TierBase-wb-5X, 0.21573681) (TierBase-wt-5X, 0.11552456)};
\addlegendentry{SC}
% 绘制柱状图 PC
\addplot[ybar, fill=Blue Jeans, bar shift=0.4cm, area legend, opacity=0.6] coordinates {
(TierBase-Raw, 0.0693208) (TierBase-PMem, 0.080181928) (TierBase-PBC, 0.122255913) (TierBase-wb-5X, 0.196112796) (TierBase-wt-5X, 0.206943602)};
\addlegendentry{PC}
% 叠加折线图 Cost
\addplot[Green2, line width=2pt, mark=*] coordinates {
(TierBase-Raw, 1.0) (TierBase-PMem, 0.695421468) (TierBase-PBC, 0.403577926) (TierBase-wb-5X, 0.21573681) (TierBase-wt-5X, 0.206943602)};
\addlegendentry{Cost}
\end{axis}
\end{tikzpicture}
\caption{Cost comparison in TierBase}
\label{totalcost}
\end{figure}
To optimize costs further, we developed several cost-saving strategies within TierBase. Figure \ref{totalcost} illustrates the cost-performance trade-offs and the impact of these optimization techniques in a real-world use case. The figure shows how enabling our cost-saving strategies leads to reductions in both space cost ($SC$) and performance cost ($PC$), which represent storage and query processing expenses, respectively. In our cost model, the overall cost is defined as the maximum of $SC$ and $PC$, represented by the green line in the figure. Despite the increase in $PC$, the significant reduction in $SC$ results in an overall cost decrease. Our pre-trained compression technique (TierBase-PBC) achieves up to a 62\% cost reduction over the baseline (TierBase-Raw), demonstrating substantial savings in one of our primary online serving scenarios.
In developing TierBase, we focus on two key questions:
\noindent \textbf{Q1: How can we develop a comprehensive cost model for large-scale online data serving systems that adapts to varying workloads?}
Developing a comprehensive cost model for complex online data serving systems requires identifying key metrics that accurately capture real-world costs across various workloads. Traditional models \cite{tco,10.5555/1287369.1287387} typically focus on overall system costs without considering specific workload characteristics. The challenge lies in developing a quantitative framework that accurately models cost-performance trade-offs between different storage configurations while incorporating workload-specific characteristics and capturing the non-linear relationship between system configuration and cost.
\noindent \textbf{Q2: How can we effectively evaluate and apply optimization techniques in key-value stores to balance performance and cost for specific workloads?}
The research and industry communities have developed a number of innovative techniques \cite{SlimCache,riak} to optimize performance and storage efficiency for key-value stores. However, they are often workload-specific, and there is no universal solution. The challenge lies in developing a unified framework to evaluate and apply these diverse optimization techniques across different workloads considering both performance metrics and overall system cost. This cost model aims to enable informed decisions about which techniques to apply in different scenarios, moving beyond one-size-fits-all solutions towards a workload-aware optimization strategy for key-value stores.
To answer these questions, in this paper, we introduce:
\noindent\textbf{Space-Performance Cost Model}: A novel approach balances performance and space costs, proposing that optimal cost is achieved when these factors are equal. This model extends to tiered storage systems, incorporating cache ratios and miss ratios to determine cost-effectiveness.
\noindent\textbf{TierBase}: Guided by this cost model, TierBase employs a tiered storage architecture that balances performance and storage space for cost-efficiency. It incorporates innovative features such as a flexible design for handling diverse workloads, pre-trained data compression techniques, elastic threading mechanisms, and utilization of persistent memory.
\noindent\textbf{Cost Optimization Framework}: We introduce a framework for evaluating and optimizing costs for key-value stores. This framework includes strategies for adapting to diverse workloads and provides guidelines for making cost-effective decisions in system configuration and resource allocation.
To sum up, the main contributions are as follows:
\begin{itemize}
\item We propose a comprehensive Space-Performance Cost Model for key-value store that aligns with and extends the classic Five-Minute Rule, guiding decisions on optimal storage configuration selection.
\item We present the architecture of TierBase, a distributed key-value store that leverages a tiered storage design to effectively balance performance and cost-efficiency across diverse workloads.
\item We introduce and evaluate several cost-optimizing techniques implemented in TierBase, including pre-trained data compression, elastic threading mechanisms, and the utilization of persistent memory.
\item We demonstrate the effectiveness of our cost optimization framework through extensive evaluations using synthetic benchmarks, real-world workloads, and case studies from Ant Group's production environments. These evaluations showcase TierBase's superior cost-effectiveness compared to existing solutions and its ability to achieve significant cost reductions in large-scale, data-intensive applications.
\end{itemize}
\section{Space-performance Cost Modeling}\label{sec:cost_model}
In this section, we introduce a novel cost model for key-value storage systems, based on real-world implementations at Ant Group. Our model unifies performance and storage costs, providing a comprehensive framework for system optimization in online data serving with real-time latency requirements.
\begin{figure}[t]
\centering
\subfigure[Single-Tier Storage]{
\centering
\includegraphics[scale=0.29]{figures/costmodel_final1.pdf}
\label{fig:cost-model1}
}
\hspace{-0.2cm}
\subfigure[Tiered Storage]{
\centering
\includegraphics[scale=0.29]{figures/costmodel_final2.pdf}
\label{fig:cost-model2}
}
\caption{Space-Performance Cost Model}
\label{fig:cost-model}
\end{figure}
% \vspace{1pt}
\subsection{Cost Analysis Framework}
Our framework is built upon two primary components:
\noindent\textbf{Performance Cost ($PC$)} in key-value storage systems reflects the expenses associated with data transfer from storage media to end-users, encompassing resource utilization for both read and write operations. This includes CPU overhead, network I/O, disk IOPS consumption, and memory bandwidth usage.
\noindent\textbf{Space Cost ($SC$)} depends on the resources and expenses for data storage, varying by storage medium and space used. In caching and in-memory storage, it's linked to the data volume in RAM, which is fast but expensive. Disk-based storage costs are typically cheaper for large data volumes. These costs also account for storage overhead related to data structures and replicas necessary to ensure reliability and availability.
\noindent\textbf{Space-Performance Cost Model.}
Our Space-Performance Cost Model is based on the observation that in enterprise data centers and cloud environments, resource instances (virtual machines or containers with compute and storage resources) are typically provided with pre-defined allocations. These allocations are usually evenly divided to maximize utilization, precluding arbitrary resource allocation.
Given this constraint, for a given workload $w$, which is a stream of read and write operations on a given resource instance $i$ and storage system with configuration $s$, both the maximum performance ($MaxPerf(w,i,s)$) and the maximum storable data amount ($MaxSpace(w,i,s)$) are deterministic and quantifiable. These metrics are measured in queries per second (QPS) and gigabytes (GB), respectively.
In a distributed, shared-nothing architecture, we define the monetary cost $C$ as the maximum of the performance cost ($PC$) and the space cost ($SC$) for a given workload on a set of resource instances $i$ with the same configuration:
\begin{definition}[Cost of workload $w$]
The cost of workload $w$ is defined as the maximum of the performance cost and the space cost for a given workload on a set of resource instances $i$ with a specific storage configuration $s$:
\begin{equation}
C(w, i, s) = \max(PC(w, i, s), SC(w, i, s))
\end{equation}
Where:
\begin{align*}
PC(w, i, s) &= Cost(i) \times \left\lceil \frac{QPS(w)}{MaxPerf(w, i, s)} \right\rceil \\
SC(w, i, s) &= Cost(i) \times \left\lceil \frac{DataSize(w)}{MaxSpace(w, i, s)} \right\rceil
\end{align*}
Here, $Cost(i)$ is the monetary cost of a single resource instance $i$, $QPS(w)$ is the total queries per second for the workload $w$, $DataSize(w)$ is the total amount of data to be stored for workload $w$, and $MaxPerf(w, i, s)$ and $MaxSpace(w, i, s)$ are the maximum performance and space capacity for the given resource instance $i$ and storage configuration $s$, respectively.
\end{definition}
In a distributed, shared-nothing architecture, the maximum of the performance cost and space cost is used because the system must be provisioned to meet the greater of the two demands: query processing or data storage. This ensures that sufficient resources are allocated to handle the workload's heaviest requirement, whether it's the query throughput or the data volume.
For real-world deployments, we incorporate tolerance ratios for both $MaxPerf$ and $MaxSpace$, ensuring system redundancy and reliability. These ratios accommodate variations in workload distribution and access patterns, enabling adaptation to scenarios that deviate from the cost model's assumption of even data sharding.
In Figure \ref{fig:cost-model1}, we illustrate both the performance and space costs. For workloads where the performance cost exceeds the space cost, we categorize them as \textit{performance-critical workloads}. Conversely, when the space cost is dominant, we refer to these as \textit{space-critical workloads}.
\subsection{Cost Efficiency Metrics}\label{sec:cost_mertrics}
Our cost model provides a framework for optimizing resource allocation and system configuration in distributed key-value storage systems. By leveraging the insights from this model, we can make informed decisions to minimize overall costs while meeting both performance and space requirements.
Consider a scenario where a workload typically requires multiple resource instances. We can simplify our model by removing the ceiling function and define the cost metrics as follows:
\begin{definition}[Cost Metrics]
We define two key cost metrics:
\begin{align*}
CPQPS &= Cost(i) / MaxPerf(w,i,s) \\
CPGB &= Cost(i) / MaxSpace(w,i,s)
\end{align*}
where CPQPS is the Cost per Query per Second, representing the performance cost incurred for processing each query per second, and CPGB is the Cost per GB, representing the space cost for storing each gigabyte of data.
\end{definition}
For ease of presentation in subsequent discussions, we will consider the same $i$ and $w$, allowing us to represent different configurations as subscripts in later formulae.
Using these cost metrics, we can express the total cost of the storage system as:
\begin{equation}
C = \max(CPQPS \times QPS, CPGB \times DataSize)
\end{equation}
This formulation allows us to evaluate and optimize the overall system cost by considering both performance and space requirements.
\subsection{Space-Performance Trade-off and Optimal Cost Theorem}
Our cost model reveals an inherent trade-off between performance and space costs in key-value storage systems. This trade-off forms the basis for our Optimal Cost Theorem.
\begin{definition}[Space-Performance Trade-off of Storage Configurations]
Given a set of storage configurations ${S}$, the space-performance trade-off describes the relationship between the Cost per Query per Second ($CPQPS$) and the Cost per Gigabyte ($CPGB$), expressed as: $CPQPS_s = f(CPGB_s), \quad s \in S$
where $f$ is a non-increasing function. As $CPGB_s$ decreases for a given configuration $s$, $CPQPS_s$ tends to increase, and vice versa.
\end{definition}
A typical example of this trade-off is data compression: for a fixed compression algorithm, setting higher compression levels reduces space cost ($CPGB$) but increases performance cost ($CPQPS$) due to added computational overhead, allowing a trade-off between storage efficiency and query performance.
Based on the trade-off, we establish the Optimal Cost Theorem:
\begin{theorem}[Optimal Cost $C^*$]
For a given workload $w$ with requirements $QPS$ and $DataSize$, and a set of storage configurations $S$, the optimal cost $C^*$ is achieved by selecting the configuration $s^* \in S$ that minimizes the overall cost while balancing performance and space costs:
$C^* = \min_{s \in S} \max(PC_{s}, SC_{s})$
The optimal configuration $s^*$ is one that minimizes the absolute difference between performance and space costs:
$s^* = \argmin_{s \in S} |PC_{s} - SC_{s}|$
\end{theorem}
\begin{proof}
Let $s^*$ be the optimal configuration that minimizes the overall cost:
$C^* = \min_{s \in S} \max(PC_s, SC_s)$
Assume, for contradiction, that $PC_{s^*} \neq SC_{s^*}$. Without loss of generality, let $PC_{s^*} > SC_{s^*}$. Then:
$C^* = PC_{s^*}$
Now, consider a configuration $s'$ that slightly reduces $PC_{s^*}$ at the expense of increasing $SC_{s^*}$, such that:
$PC_{s'} = PC_{s^*} - \epsilon$
$SC_{s'} = SC_{s^*} + \delta$
Where $\epsilon > 0$ and $\delta > 0$ are small positive values.
If we choose $\epsilon$ and $\delta$ such that $SC_{s^*} + \delta < PC_{s^*} - \epsilon$, then:
$\max(PC_{s'}, SC_{s'}) = PC_{s'} = PC_{s^*} - \epsilon < PC_{s^*} = C^*$
This contradicts the assumption that $s^*$ is the optimal configuration. Therefore, our initial assumption must be false, and we must have $PC_{s^*} = SC_{s^*}$ for the optimal configuration.
Hence, the optimal configuration $s^*$ is one that minimizes the absolute difference between performance and space costs:
$s^* = \argmin_{s \in S} |PC_s - SC_s|$
This proves both parts of the theorem.
\end{proof}
The proof demonstrates that any imbalance between performance and space costs can be optimized to yield a lower total cost, thus establishing the optimal point at their equality.
This theorem provides a guiding principle for optimizing key-value storage systems. It suggests that the most cost-effective configuration is one where the system's resources are balanced such that neither space nor performance costs dominate. This balance point represents the optimal trade-off between space and performance for the given workload.
\subsection{Cost Model with Tiered Storage}\label{cost_tired}
Tiered storage systems typically comprise two layers: a cache tier and a storage tier. The cache tier, often utilizing memory-based technologies, prioritizes performance, while the storage tier focuses on capacity and cost-effectiveness. This structure allows systems to balance performance and capacity requirements more efficiently than single-tier alternatives.
In a tiered storage system, the total cost is a function of both the cache tier and the storage tier. We propose a comprehensive cost model for tiered storage systems that accounts for both performance and capacity costs across tiers:
\begin{align}
C_{tiered} = \max(&PC_{cache}
+ PC_{miss}\times MR, \nonumber \\
&SC_{cache} \times CR) \nonumber \\
+ \max(&PC_{storage} \times MR, SC_{storage})
\label{eq:tiered_cost}
\end{align}
where:
\begin{itemize}
\item $CR$ is the cache ratio (cache capacity / total capacity)
\item $MR$ is the cache miss ratio (proportion of requests served by the storage tier)
\item $PC_{miss}$ is the additional performance cost incurred on a cache miss
\item $PC_{cache/storage}$ and $SC_{cache/storage}$ represent performance and space costs for each tier
\end{itemize}
This model enables a comparison between tiered storage and single-tier alternatives. Tiered storage becomes cost-effective when its total cost is lower than both a pure cache solution and a pure storage solution, expressed as: $C_{tiered} < \min(C_{cache}, C_{storage})$. This approach can be particularly effective for workloads with skewed data access patterns.
The model provides insights into optimizing cache ratio ($CR$) and managing miss ratio ($MR$) to minimize overall system cost. Further detailed cost analysis on tiered storage is presented in Section \ref{cost_analysis_tired_storage}.
\subsection{Cost Optimization Strategies}
Our cost model serves as a valuable guide for optimization efforts, assisting system designers and administrators in their decision-making process. We discuss optimization strategies for both single-tier and tiered storage systems, using the space-performance cost model as our framework.
\subsubsection{Single-Tier Storage Optimization}
In single-tier storage systems, the primary goal is to balance performance cost ($CPQPS$) and space cost ($CPGB$) to minimize overall cost. The optimization strategies depend on the workload characteristics:
\sstitle{Space-Critical Workloads}:
When the workload is space-critical. Here, reducing $CPGB$ becomes the primary goal.
One approach is to enable data compression, which reduces $CPGB$ but may increase $CPQPS$ due to the additional computational overhead. The overall cost can still be optimized through such trade-offs according to the Optimal Cost Theorem. Other potential approaches include using instance with larger storage and implementing tiered storage solutions.
\sstitle{Performance-Critical Workloads}: In this case, optimization efforts should focus on reducing $CPQPS$. Strategies may include:
Optimizing query execution, tiered caching mechanisms, and utilizing faster storage media for frequently accessed data.
\sstitle{Resource Instance Selection}:
Choosing the right type of resource instance can significantly impact both $CPQPS$ and $CPGB$. This involves analyzing different instance types to find the optimal balance between performance capabilities and storage space for the specific workload.
\subsubsection{Tiered Storage Optimization}
Tiered storage systems offer additional opportunities for cost optimization by leveraging the strengths of different storage tiers. The effectiveness of tiered storage depends on three key factors:
\sstitle{Skewed Data Access Pattern:}
Optimal tiered storage performance occurs when both Cache Ratio ($CR$) and Miss Ratio ($MR$) are low. This scenario is typical in workloads with high temporal locality, where a small subset of "hot" data is frequently accessed. The cache tier can store this data, resulting in a low $CR$ while serving most requests (low $MR$).
\sstitle{Cost Disparity between Tiers:}
The significant cost difference between cache and storage tiers is crucial for effective tiered storage. The cache tier offers high performance at a higher cost per unit capacity, while the storage tier provides lower performance at a much lower cost. This disparity allows the system to balance high performance for frequently accessed data with cost-effective storage for less accessed information.
\sstitle{Low Miss Penalty}:
The miss penalty ($PC_{miss}$) represents the additional performance cost when a request misses the cache. A low miss penalty is vital for effective tiered storage as it reduces the impact of cache misses, allowing for a smaller cache (lower $CR$) without significantly degrading overall performance. We will present our techniques for minimizing $PC_{miss}$ in Subsection \ref{sec:writethough_back}.
\subsubsection{Workload-Driven Optimization Approaches}
Instead of immediately diving into TierBase-specific techniques, we can introduce a more general framework for mapping workload characteristics to optimization strategies. This sets the stage for the detailed techniques that will be discussed in the following section.
Table \ref{tab:workload_optimization} presents a mapping of various workload features to optimization strategies implemented in TierBase. This mapping illustrates how specific workload characteristics inform the choice of optimization techniques.
% \begin{table}[h]
% \centering
% \caption{Workload Features and Corresponding TierBase Optimizations}
% \resizebox{\linewidth}{!}{
% \begin{tabular}{|p{0.25\textwidth}|p{0.19\textwidth}|}
% \hline
% \textbf{Workload Features} & \textbf{Optimization Technique} \\
% \hline
% \multirow{2}{*}{ \thead{Skewed access patterns \\ (a small subset of data accessed frequently)}} & \checkmark Tiered Storage \\
% & \checkmark Elastic Threading \\
% \hline
% \multirow{2}{*}{Low latency requirements} & \checkmark In Memory Mode \\
% & \checkmark PMem Usage \\
% \hline
% \multirow{3}{*}{Space-critical (Large volume, low throughput) } & \checkmark Larger Storage Instance \\ & \checkmark Tiered Storage \\
% & \checkmark Pre-trained Compression \\
% \hline
% \multirow{3}{*}{Performance-critical (High throughput, small volume)} & \checkmark In Memory Mode \\ &
% \checkmark PMem for Persistence \\
% \hline
% \multirow{2}{*}{Read-heavy, Write-less} & \checkmark Elastic Threading \\
% & \checkmark Pre-trained Compression \\
% \hline
% \multirow{2}{*}{Write-heavy} & \checkmark Write-back Caching \\
% & \checkmark PMem for WAL \\
% \hline
% \end{tabular}}
% \label{tab:workload_optimization}
% \end{table}
\begin{table}[]
\caption{Workload Features and Optimization Options}
\small
\begin{tabular}{c|c}
\hline
\textbf{Workload Features} & \textbf{Optimization Options} \\ \hline
\begin{tabular}[c]{@{}c@{}}Skewed access patterns \\ (a small subset of data accessed frequently)\end{tabular} & \begin{tabular}[c]{@{}c@{}}Tiered Storage\\ Elastic Threading\end{tabular} \\ \hline
Low latency requirements & \begin{tabular}[c]{@{}c@{}}In Memory Mode\\ PMem Usage\end{tabular} \\ \hline
\begin{tabular}[c]{@{}c@{}}Space-critical \\ (Large volume, low throughput)\end{tabular} & \begin{tabular}[c]{@{}c@{}}Larger Storage Instance\\ Tiered Storage\\ Pre-trained Compression\end{tabular} \\ \hline
\begin{tabular}[c]{@{}c@{}}Performance-critical \\ (High throughput, small volume)\end{tabular} & \begin{tabular}[c]{@{}c@{}}In Memory Mode\\ PMem for Persistence\end{tabular} \\ \hline
Read-heavy, Write-less & \begin{tabular}[c]{@{}c@{}}Elastic Threading\\ Pre-trained Compression\end{tabular} \\ \hline
Write-heavy & \begin{tabular}[c]{@{}c@{}}Write-back Caching\\ PMem for WAL\end{tabular} \\ \hline
\end{tabular}
\label{tab:workload_optimization}
\end{table}
These optimization techniques are designed to address specific workload characteristics and leverage the strengths of both single-tier and tiered storage architectures. By applying these strategies guided by our cost model, we can iteratively refine system configurations, resource allocations, and feature enablements.
In the following sections, we will detail each of these optimization techniques, explaining how they work and how they contribute to overall system cost-effectiveness. Later, in Section \ref{sec:exp}, we will demonstrate how these strategies are applied in practice. Our evaluation methodology involves replaying real-world workloads and assessing costs across various configurations, providing empirical validation of our cost-optimization approach.
%\vspace{-0.25cm}
\section{\tbase System Design}
\begin{figure*}[ht]
\centering
\includegraphics[width=0.8\textwidth]{figures/overview.pdf}
\caption{TierBase architecture overview}
\label{fig:overview}
\end{figure*}
Building upon our unified space-performance cost model, we present TierBase, a high-performance, distributed key-value storage system designed to optimize cost for large-volume online storage. TierBase leverages a tiered storage architecture to provide low-latency, cost-effective data access while addressing the challenges highlighted in our cost model.
TierBase extends Redis's capabilities by supporting not only basic key-value operations like GET and SET, but also advanced data structures such as lists, sets, and sorted sets. Additionally, it provides CAS (Compare-And-Set) operations, wide-column data handling and vector search.
TierBase supports vector search by integrating the VSAG library\cite{vsag}, a vector indexing library developed by Ant Group for similarity search, which enables efficient ANN queries over high-dimensional vectors within our key-value infrastructure. The integration supports dynamic vector operations, including real-time insertion and deletion in memory, demonstrating performance improvements of 3-4x compared to conventional algorithms such as HNSW.
As shown in Figure \ref{fig:overview}, TierBase incorporates a tiered storage architecture, separating the caching tier from the storage tier, allowing independent scaling based on workload requirements.
The cache tier employs in-memory hash tables stored in DRAM or persistent memory (PMem) for efficient random access performance, while the storage tier typically utilizes a LSM-tree structure stored on SSD or HDD to optimize write performance and storage capacity. This architecture allows TierBase to effectively balance high-speed data access with efficient data storage across different storage media.
TierBase also features memory compression and elastic threading support, optimizing resource utilization dynamically.
The architecture of TierBase is structured into three primary tiers: client, cache, and storage.
\noindent\textbf{Client Tier}. The client tier consists of TierBase clients and proxy services. TierBase clients, compatible with native Redis clients, retrieve cluster routing information from the coordinator cluster for direct data access. They handle failover, cluster scaling automatically. For small-scale scenarios, TierBase provides a proxy service facilitating rapid integration for public cloud users.
\noindent\textbf{Cache Tier}.
The cache tier in TierBase consists of instances and coordinators. Each instance serves as a data node with key hashes for data sharding. The cache instances implements hash tables for efficient key-value storage. Moreover, the cache tier can operate independently without the storage tier for in-memory storage use cases, providing high-speed data access similar to systems like Redis and Memcached. TierBase supports both single-replica and multi-replica modes, implementing various replication protocols to accommodate different reliability requirements. Coordinators oversee the entire cluster, managing failovers and administering tenant resource allocation.
\noindent\textbf{Storage Tier}.
The storage tier provides data persistence through a disaggregated key-value storage system. The cache tier directly accesses this tier for cache misses, employing either write-through or write-back policies for data writing.
TierBase offers various disaggregated storage options through a pluggable storage adapter. In our experiments, we focus on the Universal Configurable Storage (UCS)\footnote{UCS is an internal system developed by Ant Group and does not have a publicly available reference at the time of writing this paper.}, a sophisticated real-time serving and analytical storage engine. UCS implements an LSM-Tree with a shared disk architecture and remote compaction. This design ensures optimal online performance while supporting both row and columnar storage formats.
Although our experiments focus on an LSM-tree storage engine, the pluggable storage adapter in TierBase allows integration with various disaggregated storage systems based on different data structures. Consequently, the cost optimization techniques in the cache tier and cost evaluation with the cost model can be applied to a wide range of key-value stores.
Additionally, TierBase includes monitoring and analysis tools for real-time metrics collection, problem diagnosis, and workload-based suggestions. It integrates with Cougar\cite{Cougar} for automatic scaling in cloud environments.
% Value compression techinques including zstd with dictionary and noval PBC compression techinque.
% Values are usually generated by programs which produce strings with limited patterns.
% May need some production data from Qinqian (how much the data can be compressed)
% These tehcnique relies on pre-trained dictionary/patterns for keys and values. Need initial data to start to compression cycle.
% Retrain processes are required if pattern changes are detected.
\section{Cost Optimization Strategies}
In this section, we introduce the well-designed features which aim to optimize the cost of TierBase.
\label{Cost Optimization Strategies}
\input{disaggregated}
\input{compress}
%\input{heterogenous}
\input{pmem}
\input{thread}
\subsection{Tiered Storage}
\label{sec:writethough_back}
TierBase introduces a tiered storage architecture that disaggregates cache and storage components, allowing for independent optimization. This approach directly addresses the space-performance trade-off highlighted in our cost model. The cache tier is optimized for speed (minimizing $PC_{cache}$), while the storage tier is designed for capacity and durability (optimizing $SC_{storage}$). Both tiers can scale independently, accommodating diverse workloads and data access patterns.
To ensure data consistency and reliability in this disaggregated architecture, we adapt the well-known caching techniques "write-through" and "write-back". These strategies are commonly used in conventional hardware scenarios to synchronize data between cache and storage. However, applying these techniques to a disaggregated architecture presents unique challenges. In traditional contexts, write-through and write-back policies are implemented within a single tier, where the cache and storage are tightly coupled. This tight coupling allows for simpler coordination and synchronization mechanisms between the cache and storage, as they reside on the same physical node or have low-latency communication channels. In contrast, the separation of cache and storage tiers in TierBase introduces new complexities in maintaining data consistency and synchronization, requiring careful design and implementation of coordination protocols and synchronization strategies.
\subsubsection{Write-through Caching}
In the write-through caching policy (Figure \ref{fig:writethrough}), TierBase prioritizes data consistency between the cache and storage tiers. When a write request is received, it is first executed on the cache tier and then synchronously passed to the disaggregated storage tier before acknowledging completion to the application. If the storage update succeeds, the cache tier maintains the updated data; otherwise, the corresponding cache entry is invalidated, and an error is returned to the application.
To ensure data consistency in the presence of failures while reducing $PC_{miss}$, TierBase employs several key techniques:
\sstitle{Temporary Update Buffer.} Each connection maintains a temporary update buffer. Incoming update requests are initially performed on this buffer, and the results are used to update the main cache. If the storage write succeeds, the data is seamlessly transferred from the temporary buffer to the main cache. In case of a storage write failure, the corresponding entry in the main cache is removed, ensuring subsequent reads fetch the data from the storage, maintaining consistency.
\sstitle{Sequential Write Ordering.} TierBase uses a per-key write queue to maintain the sequential order of writes to the same key, ensuring consistent execution order in the cache tier for asynchronous storage updates.
\sstitle{Write Coalescing.}
Within Redis's event loop, TierBase coalesces multiple write commands targeting the same key into a single operation, similar to the concept of group commit in database systems. This approach efficiently updates the store with the final result, reducing the number of write operations and consequently lowering $PC_{miss}$.
This write-through strategy is particularly effective in environments where read operations significantly outnumber write operations, and high data reliability are critical.
\begin{figure}[t]
\subfigure[Write-through caching policy]{
\centering
\includegraphics[scale=0.39]{figures/write_through.pdf}
% \caption{Write through}
\label{fig:writethrough}
}
\hspace{-0.3cm}
\subfigure[Write-back caching policy]{
\centering
\includegraphics[scale=0.39]{figures/write_back.pdf}
% \caption{Write back}
\label{fig:writeback}
}
\caption{Caching policy for write operation}
\label{fig:cachingpolicy}
%\vspace{-2mm}
\end{figure}
\subsubsection{Write-back Caching}
The write-back caching policy in TierBase prioritizes performance by optimizing $PC_{cache}$ and reducing $PC_{miss}$. Updates are first written to the cache tier with immediate response to the application, while data synchronization to the storage tier is deferred and performed asynchronously in batches. This approach minimizes $PC_{storage}$ by reducing the frequency of writes to the storage tier.
In cases where requested data is not present in the cache during an update operation, TierBase fetches the data from the storage tier before updating the cache. Data updated in the cache but not yet synchronized to storage is marked as``dirty" and periodically propagated in batches, minimizing remote calls to the storage tier.
Implementing write-back caching in a tiered storage architecture introduces unique challenges in ensuring data reliability and optimizing synchronization efficiency between cache and storage:
\sstitle{Replication of Cache.} To prevent data loss in case of cache tier failure, TierBase maintains multiple replicas of dirty data and cache contents.
\sstitle{Managing Dirty Data.} TierBase balances the scale of dirty data by restricting its size and establishing maximum interval times for batch updates. A backpressure mechanism is activated when dirty data approaches a predefined threshold.
\sstitle{Optimizing Update.} TierBase minimizes remote calls to the storage tier by batching updates and merging multiple updates for the same key.
\sstitle{Deferred Cache-fetching.}
For update operations on missing keys, TierBase accumulates operations and submits batch read tasks to fetch data from storage, reducing read requests and minimizing costs in both tiers.
The consistency level in write-back caching is determined by the cache tier's configurable coherent protocol, ensuring updates are eventually propagated to underlying storage with strong consistency support.
\subsubsection{Write-through versus write-back}
TierBase supports both write-through and write-back caching policies, each offering different trade-offs:
Write-through caching provides lower $SC_{cache}$ as it doesn't store dirty data, but potentially higher $PC_{cache}$ for write-heavy workloads due to synchronous storage updates. Write-back caching offers lower $PC_{cache}$ and $PC_{miss}$ for write-heavy workloads due to deferred and batched storage updates, but incurs higher $SC_{cache}$ due to storing dirty data and potential replication.
The choice between these policies depends on specific workload characteristics and relative costs of cache and storage resources. Write-back caching may provide better cost-performance for write-heavy workloads with good temporal locality, while write-through caching may be more cost-effective for read-heavy workloads or when storage writes are relatively inexpensive.
TierBase's flexible configuration allows users to select the appropriate caching policy based on their application's requirements and cost structure, optimizing the space-performance trade-off for various workloads and scenarios.
\begin{figure}[tb]
\begin{center}
\begin{tabular}[t]{c}
\includegraphics[scale=0.37]{figures/compression1.pdf}
\end{tabular}
\end{center}
%\vspace*{-0.5cm}
\caption{The framework of pre-trained based compression}
%\vspace*{-0.2cm}
\label{fig:compression-overview}
\end{figure}
% \setlength{\textfloatsep}{20pt}
\subsection{Pre-trained Compression Mechanism}
\label{pre_compress}
In the context of our space-performance cost model, in-memory data compression plays a crucial role in optimizing the trade-off between storage costs ($SC$) and performance costs ($PC$) within the memory tier.
In TierBase, we develop a pre-trained compression mechanism which includes two efficient compression algorithms: our newly developed Pattern-Based Compression (PBC) \cite{pbc,github_pbc} and the widely adopted Zstandard (Zstd) \cite{zstd} by Meta. The framework of pre-trained compression is shown in Figure \ref{fig:compression-overview}. In the pre-training phase, Zstd builds a dictionary by identifying frequent strings in the data, while PBC employs hierarchical clustering and a unique similarity metric to pinpoint and extract data patterns. In the compression phase, the resulting patterns, along with residual strings, are then compressed further using string compression techniques.
Initially, we construct the dictionary (patterns) offline using samples from data records. We then apply this dictionary to the entire workload, enabling data compression and decompression.
A key challenge with pre-trained compression in production is the need to re-sample and re-train datasets when patterns change to avoid reduced compression ratios. To address this, TierBase introduces a monitoring service that continuously tracks compression efficiency and initiates re-sampling and re-training when necessary. Specifically, it monitors the compression ratio and the number of data records that do not align with the pattern. Re-sampling and retraining are triggered when the compression ratio falls below a baseline level or when the rate of unmatched records exceeds a predefined threshold.
Furthermore, TierBase’s Insight service includes a compressor recommender that automatically suggests the optimal compressor based on data types and performance requirements. This adaptive compression mechanism supports various data types, dynamically rebuilding the dictionary to accommodate changes in data patterns.
Our experiments demonstrate the cost-effectiveness of our pre-trained compression mechanism, enabling TierBase to dynamically adjust its compression strategy and balance the space-performance trade-off based on evolving data patterns and workloads. Despite a moderate increase in performance cost ($PC$) for write operations due to compression overhead, the significant reduction in space cost ($SC$) and high decompression speed for read operations optimize overall cost-effectiveness. By adjusting compression levels, TierBase can fine-tune the balance between $SC$ and $PC$, achieving an optimal point in the cost model to minimize total cost while maintaining high performance across diverse workloads.
\subsection{Persistent Memory Utilization}
A standout component in TierBase's storage strategy is the adoption of persistent memory(PMem). The PMem distinguishes itself through its capacity, affordability compared to DRAM, swift memory-like access speeds, and its non-volatile nature. The utilization of PMem enhances the overall performance while reduce the cost of TierBase in two folds:
\noindent\textbf{DRAM Extension}: Serving as an economical DRAM supplement, PMem allows for efficient memory use by keeping frequently accessed (hot) data, in DRAM, while less accessed (cold) data is stored in PMem. This strategy optimizes the balance between space cost ($SC$) and performance cost ($PC$).
\noindent\textbf{WAL Persistence}: PMem greatly improves TierBase’s Write-Ahead Log (WAL) persistence by overcoming the I/O operations per second (IOPS) bottleneck found in disk or cloud storage, ensuring faster and more consistent data synchronization. Crucially, WAL files are first written to a PMem-based persistent ring buffer, then batch-moved to cloud storage, achieving high throughput and real-time persistence, thus significantly boosting performance in high-demand scenarios.
To address the performance gap between PMem and DRAM, particularly in write latency, TierBase employs a refined memory allocation strategy. Small, frequently accessed data (keys and indexes) are stored in DRAM, while larger value data resides in PMem. Write operations to PMem are optimized through batching: data structures are assembled in DRAM before bulk transfer to PMem, reducing the impact on performance costs.
Our production experience demonstrates that PMem, when integrated into a tiered storage architecture alongside DRAM and SSDs, delivers strong performance even with straightforward data structures. This approach effectively balances performance and cost in TierBase's storage system.
\subsection{Elastic Threading}
\begin{figure}[t]
\centering
\includegraphics[scale=0.4]{figures/thread.pdf}
\caption{Elastic threading}
\label{fig:elastic}
\end{figure}
TierBase implements an innovative elastic threading approach to optimize performance cost ($PC$) within allocated node resources. This dynamic method seamlessly switches between single-thread and multi-thread modes based on workload demands, enhancing system responsiveness and resource efficiency without external scaling.
In normal conditions, TierBase operates in a default single-thread mode, utilizing an event-driven model with epoll. This approach offers high CPU efficiency and lower $PC$ for typical workloads. We claim that the efficiency of a single-threaded process per data shard generally outperforms that of multi-threading due to reduced locking overhead, a principle supported by Amdahl's Law\cite{Amdahl}.
When the workload on a particular instance increases significantly, TierBase seamlessly transitions to multi-threaded mode by dynamically adding threads within the container's pre-allocated CPU resources. Containers are provisioned with CPU capacity based on anticipated peak workloads, but this capacity isn't fully utilized during normal operations. Elastic threading allows TierBase to leverage these underutilized CPU resources when needed, boosting the affected instance's performance without exceeding resource limits or incurring additional costs. When the workload subsides, TierBase switches back to single-thread mode, allowing CPU resources to be used by other processes within the container and maximizing resource efficiency.
Elastic threading is particularly effective for skewed workloads like dynamic hotspots. Typically, one instance might switch to multi-threaded mode while others remain in single-threaded mode within the same container, optimizing resources across the system. If the container's overall CPU load remains consistently high, the system recognizes the need to scale out to further enhance tenant performance.
This approach improves responsiveness to immediate demands and optimizes resource use, preventing unnecessary allocation during low-activity periods. By dynamically balancing between single-threaded efficiency and multi-threaded performance, elastic threading significantly contributes to overall CPU efficiency. Elastic threading uses only idle CPU resources within the allocated container. Threads are dynamically added or removed based on workload demands, ensuring efficient resource use without over-provisioning or incurring extra costs.
\section{Further Cost Analysis and Framework}
\label{detailed_analysis}
This section provides an in-depth analysis of our cost model by examining space-performance trade-offs in storage systems, relating these to our Optimal Cost Theorem and the classic Five-Minute Rule. We adapt the Five-Minute Rule for modern distributed systems and provide a framework for cost optimization for tiered storage.
\subsection{Adapting the Five-Minute Rule for Modern Storage Systems}
\label{interval}
The Five-Minute Rule\cite{gray19875,five20,five30}, introduced by Jim Gray and Gianfranco Putzolu in 1985, has been a cornerstone in database system design. Originally formulated for single-server environments, it provided a simple heuristic for deciding whether data should be kept in memory or on disk based on its access frequency:
{\small
\setlength{\abovedisplayskip}{5pt}
\setlength{\belowdisplayskip}{5pt}
\begin{align}
BreakEvenInterval &= \left( \frac{PagesPerMBofRAM}{AccessPerSecondPerDisk} \right) \nonumber \\
&\quad \times \left( \frac{PricePerDiskDrive}{PricePerMBofRAM} \right) \label{eq:rule_equation}
\end{align}
}
However, in today's distributed and cloud-based systems, we need to consider a broader range of factors and trade-offs. We propose an adapted version of the Five-Minute Rule that aligns with our cost model:
{\small
\begin{equation}
BreakEvenInterval = \frac{CPQPS_{slow}}{CPGB_{fast} \times AverageRecordSize}
\end{equation}
}
Where $CPQPS_{slow}$ is the Cost Per Query Per Second for slower, space-optimized storage, $CPGB_{fast}$ is the Cost Per Gigabyte for faster, performance-optimized storage, and $AverageRecordSize$ is the average size of data records in the workload.
To illustrate how our adapted rule relates to the original, we provide the following mapping.
\begin{itemize}%[leftmargin=*]
\item The ratio $\left( \frac{PricePerDiskDrive}{AccessPerSecondPerDisk} \right)$ effectively represents the $CPQPS_{slow}$.
\item $PricePerMBofRAM$ correlates to $CPGB_{fast}$.
\item $PagesPerMBofRAM$ is conceptually similar to \\$\left( \frac{1GB}{AverageRecordSize} \right)$.
\end{itemize}
This formulation determines the optimal point on the space-performance trade-off spectrum for a given workload in a distributed environment. It can be illustrated by comparing fast, in-memory storage systems like Redis \cite{redis} with slower, more space-efficient systems like HBase\cite{hadoop}, or by examining different configurations of the same database system.
The break-even interval analysis, derived from our adapted Five-Minute Rule, optimizes data placement by comparing data access intervals to the break-even point. It guides the choice between fast, performance-oriented storage and slower, space-efficient options.
Our Cost Optimal Theorem extends this concept by determining the best overall storage settings for a given workload, aiming to minimize system cost by balancing performance cost ($PC$) and space cost ($SC$). It considers the entire system configuration, including multiple storage tiers and complex workload characteristics, to guide high-level design and resource allocation decisions.
Our comprehensive experiments assessed the performance and cost efficiency of our system against leading open-source key-value databases using this integrated approach. The evaluation results on real application workloads demonstrate the model's effectiveness in guiding cost-saving database system designs. The case study in Section \ref{case_study} showcases how the break-even interval, derived from the Five-Minute Rule, helps choose the most cost-effective TierBase configuration within the framework established by the Cost Optimal Theorem.
\subsection{Cost Analysis of Tiered Storage}
\label{cost_analysis_tired_storage}
Revisiting Equation \ref{eq:tiered_cost}, we can focus on optimizing the cost of the cache tier. In disaggregated storage systems with a sufficiently large storage pool, the storage tier cost is dominated by $SC$ when $MR < SC_{storage} / PC_{storage}$ for skewed access patterns. As illustrated in Figure \ref{fig:cost-model2}, this allows us to concentrate on the cache tier cost:
\begin{align}
Cost_{cache} = \max(&PC_{cache} + PC_{miss} \times MR, \nonumber \\
&SC_{cache} \times CR)
\end{align}
To find the optimal cost, we consider the relationship between the Miss Ratio ($MR$) and the Cache Ratio ($CR$), typically represented by the Miss Ratio Curve\cite{10.1145/3185751}, where $MR = f(CR)$, and $f$ is a non-increasing function.
\begin{theorem}[Optimal Cache Tier Cost]
The optimal cost for the cache tier of a tiered storage is achieved when the performance cost equals the space cost:
\begin{equation}
PC_{cache} + PC_{miss} \times f(CR^*) = SC_{cache} \times CR^*
\end{equation}
where $CR^*$ is the optimal cache ratio.
\end{theorem}
% \begin{proof}
Let $CR^*$ be the optimal cache ratio that minimizes the overall cost of the cache tier:
$Cost_{cache}^* = \min_{0 \leq CR \leq 1} \max(PC_{cache} + PC_{miss} \times f(CR), SC_{cache} \times CR)$
Define two functions:
$g(CR) = PC_{cache} + PC_{miss} \times f(CR)$
$h(CR) = SC_{cache} \times CR$
Note that $g(CR)$ is non-increasing (as $f(CR)$ is non-increasing) and $h(CR)$ is increasing linearly with $CR$.
The optimal cost occurs at the intersection of these two functions. To see why, consider:
1. If $g(CR) > h(CR)$, we can decrease $CR$ to reduce cost.
2. If $g(CR) < h(CR)$, we can increase $CR$ to reduce cost.
3. The minimum cost occurs when neither of these improvements is possible, i.e., at $g(CR) = h(CR)$.
Therefore, the optimal cache ratio $CR^*$ satisfies:
\begin{equation}
PC_{cache} + PC_{miss} \times f(CR^*) = SC_{cache} \times CR^*
\end{equation}
This equality represents the balance point where performance cost (including miss penalty) equals space cost, minimizing the overall cache tier cost.
% \end{proof}
This theorem provides a principle for optimizing tiered storage systems: the most cost-effective configuration is one where the cache tier's performance cost (including the cost of cache misses) equals its space cost. This balance point represents the optimal trade-off between performance and space for the cache tier.
In practice, estimating the exact $CR^*$ is challenging, as $f(CR)$ can be complex and highly dependent on specific workload characteristics. Nevertheless, this theorem serves as a valuable target for optimization efforts, guiding cache size tuning. To address this challenge, we propose an evaluation-based approach in Section \ref{sec:framework} to find the optimal $CR$.
Furthermore, this analysis provides a way for determining when to use tiered storage over single-tier solutions and how to optimally configure the cache tier within a tiered storage system, enhancing our understanding of cost-effective storage design in modern disaggregated environments.
\subsection{Cost Optimization Framework}
\label{sec:framework}
In order to speedup the cost optimization procedure, we develop a sample-based method to calculate the cost for various configurations with regard to real-world workloads. The method involves the following steps:
\begin{enumerate}
\item \textbf{Sample}: Sample data snapshots and record a representative period of workload from production instances.
\item \textbf{Load}: Load the sampled data snapshot into a testing instance with a specific configuration.
\item \textbf{Replay}: Replay the recorded real-world key-value operation traces on the testing instance, measuring and collecting the maximum performance and maximum space utilization for the workload.
\item \textbf{Calculation}: Calculate the workload cost based on measurements.
\item \textbf{Iteration}: Repeatedly perform steps 2-4 with different configurations to approach cost-optimal configuration.
\end{enumerate}
This method simulates key-value store behavior under realistic conditions, providing accurate performance and cost assessments. By using real workload traces and access patterns, we obtain a precise representation of system performance. This method enables comprehensive exploration of the configuration space, ensuring identification of the most cost-effective configuration for each individual workload.
While the configuration space for cost optimization can be large, in practice, we focus on the most impactful parameters specific to the workload, guided by user input and prior experience. This approach narrows the candidate configurations substantially. Optimization computations are performed offline and parallelized to accelerate the process, ensuring that the time invested is minor compared to the long-term cost savings achieved. To address the cold start problem, we initialize the system with configurations based on user inputs and best practices.The detailed optimization results and cost savings are analyzed with case studies in Section \ref{sec:exp}.
% \input{figures/client_plot_single}
\section{Experiments}
\label{sec:exp}
\subsection{Settings}
%AEP机器参数,pmem
The experimental evaluation is conducted on the following servers. For the cache tier, we use three servers with dual Intel Xeon Platinum 8263C CPUs at 2.50 GHz, 192GB DRAM, and eight 128GB Intel\textsuperscript{\textregistered} Optane\texttrademark{} DCPMM 100 series(App Direct Mode), while for the storage tier, we use three servers with Intel Xeon Platinum 8163 CPU at 2.50 GHz, 64GB DRAM, and 8TB SSDs. For all servers, NUMA is enabled and Hyper-threading is disabled for linear performance scaling and to avoid contention between logical cores. The system and software environments are as follows: Linux kernel version 4.19.91, OpenJDK version 1.8.0, GCC version 10.2.1, Dragonfly 1.23.0, Redis 6.0.17, Cassandra 4.0.11, HBase 2.4.1, and Memcached 1.6.20.
YCSB (Yahoo! Cloud Serving Benchmark) \cite{ycsb} is utilized which encompasses the load and run phase. Our experiments utilize two distinct default workloads from YCSB: Workload A, characterized by a predominance of write operations, and Workload B, distinguished by a higher proportion of read operations. We have adapted YCSB to accept user-specified datasets for data insertion, as opposed to the default use of random strings as values. In particular, the Cities dataset \cite{cities} is designated as the default for our tests. We deploy 16 YCSB threads for single-thread cases and 48 for multi-thread cases.
We focus our comparisons on widely-used production systems to evaluate TierBase's performance and cost-effectiveness in real deployment scenarios, which have essential features implemented, such as full failure recovery. These systems can reflect the performance and cost accurately in real world applications.
We selected Redis \cite{redis}, Memcached \cite{memcached} and Dragonfly \cite{dragonflydb} for caching system comparison. Redis and Memcached are established caching systems, extensively utilized across diverse applications. Dragonfly is a newly introduced, high-performance caching system. For databases with persistence, we select Redis with AOF, Cassandra \cite{Cassandra}, and HBase \cite{hadoop} as competitors. Specifically, Redis-AOF ensures data durability by logging writes to disk, which can impact performance due to the additional disk I/O overhead.
Instances represent the fundamental units of resource allocation. In systems operating in single-thread mode, each instance is allocated 1 CPU core and 4GB of memory. In multi-thread mode and databases with persistence, the allocation for each instance increases to 4 CPU cores and 16GB of memory. These specifications are common instance configurations used by Ant Group.
\subsection{Performance Evaluation}
\subsubsection{Caching Systems}
Figure \ref{fig:performance} illustrates the performance comparison of four caching systems: TierBase, Redis, Memcached, and Dragonfly. During this evaluation, TierBase was tested in its default mode without any cost optimization techniques enabled. We evaluate the performance for single-thread and multi-thread mode separately and report the throughput and 99th percentile tail latency respectively.
In single-thread mode (Figures \ref{fig:performance}(a) and \ref{fig:performance}(b)), TierBase and Redis exhibit similar performance, outperforming Memcached and Dragonfly across all workloads. This distinction arises because Memcached and Dragonfly are principally engineered for multi-thread environments, while in contrast, Redis is meticulously optimized for single-thread mode. TierBase maintains the lowest latency across most workloads. During the load phase, the latency of TierBase and Redis is significantly lower than that of Memcached and Dragonfly.
In multi-thread mode (Figures \ref{fig:performance}(c) and \ref{fig:performance}(d)), Memcached and Dragonfly surpass TierBase and Redis. Memcached combines a streamlined caching approach with a lightweight threading model, minimizing inter-thread contention and enhancing speed. Dragonfly benefits from a shared-nothing architecture for threads, boosting its parallel processing. Although TierBase's per-instance throughput is slightly lower in multi-thread mode, it excels in real-world scenarios through efficient scaling. Figure \ref{fig:performance}(c) shows that 4 single-threaded TierBase instances outperform a single multi-threaded instance of Memcached or Dragonfly using equivalent resources, leading to a lower performance cost. In practice, scaling out across multiple instances meets performance requirements, and TierBase's cost-effectiveness makes this economically viable. Thus, TierBase effectively balances performance and cost, aligning with the demands of large-scale applications.
\input{figures/performance_multi}
\input{figures/persistence_single}%
% \input{figures/compress}%
\setlength{\textfloatsep}{10pt}
\subsubsection{Persistence Mechanisms}
Figure \ref{fig:ps} outlines TierBase's performance with four persistence mechanisms in single-thread mode: WAL, WAL while using PMem as the persistent ring buffer(WAL-PMem), write-back and write-through introduced in Section \ref{sec:writethough_back}.
For the throughput performance(Figure \ref{fig:ps}(a)), write-back significantly outperforms write-through in the load phase by 92.52\%, due to its deferred writing mechanism that reduces immediate write operation overhead. In various read-write workloads, write-back's throughput is about twice of write-through, demonstrating its efficiency in write-intensive tasks. The WAL-PMem mode, while not as effective as write-back, still surpasses write-through, indicating benefits by using persistent memory.
However, WAL mode outperforms WAL-PMem due to its use of SSDs and asynchronous disk flushes every second, while WAL-PMem synchronizes to PMem per transaction, potentially incurring higher synchronization overhead.
In terms of latency (Figure \ref{fig:ps}(b)), write-through experiences the highest latency due to its immediate write to storage, being around 3 times higher than write-back in the load phase. Write-back, with its deferred write, significantly lowers latency, particularly in write-heavy scenarios. WAL-PMem offers a middle ground, with lower latency than write-through but higher than write-back.
\subsection{Features Evaluation}
\input{figures/compress}
\subsubsection{Compression.}
As introduced in \ref{pre_compress}, \tbase has implemented pre-trained based compression strategies to mitigate memory utilization. We evaluate effectivness of the pre-trained based compression methods:(i) Zstd-b, (ii) Zstd-d, (iii) PBC. Basic Zstd\cite{zstd} (denoted as Zstd-b) which is without pre-trained dictionaries, Zstd with pre-trained dictionaries(denoted as Zstd-d) and Pattern-Based Compression\cite{pbc} (PBC). We also include the raw data without compression(Raw) as the bar of throughput.
As shown in Table \ref{fig:compress study}, the pre-trained based methods, PBC and Zstd-d, consistently outperform Zstd-b. It demonstrates that the pre-trained mechanism, by prior analysis and storage of common data patterns, is able to enhance the compression ratio. Notably, PBC consistently achieves higher compression ratios than Zstd. In KV datasets, the distinctive patterns within the values lead to a more significant improvement in PBC's compression performance. Specifically, PBC surpasses Zstd-d by 43\% and Zstd-b by 74\% in average compression ratios. These enhanced ratios contribute to PBC's sustained superiority in overall compression performance.
In the evaluation of throughput. all three compression methods perform worse compared to Raw, especially in SET operations. Among the three compression mechanisms tested, Zstd-d demonstrated the highest performance. In public datasets, the throughput of Zstd-d was approximately twice as high as PBC and about 3.5 times higher than Zstd-b. This notable difference is primarily due to the higher computational overhead in PBC's compression process which involves pattern matching and string encoding. Meanwhile, Zstd-b, without pre-trained dictionary, necessitates online data analysis during compression, which hampers throughput. In contrast, when considering average GET operation throughput, PBC not only surpasses Zstd-d but also nearly parallels the velocity of Raw. Zstd-b still demonstrates the least favorable performance.
The implementation of compression introduces a calculated trade-off, modestly impeding throughput performance in exchange for substantial memory conservation, thereby augmenting the judicious utilization of resources. Based on the pre-trained compression strategy, it is possible to preserve common patterns in the data in advance, avoiding real-time computation during compression and decompression, thereby enhancing the efficiency and effectiveness of the compression process. The Section \ref{sec:cost evaluation} will provide an in-depth exploration of the multifaceted benefits engendered by compression.
\subsubsection{Elastic threading.}
%\newline
\indent
In order to show the effect of elastic threading, we simulate a scenario of workload burst to test the system's adaptability to sudden workload influxes. At the beginning, the workload maintenance a low QPS(20,000). Then, we increase in the number of client requests to simulate a surge in workload at the 15 second. This state lasts for 30 seconds and finally the workload returned to normal, the low QPS state. We represent single-thread, multi-thread and elastic threading modes as $s$, $m$ and $e$ (e.g. TierBase-s, TierBase-m, TierBase-e).
As shown in Figure \ref{fig:elastic-thread}, under normal conditions, all databases manage well, with Redis showing some jitter in multi-thread mode. Upon increased workload, systems' throughput reaches their limits, and latency rise. In single-thread mode, \tbase has the highest latency, followed by Redis. However, with elastic threading, \tbase initially faces higher latency but quickly adjusts to have the lowest latency, equal to its multi-thread mode performance. In terms of throughput, both \tbase and Redis hit 120,000 QPS in single-thread mode, with Redis peaking at 180,000 QPS and \tbase at over 240,000 QPS in multi-thread mode. % Elastic threading allowed \tbase to switch efficiently from single-thread to multi-thread mode, outperforming single-thread Redis by 100,000 QPS.
In summary, the experiment result indicates that elastic threading allows \tbase to operate in a cost-saving single-thread mode under normal scenario, while automatically switching to a multi-thread mode to achieve higher throughput performance during workload spikes, without the need for manual intervention.
\input{figures/burst_recover1}
\input{Cost_Calculation_result}
\
\newline
\indent
% \begin{figure*}
% \centering
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% xmin=0.5, xmax=5.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge TierBase }
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Redis }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge Memcached }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge Dragonfly }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.55cm,
% width=1\textwidth,
% height=0.4\textwidth,
% %xlabel={\huge \bf YCSB Workload},
% scaled y ticks=false,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=50000,ymax=175000,
% ytick={60000,90000,120000,150000,180000},
% yticklabels={60,90,120,150,180,140},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge thoughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 113184.14666451453)
% (2, 131550.90779311996)
% (3, 135567.29744614722)
% (4, 139309.9595670512)
% (5, 138202.66983079497)
% (6, 90078.07533793423)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 117631.35067095495)
% (2, 135074.06501342953)
% (3, 131875.15308675036)
% (4, 138756.28128280398)
% (5, 142136.77844571666)
% (6, 87454.81189155314)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 112040.517451794)
% (2, 126989.00530465912)
% (3, 123591.10493517923)
% (4, 125167.3375836492)
% (5, 127281.74024610719)
% (6, 83096.7468128943)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 103577.42007621226)
% (2, 108935.2282308765)
% (3, 110663.38966790958)
% (4, 106739.07186153322)
% (5, 114665.76116066572)
% (6, 74361.5307874211)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% \label{fig:ps1}
% } \hspace{1cm}
% \subfigure[Latency (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.55cm,
% width=1\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=0,ymax=350,
% % ymode =log,
% ytick={100,200,300},
% yticklabels={100,200,300},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 191.0013535956685)
% (2, 157.50129439585794)
% (3, 146.05137373560405)
% (4, 144.50127519591936)
% (5, 141.55130763581556)
% (6, 194.62721168956716)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 189.0014239954432)
% (2, 157.75159169490658)
% (3, 168.57655045503856)
% (4, 156.00134079570944)
% (5, 148.57645435534607)
% (6, 195.37448401168712)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 246.046959248652)
% (2, 177.5417928313147)
% (3, 259.3666346338459)
% (4, 232.0445912865394)
% (5, 225.06213000591993)
% (6, 246.9976099930035)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 263.00131039580674)
% (2, 162.00134879568384)
% (3, 172.0012415960269)
% (4, 174.5014959952128)
% (5, 163.52632751575194)
% (6, 206.50127761863314)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \label{fig:s2}
% }
% \subfigure[ Throughput (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% %xlabel={\huge \bf YCSB Workload},
% bar width=0.55cm,
% scaled y ticks=false,
% width=1\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=70000,ymax=520000,
% ytick={100000,200000,300000,400000},
% yticklabels={100,200,300,400},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge thoughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 212064.3283560956)
% (2, 246772.0948768674)
% (3, 284127.97921917425)
% (4, 306892.8597799601)
% (5, 320624.2315092562)
% (6, 193095.15061582578)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 194937.95124821865)
% (2, 209987.08784449435)
% (3, 227837.90635583305)
% (4, 228874.24461547082)
% (5, 241211.27667972192)
% (6, 148226.924689852)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 343937.2340640109)
% (2, 377406.00780349335)
% (3, 389154.74239110027)
% (4, 400234.6291817671)
% (5, 385160.1255477292)
% (6, 258020.25783571514)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 334524.3111484017)
% (2, 345105.97806245193)
% (3, 355606.9430577287)
% (4, 342520.44030230143)
% (5, 350951.3696242389)
% (6, 230826.45675877255)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm1}
% \end{tikzpicture}
% % \label{fig:m1}
% }\hspace{1cm}
% \subfigure[Latency (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.55cm,
% width=1\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=0,ymax=650,
% % ymode =log,
% % ytick={500,1000,1500,2000,2500},
% % yticklabels={500,1000,1500,2000,2500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 375.0027311737807)
% (2, 245.253054270679)
% (3, 202.02860452539656)
% (4, 217.0033551677904)
% (5, 206.05436777806932)
% (6, 285.023505857191)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 353.00243357663766)
% (2, 321.5024109768546)
% (3, 335.72681292259597)
% (4, 282.5029039721219)
% (5, 245.0283751275988)
% (6, 349.38200802785093)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 421.0348284656467)
% (2, 322.768110726137)
% (3, 320.12300581914417)
% (4, 327.0413564029785)
% (5, 331.968477602615)
% (6, 408.6544217168574)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 358.0026111749327)
% (2, 205.00323106898176)
% (3, 198.5040127614775)
% (4, 213.00324956880416)
% (5, 197.55384768306226)
% (6, 258.3676851229459)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm2}
% \end{tikzpicture}
% \label{fig:pm2}
% }
% % \label{fig:sm}
% \caption{Performance analysis of single-thread and multi-thread Mode}
% \label{fig:performance}
% \end{figure*}
%-------------------原图-----------------
% \begin{figure}
% \centering
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0.1pt,
% width=0.1pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% % xmin=0.5, xmax=3.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge TierBase }
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Redis }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge Memcached }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge Dragonfly }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% %xlabel={\huge \bf YCSB Workload},
% scaled y ticks=false,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=50000,ymax=175000,
% ytick={60000,90000,120000,150000,180000},
% yticklabels={60,90,120,150,180,140},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge throughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 113184.14666451453)
% (2, 131550.90779311996)
% (3, 135567.29744614722)
% % (4, 139309.9595670512)
% % (5, 138202.66983079497)
% % (6, 90078.07533793423)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 117631.35067095495)
% (2, 135074.06501342953)
% (3, 131875.15308675036)
% % (4, 138756.28128280398)
% % (5, 142136.77844571666)
% % (6, 87454.81189155314)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 112040.517451794)
% (2, 126989.00530465912)
% (3, 123591.10493517923)
% % (4, 125167.3375836492)
% % (5, 127281.74024610719)
% % (6, 83096.7468128943)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 103577.42007621226)
% (2, 108935.2282308765)
% (3, 110663.38966790958)
% % (4, 106739.07186153322)
% % (5, 114665.76116066572)
% % (6, 74361.5307874211)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% \label{fig:ps1}
% }
% \subfigure[Latency (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=350,
% % ymode =log,
% ytick={100,200,300},
% yticklabels={100,200,300},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 191.0013535956685)
% (2, 157.50129439585794)
% (3, 146.05137373560405)
% % (4, 144.50127519591936)
% % (5, 141.55130763581556)
% % (6, 194.62721168956716)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 189.0014239954432)
% (2, 157.75159169490658)
% (3, 168.57655045503856)
% % (4, 156.00134079570944)
% % (5, 148.57645435534607)
% % (6, 195.37448401168712)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 246.046959248652)
% (2, 177.5417928313147)
% (3, 259.3666346338459)
% % (4, 232.0445912865394)
% % (5, 225.06213000591993)
% % (6, 246.9976099930035)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 263.00131039580674)
% (2, 162.00134879568384)
% (3, 172.0012415960269)
% % (4, 174.5014959952128)
% % (5, 163.52632751575194)
% % (6, 206.50127761863314)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \label{fig:s2}
% }
% \subfigure[ Throughput (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% %xlabel={\huge \bf YCSB Workload},
% bar width=0.45cm,
% scaled y ticks=false,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=70000,ymax=520000,
% ytick={100000,200000,300000,400000},
% yticklabels={100,200,300,400},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge throughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 212064.3283560956)
% (2, 246772.0948768674)
% (3, 284127.97921917425)
% % (4, 306892.8597799601)
% % (5, 320624.2315092562)
% % (6, 193095.15061582578)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 194937.95124821865)
% (2, 209987.08784449435)
% (3, 227837.90635583305)
% % (4, 228874.24461547082)
% % (5, 241211.27667972192)
% % (6, 148226.924689852)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 343937.2340640109)
% (2, 377406.00780349335)
% (3, 389154.74239110027)
% % (4, 400234.6291817671)
% % (5, 385160.1255477292)
% % (6, 258020.25783571514)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 334524.3111484017)
% (2, 345105.97806245193)
% (3, 355606.9430577287)
% % (4, 342520.44030230143)
% % (5, 350951.3696242389)
% % (6, 230826.45675877255)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm1}
% \end{tikzpicture}
% % \label{fig:m1}
% }
% \subfigure[Latency (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=650,
% % ymode =log,
% % ytick={500,1000,1500,2000,2500},
% % yticklabels={500,1000,1500,2000,2500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 375.0027311737807)
% (2, 245.253054270679)
% (3, 202.02860452539656)
% % (4, 217.0033551677904)
% % (5, 206.05436777806932)
% % (6, 285.023505857191)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 353.00243357663766)
% (2, 321.5024109768546)
% (3, 335.72681292259597)
% % (4, 282.5029039721219)
% % (5, 245.0283751275988)
% % (6, 349.38200802785093)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 421.0348284656467)
% (2, 322.768110726137)
% (3, 320.12300581914417)
% % (4, 327.0413564029785)
% % (5, 331.968477602615)
% % (6, 408.6544217168574)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 358.0026111749327)
% (2, 205.00323106898176)
% (3, 198.5040127614775)
% % (4, 213.00324956880416)
% % (5, 197.55384768306226)
% % (6, 258.3676851229459)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm2}
% \end{tikzpicture}
% \label{fig:pm2}
% }
% % \label{fig:sm}
% \caption{Performance of single-thread and multi-thread mode}
% \label{fig:performance}
% \end{figure}
%-----------------arxiv防报错
\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{figures/performance_arxiv.pdf} % 确保路径和文件名正确
\caption{Performance of single-thread and multi-thread mode}
\label{fig:performance}
\end{figure}
% \begin{figure}
% \centering
% \hspace{0.5cm}
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% xmin=0.5, xmax=3.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge TierBase }
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Redis }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge Memcached }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge Dragonfly }
% \addlegendimage{pattern=myDenseLines, pattern color=red}
% \addlegendentry{\Large TierBase-4Nodes }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% %xlabel={\huge \bf YCSB Workload},
% scaled y ticks=false,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=50000,ymax=175000,
% ytick={60000,90000,120000,150000,180000},
% yticklabels={60,90,120,150,180,140},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge Throughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 113184.14666451453)
% (2, 131550.90779311996)
% (3, 135567.29744614722)
% % (4, 139309.9595670512)
% % (5, 138202.66983079497)
% % (6, 90078.07533793423)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 117631.35067095495)
% (2, 135074.06501342953)
% (3, 131875.15308675036)
% % (4, 138756.28128280398)
% % (5, 142136.77844571666)
% % (6, 87454.81189155314)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 112040.517451794)
% (2, 126989.00530465912)
% (3, 123591.10493517923)
% % (4, 125167.3375836492)
% % (5, 127281.74024610719)
% % (6, 83096.7468128943)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 103577.42007621226)
% (2, 108935.2282308765)
% (3, 110663.38966790958)
% % (4, 106739.07186153322)
% % (5, 114665.76116066572)
% % (6, 74361.5307874211)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% \label{fig:ps1}
% }
% \subfigure[Latency (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=350,
% % ymode =log,
% ytick={100,200,300},
% yticklabels={100,200,300},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 191.0013535956685)
% (2, 157.50129439585794)
% (3, 146.05137373560405)
% % (4, 144.50127519591936)
% % (5, 141.55130763581556)
% % (6, 194.62721168956716)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 189.0014239954432)
% (2, 157.75159169490658)
% (3, 168.57655045503856)
% % (4, 156.00134079570944)
% % (5, 148.57645435534607)
% % (6, 195.37448401168712)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 246.046959248652)
% (2, 177.5417928313147)
% (3, 259.3666346338459)
% % (4, 232.0445912865394)
% % (5, 225.06213000591993)
% % (6, 246.9976099930035)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 263.00131039580674)
% (2, 162.00134879568384)
% (3, 172.0012415960269)
% % (4, 174.5014959952128)
% % (5, 163.52632751575194)
% % (6, 206.50127761863314)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \label{fig:s2}
% }
% \subfigure[ Throughput (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% %xlabel={\huge \bf YCSB Workload},
% bar width=0.4cm,
% scaled y ticks=false,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=70000,ymax=600000,
% ytick={200000,400000,600000},
% yticklabels={200,400,600},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge Throughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=red] coordinates {
% (1, 4*113184.14666451453)
% (2, 4*131550.90779311996)
% (3, 4*135567.29744614722)
% % (4, 139309.9595670512)
% % (5, 138202.66983079497)
% % (6, 90078.07533793423)
% };
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 212064.3283560956)
% (2, 246772.0948768674)
% (3, 284127.97921917425)
% % (4, 306892.8597799601)
% % (5, 320624.2315092562)
% % (6, 193095.15061582578)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 194937.95124821865)
% (2, 209987.08784449435)
% (3, 227837.90635583305)
% % (4, 228874.24461547082)
% % (5, 241211.27667972192)
% % (6, 148226.924689852)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 343937.2340640109)
% (2, 377406.00780349335)
% (3, 389154.74239110027)
% % (4, 400234.6291817671)
% % (5, 385160.1255477292)
% % (6, 258020.25783571514)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 334524.3111484017)
% (2, 345105.97806245193)
% (3, 355606.9430577287)
% % (4, 342520.44030230143)
% % (5, 350951.3696242389)
% % (6, 230826.45675877255)
% };
% % \legend{ \huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm1}
% \end{tikzpicture}
% % \label{fig:m1}
% }
% \subfigure[Latency (multi-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.4cm,
% width=0.5\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% height=0.4\textwidth,
% % xlabel={\huge \bf Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=650,
% % ymode =log,
% % ytick={500,1000,1500,2000,2500},
% % yticklabels={500,1000,1500,2000,2500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines , pattern color=red] coordinates {
% (1, 1.1*375.0027311737807)
% (2, 1.12*245.253054270679)
% (3, 1.05*202.02860452539656)
% % (4, 217.0033551677904)
% % (5, 206.05436777806932)
% % (6, 285.023505857191)
% };
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 375.0027311737807)
% (2, 245.253054270679)
% (3, 202.02860452539656)
% % (4, 217.0033551677904)
% % (5, 206.05436777806932)
% % (6, 285.023505857191)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 353.00243357663766)
% (2, 321.5024109768546)
% (3, 335.72681292259597)
% % (4, 282.5029039721219)
% % (5, 245.0283751275988)
% % (6, 349.38200802785093)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 421.0348284656467)
% (2, 322.768110726137)
% (3, 320.12300581914417)
% % (4, 327.0413564029785)
% % (5, 331.968477602615)
% % (6, 408.6544217168574)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 358.0026111749327)
% (2, 205.00323106898176)
% (3, 198.5040127614775)
% % (4, 213.00324956880416)
% % (5, 197.55384768306226)
% % (6, 258.3676851229459)
% };
% % \legend{\huge TierBase, \huge Redis, \huge Memcached, \huge Dragonfly}
% \end{axis}
% \label{fig:pm2}
% \end{tikzpicture}
% \label{fig:pm2}
% }
% % \label{fig:sm}
% \caption{Performance of single-thread and multi-thread Mode}
% \label{fig:performance}
% \end{figure}
% \begin{figure*}
% \centering
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% xmin=0.5, xmax=5.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum width=1.6cm,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Write-though }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge Write-back }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge WAL-PMEM }
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge WAL }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput of TireBase with different persistence mechanisms]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.55cm,
% scaled y ticks=false,
% width=1\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=10000,ymax=175000,
% ytick={40000,80000,120000,160000},
% yticklabels={40,80,120,160,180},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge thoughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c1, fill opacity=1] coordinates {
% (1, 28483.56336136251)
% (2, 44045.48850457489)
% (3, 76762.72967523593)
% (4, 83887.42125300222)
% (5, 94710.70826941344)
% (6, 36263.906937612795)
% };
% \addplot [pattern=myDenseLines ,pattern color=c8, fill opacity=1] coordinates {
% (1, 73589.53393295176)
% (2, 93976.71790974036)
% (3, 121150.74146965306)
% (4, 129948.95449992928)
% (5, 126405.68284310657)
% (6, 67100.69057997446)
% };
% \addplot [pattern=myDenseLines ,pattern color=American Yellow, fill opacity=1] coordinates {
% (1, 60155.44166125268)
% (2, 84606.31445373365)
% (3, 118281.1278296468)
% (4, 130324.40977377175)
% (5, 112767.92736339974)
% (6, 60176.91818231142)
% };
% \addplot [pattern=myDenseLines , pattern color=c5, fill opacity=1] coordinates {
% (1, 74831.09013575716)
% (2, 85578.87720337728)
% (3, 129537.03463820307)
% (4, 137008.82336822493)
% (5, 129332.64355923435)
% (6, 69511.13462183573)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% } \hspace{1cm}
% \subfigure[Latency of TireBase with different persistence mechanisms]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.55cm,
% width=1\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=6.5,
% ymin=0,ymax=1650,
% % ymode =log,
% ytick={500,1000,1500},
% yticklabels={500,1000,1500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 1349.4978432069015)
% (2, 1139.903090310111)
% (3, 805.9100100879677)
% (4, 692.9997488008038)
% (5, 766.7290908669092)
% (6, 1194.7865052998136)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 588.0004991984025)
% (2, 474.2693369381218)
% (3, 325.20710783725497)
% (4, 303.0010735965645)
% (5, 316.4854830464543)
% (6, 548.0946955931641)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 711.996412811479)
% (2, 600.9122455808141)
% (3, 245.51516465147313)
% (4, 207.00191519387135)
% (5, 190.13208377733187)
% (6, 888.6072394130068)
% };
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 1140.997571207772)
% (2, 763.8141993945619)
% (3, 176.05137373560405)
% (4, 149.50127519591936)
% (5, 151.55130763581556)
% (6, 464.4514192629965)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% }
% \caption{Performance analysis of different data persistence mechanisms}
% \label{fig:ps}
% \end{figure*}
%-------------原图
% \begin{figure}
% \centering
% \hspace{0.8cm}
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% xmin=0.5, xmax=3.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum width=1.6cm,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge Write-through }
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Write-back }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge WAL-PMem }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge WAL }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput of TierBase with different persistence mechanisms]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% scaled y ticks=false,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=10000,ymax=175000,
% ytick={40000,80000,120000,160000},
% yticklabels={40,80,120,160,180},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge throughput ($k$ qps)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c5, fill opacity=1] coordinates {
% (1, 28483.56336136251)
% (2, 44045.48850457489)
% (3, 76762.72967523593)
% % (4, 83887.42125300222)
% % (5, 94710.70826941344)
% % (6, 36263.906937612795)
% };
% \addplot [pattern=myDenseLines ,pattern color=c1, fill opacity=1] coordinates {
% (1, 73589.53393295176)
% (2, 93976.71790974036)
% (3, 121150.74146965306)
% % (4, 129948.95449992928)
% % (5, 126405.68284310657)
% % (6, 67100.69057997446)
% };
% \addplot [pattern=myDenseLines ,pattern color=c8, fill opacity=1] coordinates {
% (1, 60155.44166125268)
% (2, 84606.31445373365)
% (3, 118281.1278296468)
% % (4, 130324.40977377175)
% % (5, 112767.92736339974)
% % (6, 60176.91818231142)
% };
% \addplot [pattern=myDenseLines , pattern color=c3, fill opacity=1] coordinates {
% (1, 74831.09013575716)
% (2, 85578.87720337728)
% (3, 129537.03463820307)
% % (4, 137008.82336822493)
% % (5, 129332.64355923435)
% % (6, 69511.13462183573)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% }
% \subfigure[Latency of TierBase with different persistence mechanisms]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=1650,
% % ymode =log,
% ytick={500,1000,1500},
% yticklabels={500,1000,1500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c5] coordinates {
% (1, 1349.4978432069015)
% (2, 1139.903090310111)
% (3, 805.9100100879677)
% % (4, 692.9997488008038)
% % (5, 766.7290908669092)
% % (6, 1194.7865052998136)
% };
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 588.0004991984025)
% (2, 474.2693369381218)
% (3, 325.20710783725497)
% % (4, 303.0010735965645)
% % (5, 316.4854830464543)
% % (6, 548.0946955931641)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 711.996412811479)
% (2, 600.9122455808141)
% (3, 245.51516465147313)
% % (4, 207.00191519387135)
% % (5, 190.13208377733187)
% % (6, 888.6072394130068)
% };
% \addplot [pattern=myDenseLines , pattern color=c3] coordinates {
% (1, 1140.997571207772)
% (2, 763.8141993945619)
% (3, 176.05137373560405)
% % (4, 149.50127519591936)
% % (5, 151.55130763581556)
% % (6, 464.4514192629965)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% }
% \caption{Performance of data persistence mechanisms}
% \label{fig:ps}
% \end{figure}
% \setlength{\textfloatsep}{10pt}
%-----------arxiv
\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{figures/persistence_arxiv.pdf} % 确保路径和文件名正确
\caption{Performance of different data persistence mechanisms}
\label{fig:ps}
\end{figure}
\setlength{\textfloatsep}{10pt}
% \begin{figure}
% \centering
% \hspace{0.5cm}
% \begin{tikzpicture}[scale=0.52]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=black},
% % legend image code/.code={
% % \draw[mark=-, mark size=5pt,] plot coordinates {(0cm,0cm) (0.3cm,0cm)};
% % \draw[mark=*, mark size=3pt,] plot coordinates { (0.15cm,0cm)};
% % },
% ytick={50000,100000,150000,200000},
% yticklabels={50,100,150,200},
% ticklabel style={font=\small},
% every axis plot/.append style={line width = 1pt},
% every axis/.append style={line width = 1pt},
% xmin=0.5, xmax=3.5,
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,minimum width=1.6cm,minimum height=1cm,
% draw=black},
% legend image code/.code={
% \draw [#1] (-0.5cm,-0.2cm) rectangle (0.5cm,0.2cm); },
% ]
% \addlegendimage{pattern=myDenseLines, pattern color=c1}
% \addlegendentry{\huge Write-through }
% \addlegendimage{pattern=myDenseLines, pattern color=c8}
% \addlegendentry{\huge Write-back }
% \addlegendimage{pattern=myDenseLines, pattern color=c3}
% \addlegendentry{\huge WAL-PMem }
% \addlegendimage{pattern=myDenseLines, pattern color=c5}
% \addlegendentry{\huge WAL }
% \end{axis}
% \end{tikzpicture}
% \subfigure[Throughput (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% scaled y ticks=false,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=10000,ymax=175000,
% ytick={40000,80000,120000,160000},
% yticklabels={40,80,120,160,180},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge Throughput ($k$ QPS)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c1, fill opacity=1] coordinates {
% (1, 28483.56336136251)
% (2, 44045.48850457489)
% (3, 76762.72967523593)
% % (4, 83887.42125300222)
% % (5, 94710.70826941344)
% % (6, 36263.906937612795)
% };
% \addplot [pattern=myDenseLines ,pattern color=c8, fill opacity=1] coordinates {
% (1, 73589.53393295176)
% (2, 93976.71790974036)
% (3, 121150.74146965306)
% % (4, 129948.95449992928)
% % (5, 126405.68284310657)
% % (6, 67100.69057997446)
% };
% \addplot [pattern=myDenseLines ,pattern color=American Yellow, fill opacity=1] coordinates {
% (1, 60155.44166125268)
% (2, 84606.31445373365)
% (3, 118281.1278296468)
% % (4, 130324.40977377175)
% % (5, 112767.92736339974)
% % (6, 60176.91818231142)
% };
% \addplot [pattern=myDenseLines , pattern color=c5, fill opacity=1] coordinates {
% (1, 74831.09013575716)
% (2, 85578.87720337728)
% (3, 129537.03463820307)
% % (4, 137008.82336822493)
% % (5, 129332.64355923435)
% % (6, 69511.13462183573)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps1}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% }
% \subfigure[Latency (single-thread)]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% ybar=0.45pt,
% bar width=0.45cm,
% width=0.5\textwidth,
% height=0.4\textwidth,
% % xlabel={\huge \bf YCSB Workload},
% xtick=data, xticklabels={\huge $Load$, \huge $A$,\huge $B$,\huge $C$,\huge $D$,\huge $F$},
% legend style={at={(0.5,0.98)},
% anchor=north,legend columns=-1,
% draw=none},
% legend image code/.code={
% \draw [#1] (0cm,-0.263cm) rectangle (1.2cm,0.085cm); },
% xmin=0.5,xmax=3.5,
% ymin=0,ymax=1650,
% % ymode =log,
% ytick={500,1000,1500},
% yticklabels={500,1000,1500},
% tick align=inside,
% ticklabel style={font=\huge},
% every axis plot/.append style={line width = 2pt},
% every axis/.append style={line width = 2.5pt},
% ylabel={\textbf{\huge p99 latency (us)}}
% ]
% \addplot [pattern=myDenseLines, pattern color=c1] coordinates {
% (1, 1349.4978432069015)
% (2, 1139.903090310111)
% (3, 805.9100100879677)
% % (4, 692.9997488008038)
% % (5, 766.7290908669092)
% % (6, 1194.7865052998136)
% };
% \addplot [pattern=myDenseLines, pattern color=c8] coordinates {
% (1, 588.0004991984025)
% (2, 474.2693369381218)
% (3, 325.20710783725497)
% % (4, 303.0010735965645)
% % (5, 316.4854830464543)
% % (6, 548.0946955931641)
% };
% \addplot [pattern=myDenseLines, pattern color=c3] coordinates {
% (1, 711.996412811479)
% (2, 600.9122455808141)
% (3, 245.51516465147313)
% % (4, 207.00191519387135)
% % (5, 190.13208377733187)
% % (6, 888.6072394130068)
% };
% \addplot [pattern=myDenseLines , pattern color=c5] coordinates {
% (1, 1140.997571207772)
% (2, 763.8141993945619)
% (3, 176.05137373560405)
% % (4, 149.50127519591936)
% % (5, 151.55130763581556)
% % (6, 464.4514192629965)
% };
% % \legend{\huge TierBase, \huge WriteThough, \huge WriteBack, \huge AEP}
% \end{axis}
% \label{fig:ps2}
% \end{tikzpicture}
% % \vspace{-3mm}
% % \caption{Single-thread}
% % \label{1grampruning}
% %\vspace*{-0.2cm}
% }
% \caption{Performance of different data persistence mechanisms}
% \label{fig:ps}
% \end{figure}
% % Please add the following required packages to your document preamble:
% % \usepackage{multirow}
% {
% \scriptsize
% \begin{table*}[h!]
% \centering
% \renewcommand{\arraystretch}{1.2}
% \tiny
% \resizebox{\textwidth}{!}{%
% \begin{tabular}{c|cc|cc|ccc|ccc}
% \hline
% \multirow{2}{*}{Datssets} & \multicolumn{2}{c|}{\begin{tabular}[c]{@{}c@{}}Comp. Ratio\\ (\%)\end{tabular}} & \multicolumn{2}{c|}{\begin{tabular}[c]{@{}c@{}}Overall Comp. Ratio\\ (\%)\end{tabular}} & \multicolumn{3}{c|}{\begin{tabular}[c]{@{}c@{}}Average SET\\ Throughput(QPS)\end{tabular}} & \multicolumn{3}{c}{\begin{tabular}[c]{@{}c@{}}Average GET\\ Throughput(QPS)\end{tabular}} \\ \cline{2-11}
% & \multicolumn{1}{c|}{PBC} & Zstd & \multicolumn{1}{c|}{PBC} & Zstd & \multicolumn{1}{c|}{PBC} & \multicolumn{1}{c|}{Zstd} & Uncompressed & \multicolumn{1}{c|}{PBC} & \multicolumn{1}{c|}{Zstd} & Uncompressed \\ \hline
% cities & \multicolumn{1}{c|}{\textbf{20.03}} & 29.20 & \multicolumn{1}{c|}{\textbf{49.19}} & 55.08 & \multicolumn{1}{c|}{54469} & \multicolumn{1}{c|}{\textbf{61667}} & 122324 & \multicolumn{1}{c|}{\textbf{109998}} & \multicolumn{1}{c|}{96861} & 138045 \\ \hline
% unece & \multicolumn{1}{c|}{\textbf{8.48}} & 10.23 & \multicolumn{1}{c|}{\textbf{11.41}} & 13.25 & \multicolumn{1}{c|}{5681} & \multicolumn{1}{c|}{\textbf{13904}} & 60045 & \multicolumn{1}{c|}{\textbf{34752}} & \multicolumn{1}{c|}{27297} & 65214 \\ \hline
% github & \multicolumn{1}{c|}{\textbf{7.42}} & 9.89 & \multicolumn{1}{c|}{\textbf{17.69}} & 22.09 & \multicolumn{1}{c|}{17332} & \multicolumn{1}{c|}{\textbf{51867}} & 110803 & \multicolumn{1}{c|}{\textbf{100563}} & \multicolumn{1}{c|}{81083} & 120195 \\ \hline
% KV1 & \multicolumn{1}{c|}{\textbf{23.41}} & 40.42 & \multicolumn{1}{c|}{\textbf{68.84}} & 75.94 & \multicolumn{1}{c|}{74878} & \multicolumn{1}{c|}{\textbf{75018}} & 122414 & \multicolumn{1}{c|}{\textbf{119688}} & \multicolumn{1}{c|}{112866} & 132397 \\ \hline
% KV2 & \multicolumn{1}{c|}{\textbf{22.97}} & 40.96 & \multicolumn{1}{c|}{\textbf{62.19}} & 71.17 & \multicolumn{1}{c|}{65329} & \multicolumn{1}{c|}{\textbf{67558}} & 120496 & \multicolumn{1}{c|}{\textbf{115888}} & \multicolumn{1}{c|}{102616} & 132961 \\ \hline
% \end{tabular}
% }
% \vspace{9pt}
% \caption{Compression evaluation}
% \label{fig:compress study}
% \end{table*}
% }
% Please add the following required packages to your document preamble:
% \usepackage{multirow}
% {
% \large
% \begin{table*}[h!]
% \centering
% \renewcommand{\arraystretch}{1.3}
% \tiny
% \resizebox{\textwidth}{!}{%
% \begin{tabular}{c|ccc|ccc|cccc|cccc}
% \hline
% \multirow{2}{*}{Datssets} & \multicolumn{3}{c|}{Comp. Ratio} & \multicolumn{3}{c|}{Overall Comp. Ratio} & \multicolumn{4}{c|}{Thoughput (set)} & \multicolumn{4}{c}{Thoughput (get)} \\ \cline{2-15}
% & \multicolumn{1}{c|}{Zstd\_nodict} & \multicolumn{1}{c|}{Zstd\_dict} & PBC & \multicolumn{1}{c|}{Zstd\_nodict} & \multicolumn{1}{c|}{Zstd\_dict} & PBC & \multicolumn{1}{c|}{Zstd\_nodict} & \multicolumn{1}{c|}{Zstd\_dict} & \multicolumn{1}{c|}{PBC} & Uncompressed & \multicolumn{1}{c|}{Zstd\_nodict} & \multicolumn{1}{c|}{Zstd\_dict} & \multicolumn{1}{c|}{PBC} & Uncompressed \\ \hline
% cities & \multicolumn{1}{c|}{0.7372} & \multicolumn{1}{c|}{0.2920} & \textbf{0.2003} & \multicolumn{1}{c|}{0.8350} & \multicolumn{1}{c|}{0.5508} & \textbf{0.4919} & \multicolumn{1}{c|}{29768} & \multicolumn{1}{c|}{\textbf{61667}} & \multicolumn{1}{c|}{54469} & 122324 & \multicolumn{1}{c|}{49473} & \multicolumn{1}{c|}{96861} & \multicolumn{1}{c|}{\textbf{109998}} & 138045 \\ \hline
% unece & \multicolumn{1}{c|}{0.3727} & \multicolumn{1}{c|}{0.1023} & \textbf{0.0848} & \multicolumn{1}{c|}{0.3976} & \multicolumn{1}{c|}{0.1325} & \textbf{0.1141} & \multicolumn{1}{c|}{6673} & \multicolumn{1}{c|}{\textbf{13904}} & \multicolumn{1}{c|}{5681} & 60045 & \multicolumn{1}{c|}{11986} & \multicolumn{1}{c|}{27297} & \multicolumn{1}{c|}{\textbf{34752}} & 65214 \\ \hline
% github & \multicolumn{1}{c|}{0.3465} & \multicolumn{1}{c|}{0.0989} & \textbf{0.0742} & \multicolumn{1}{c|}{0.4458} & \multicolumn{1}{c|}{0.2209} & \textbf{0.1769} & \multicolumn{1}{c|}{23628} & \multicolumn{1}{c|}{\textbf{51867}} & \multicolumn{1}{c|}{17332} & 110803 & \multicolumn{1}{c|}{41914} & \multicolumn{1}{c|}{81083} & \multicolumn{1}{c|}{\textbf{100563}} & 96348 \\ \hline
% KV1 & \multicolumn{1}{c|}{0.9081} & \multicolumn{1}{c|}{0.4042} & \textbf{0.2341} & \multicolumn{1}{c|}{0.9635} & \multicolumn{1}{c|}{0.7594} & \textbf{0.6884} & \multicolumn{1}{c|}{53146} & \multicolumn{1}{c|}{\textbf{75018}} & \multicolumn{1}{c|}{74878} & 122414 & \multicolumn{1}{c|}{93101} & \multicolumn{1}{c|}{112866} & \multicolumn{1}{c|}{\textbf{119688}} & 132397 \\ \hline
% KV2 & \multicolumn{1}{c|}{0.9225} & \multicolumn{1}{c|}{0.4096} & \textbf{0.2297} & \multicolumn{1}{c|}{0.9625} & \multicolumn{1}{c|}{0.7117} & \textbf{0.6219} & \multicolumn{1}{c|}{37072} & \multicolumn{1}{c|}{\textbf{67558}} & \multicolumn{1}{c|}{65329} & 120496 & \multicolumn{1}{c|}{71999} & \multicolumn{1}{c|}{102616} & \multicolumn{1}{c|}{\textbf{115888}} & 132961 \\ \hline
% \end{tabular}
% }
% \vspace{9pt}
% \caption{Compression evaluation}
% \label{fig:compress study}
% \end{table*}
% }
% {
% \begin{table*}[h!]
% \centering
% \renewcommand{\arraystretch}{1.2}
% \normalsize
% \resizebox{\textwidth}{!}{%
% \begin{tabular}{c|ccc|ccc|cccc|cccc}
% \hline
% \multirow{2}{*}{Datssets} & \multicolumn{3}{c|}{Comp. Ratio} & \multicolumn{3}{c|}{Overall Comp. Ratio} & \multicolumn{4}{c|}{Thoughput (SET)} & \multicolumn{4}{c}{Thoughput (GET)} \\ \cline{2-15}
% & \multicolumn{1}{c|}{Zstd-b} & \multicolumn{1}{c|}{Zstd-d} & PBC & \multicolumn{1}{c|}{Zstd-b} & \multicolumn{1}{c|}{Zstd-d} & PBC & \multicolumn{1}{c|}{Zstd-b} & \multicolumn{1}{c|}{Zstd-d} & \multicolumn{1}{c|}{PBC} & Raw & \multicolumn{1}{c|}{Zstd-b} & \multicolumn{1}{c|}{Zstd-d} & \multicolumn{1}{c|}{PBC} & Raw \\ \hline
% cities & \multicolumn{1}{c|}{0.7372} & \multicolumn{1}{c|}{\underline{0.2920}} & \textbf{0.2003} & \multicolumn{1}{c|}{0.8350} & \multicolumn{1}{c|}{\underline{0.5508}} & \textbf{0.4919} & \multicolumn{1}{c|}{29768} & \multicolumn{1}{c|}{\underline{61667}} & \multicolumn{1}{c|}{54469} & \textbf{122324} & \multicolumn{1}{c|}{49473} & \multicolumn{1}{c|}{96861} & \multicolumn{1}{c|}{\underline{109998}} & \textbf{138045} \\ \hline
% unece & \multicolumn{1}{c|}{0.3727} & \multicolumn{1}{c|}{\underline{0.1023}} & \textbf{0.0848} & \multicolumn{1}{c|}{0.3976} & \multicolumn{1}{c|}{\underline{0.1325}} & \textbf{0.1141} & \multicolumn{1}{c|}{6673} & \multicolumn{1}{c|}{\underline{13904}} & \multicolumn{1}{c|}{5681} & \textbf{60045} & \multicolumn{1}{c|}{11986} & \multicolumn{1}{c|}{27297} & \multicolumn{1}{c|}{\underline{34752}} & \textbf{65214} \\ \hline
% github & \multicolumn{1}{c|}{0.3465} & \multicolumn{1}{c|}{\underline{0.0989}} & \textbf{0.0742} & \multicolumn{1}{c|}{0.4458} & \multicolumn{1}{c|}{\underline{0.2209}} & \textbf{0.1769} & \multicolumn{1}{c|}{23628} & \multicolumn{1}{c|}{\underline{51867}} & \multicolumn{1}{c|}{17332} & \textbf{110803} & \multicolumn{1}{c|}{41914} & \multicolumn{1}{c|}{81083} & \multicolumn{1}{c|}{\underline{100563}} & \textbf{133527} \\ \hline
% KV1 & \multicolumn{1}{c|}{0.9081} & \multicolumn{1}{c|}{\underline{0.4042}} & \textbf{0.2341} & \multicolumn{1}{c|}{0.9635} & \multicolumn{1}{c|}{\underline{0.7594}} & \textbf{0.6884} & \multicolumn{1}{c|}{53146} & \multicolumn{1}{c|}{\underline{75018}} & \multicolumn{1}{c|}{74878} & \textbf{122414} & \multicolumn{1}{c|}{93101} & \multicolumn{1}{c|}{112866} & \multicolumn{1}{c|}{\underline{119688}} & \textbf{132397} \\ \hline
% KV2 & \multicolumn{1}{c|}{0.9225} & \multicolumn{1}{c|}{\underline{0.4096}} & \textbf{0.2297} & \multicolumn{1}{c|}{0.9625} & \multicolumn{1}{c|}{\underline{0.7117}} & \textbf{0.6219} & \multicolumn{1}{c|}{37072} & \multicolumn{1}{c|}{\underline{67558}} & \multicolumn{1}{c|}{65329} & \textbf{120496} & \multicolumn{1}{c|}{71999} & \multicolumn{1}{c|}{102616} & \multicolumn{1}{c|}{\underline{115888}} & \textbf{132961} \\ \hline
% \end{tabular}
% }
% \vspace{9pt}
% \caption{Evaluation of compression techniques}
% \label{fig:compress study}
% \end{table*}
% }
% Please add the following required packages to your document preamble:
% \usepackage{multirow}
% {\small
% \begin{table}[]
% \begin{tabular}{cc|c|c|c}
% \hline
% \multicolumn{2}{c|}{Datasets} & cities & \multicolumn{1}{c|}{KV1} & \multicolumn{1}{c}{KV2} \\ \hline
% \multicolumn{1}{c|}{\multirow{2}{*}{Comp. Ratio}} & PBC & \textbf{0.2003} & \textbf{0.2341} & \textbf{0.2297} \\
% \multicolumn{1}{c|}{} & Zstd & 0.2920 & 0.4042 & 0.4096 \\ \hline
% \multicolumn{1}{c|}{\multirow{2}{*}{\begin{tabular}[c]{@{}c@{}}Overall \\ Comp. Ratio\end{tabular}}} & PBC & \textbf{0.4919} & \textbf{0.6884} & \textbf{0.6219} \\
% \multicolumn{1}{c|}{} & Zstd & 0.5508 & 0.7594 & 0.7117 \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (SET)\end{tabular}}} & PBC & 54469 & 74878 & 65329 \\
% \multicolumn{1}{c|}{} & Zstd & 61667 & 75018 & 67558 \\
% \multicolumn{1}{c|}{} & Raw & \textbf{122324} & \textbf{122414} & \textbf{120496} \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (GET)\end{tabular}}} & PBC & 109998 & 119688 & 115888 \\
% \multicolumn{1}{c|}{} & Zstd & 96861 & 112866 & 102616 \\
% \multicolumn{1}{c|}{} & Raw & \textbf{138045} & \textbf{132397} & \textbf{132961} \\ \hline
% \end{tabular}
% \vspace{11pt}
% \caption{Evaluation of compression techniques}
% \label{fig:compress study}
% \end{table}
% }
% \setlength{\textfloatsep}{10pt}
% Please add the following required packages to your document preamble:
% \usepackage{multirow}
% Please add the following required packages to your document preamble:
% \usepackage{multirow}
% \usepackage[normalem]{ulem}
% \useunder{\uline}{\ul}{}
% \begin{table}[]
% \begin{tabular}{cc|c|c|c}
% \hline
% \multicolumn{2}{c|}{Datssets} & cities & \multicolumn{1}{l|}{KV1} & \multicolumn{1}{l}{KV2} \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{Comp. Ratio}} & PBC & \textbf{0.2003} & \textbf{0.2341} & \textbf{0.2297} \\
% \multicolumn{1}{c|}{} & Zstd-d & {\ul 0.292} & {\ul 0.4042} & {\ul 0.4096} \\
% \multicolumn{1}{c|}{} & Zstd-b & 0.7372 & 0.9081 & 0.9225 \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Overall \\ Comp. Ratio\end{tabular}}} & PBC & \textbf{0.4919} & \textbf{0.6884} & \textbf{0.6219} \\
% \multicolumn{1}{c|}{} & Zstd-d & {\ul 0.5508} & {\ul 0.7594} & {\ul 0.7117} \\
% \multicolumn{1}{c|}{} & Zstd-b & 0.835 & 0.9635 & 0.9625 \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (SET)\end{tabular}}} & PBC & 54469 & 74878 & 65329 \\
% \multicolumn{1}{c|}{} & Zstd-d & {\ul 61667} & {\ul 75018} & {\ul 67558} \\
% \multicolumn{1}{c|}{} & Raw & \textbf{122324} & \textbf{122414} & \textbf{120496} \\ \hline
% \multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (GET)\end{tabular}}} & PBC & {\ul 109998} & {\ul 119688} & {\ul 115888} \\
% \multicolumn{1}{c|}{} & Zstd-d & 96861 & 112866 & 102616 \\
% \multicolumn{1}{c|}{} & Raw & \textbf{138045} & \textbf{132397} & \textbf{132961} \\ \hline
% \end{tabular}
% \end{table}
% {\footnotesize
% \begin{table}[]
% \begin{tabular}{c|cc|cc|ccc|ccc}
% \hline
% \multirow{2}{*}{Datesets} & \multicolumn{2}{c|}{Comp. Ratio} & \multicolumn{2}{c|}{\begin{tabular}[c]{@{}c@{}}Overall \\ Comp. Ratio\end{tabular}} & \multicolumn{3}{c|}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (set)\end{tabular}} & \multicolumn{3}{c}{\begin{tabular}[c]{@{}c@{}}Thoughput\\ (get)\end{tabular}} \\ \cline{2-11}
% & \multicolumn{1}{c|}{PBC} & Zstd & \multicolumn{1}{c|}{PBC} & Zstd & \multicolumn{1}{c|}{PBC} & \multicolumn{1}{c|}{Zstd} & Raw & \multicolumn{1}{c|}{PBC} & \multicolumn{1}{c|}{Zstd} & Raw \\ \hline
% cities & \multicolumn{1}{c|}{\textbf{0.2003}} & 0.292 & \multicolumn{1}{c|}{\textbf{0.4919}} & 0.5508 & \multicolumn{1}{c|}{54469} & \multicolumn{1}{c|}{61667} & \textbf{122324} & \multicolumn{1}{c|}{109998} & \multicolumn{1}{c|}{96861} & \textbf{138045} \\
% KV1 & \multicolumn{1}{c|}{\textbf{0.2341}} & 0.4042 & \multicolumn{1}{c|}{\textbf{0.6884}} & 0.7594 & \multicolumn{1}{c|}{74878} & \multicolumn{1}{c|}{75018} & \textbf{122324} & \multicolumn{1}{c|}{119688} & \multicolumn{1}{c|}{112866} & \textbf{132397} \\
% KV2 & \multicolumn{1}{c|}{\textbf{0.2297}} & 0.4096 & \multicolumn{1}{c|}{\textbf{0.6219}} & 0.7117 & \multicolumn{1}{c|}{65329} & \multicolumn{1}{c|}{67558} & \textbf{120496} & \multicolumn{1}{c|}{115888} & \multicolumn{1}{c|}{102616} & \textbf{132961} \\ \hline
% \end{tabular}
% \end{table}
% }
\begin{table}[]
\centering
\caption{Evaluation of compression techniques}
\begin{tabular}{cc|c|c|c}
\hline
\multicolumn{2}{c|}{Datasets} & Cities & \multicolumn{1}{l|}{KV1} & \multicolumn{1}{l}{KV2} \\ \hline
\multicolumn{1}{c|}{\multirow{2}{*}{Comp. Ratio}} & PBC & \textbf{0.2003} & \textbf{0.2341} & \textbf{0.2297} \\
\multicolumn{1}{c|}{} & Zstd & 0.2920 & 0.4042 & 0.4096 \\ \hline
\multicolumn{1}{c|}{\multirow{2}{*}{\begin{tabular}[c]{@{}c@{}}Overall \\ Comp. Ratio\end{tabular}}} & PBC & \textbf{0.4919} & \textbf{0.6884} & \textbf{0.6219} \\
\multicolumn{1}{c|}{} & Zstd & 0.5508 & 0.7594 & 0.7117 \\ \hline
\multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Throughput\\ (SET)\end{tabular}}} & PBC & 54469 & 74878 & 65329 \\
\multicolumn{1}{c|}{} & Zstd & 61667 & 75018 & 67558 \\
\multicolumn{1}{c|}{} & Raw & \textbf{122324} & \textbf{122414} & \textbf{120496} \\ \hline
\multicolumn{1}{c|}{\multirow{3}{*}{\begin{tabular}[c]{@{}c@{}}Throughput\\ (GET)\end{tabular}}} & PBC & 109998 & 119688 & 115888 \\
\multicolumn{1}{c|}{} & Zstd & 96861 & 112866 & 102616 \\
\multicolumn{1}{c|}{} & Raw & \textbf{138045} & \textbf{132397} & \textbf{132961} \\ \hline
\end{tabular}
\label{fig:compress study}
\end{table}
\begin{figure}[t]
\centering
\begin{tikzpicture}[scale=0.6]
\hspace{0.1cm}
\begin{axis}[
hide axis,
scale only axis,
height=0pt,
width=100pt,
% grid=major, % 显示网格
legend style={anchor=north west,legend columns=5,font=\Large,fill opacity=0.7, draw opacity=1, row sep=-4pt,draw=black, thick,line width=1pt},
legend image post style={line width=2pt, scale=1},
xmin=0, xmax=1, ymin=0, ymax=1,
]
\addlegendimage{color=c4,mark=none,line width=2pt}
\addlegendentry{TierBase-s}
\addlegendimage{color=c5,mark=none,line width=2pt}
\addlegendentry{TierBase-e}
\addlegendimage{color=c8,mark=none,line width=2pt}
\addlegendentry{TierBase-m}
\addlegendimage{color=c1,mark=none,line width=2pt}
\addlegendentry{Redis-s}
\addlegendimage{color=c3,mark=none,line width=2pt}
\addlegendentry{Redis-m}
\end{axis}
%\vspace{-0.7cm}
\end{tikzpicture}
%-------------------突发流量延迟-----------------------
% \subfigure[Latency over time]{
% \begin{tikzpicture}[scale=0.42]
% \begin{axis}[
% % width=9cm, % 设置图的宽度为一列的宽度
% % height=5cm,
% width=1\textwidth,
% height=0.4\textwidth,
% % grid=major, % 显示网格
% xlabel={\textbf{\Huge time(s)}},
% ylabel={\textbf{\Huge latency (us)}},
% legend pos=north west, % 图例位置
% legend style={at={(0.13,1.2)},legend columns=4,font=\Huge,fill opacity=0.7, draw opacity=1, row sep=-4pt,draw=black, thick,line width=2pt},
% legend image post style={line width=2pt, scale=1},%图例的线条长度
% xlabel near ticks, % 将xlabel靠近x轴的刻度
% ylabel near ticks,
% tick label style={font=\large},
% tickwidth=3pt,
% axis line style={line width=2pt}, %加粗边线
% xtick={0,10,20,30,40,50,60},
% ytick={100,200,300},
% tick label style={font=\huge},
% xmin=0, % 确保x轴从0开始
% ymin=0, % 确保y轴从0开始
% xmax=60,
% ymax=300,
% % scaled y ticks=false,
% ]
% % 折线数据
% %tbasemul
% \addplot[color=c4,mark=none,line width=2.5pt] coordinates {
% (0.0,119.2897517134735)
% (0.5,119.2897517134735)(1.0,114.76720003252765)(1.5,116.57475032994773)(2.0,161.44570392264802)(2.5,119.85660763569274)(3.0,113.30109220659884)(3.5,115.82165945219174)(4.0,113.4748874978552)(4.5,116.92974058072863)(5.0,117.13993993686458)(5.5,118.58083367723485)(6.0,115.43098726661228)(6.5,116.43842444497588)(7.0,117.25369062706741)(7.5,117.689730463156)(8.0,116.01334398461684)(8.5,116.55402218323871)(9.0,117.28983569389081)(9.5,116.40159821124232)(10.0,117.398111257869)(10.5,114.7477657858191)(11.0,113.66481398037561)(11.5,113.30420606358055)(12.0,114.04298309779102)(12.5,115.1237426508775)(13.0,115.47896590894484)(13.5,113.38690041427856)(14.0,116.17841279426798)(14.5,114.58779751618627)(15.0,196.63404296981147)(15.5,213.71285642965773)(16.0,222.47412831565697)(16.5,220.5778651490173)(17.0,223.65575178289578)(17.5,226.72818945498634)(18.0,225.50963189528224)(18.5,226.32356478012963)(19.0,230.3849817194232)(19.5,227.431096854274)(20.0,227.30660491329508)(20.5,226.19315022746736)(21.0,224.50064453508364)(21.5,226.30097651175421)(22.0,223.64156906751762)(22.5,226.22523832661798)(23.0,224.13968233891134)(23.5,223.6452934650052)(24.0,223.89988034720201)(24.5,226.34421644812852)(25.0,230.59997311089342)(25.5,225.09598059563402)(26.0,224.32020903043878)(26.5,224.01072293739617)(27.0,223.88901331094792)(27.5,223.831682139721)(28.0,223.86199405742087)(28.5,224.4433110884423)(29.0,223.47720775014272)(29.5,227.94799012080742)(30.0,225.82371968147143)(30.5,224.45994302896764)(31.0,226.01893846682984)(31.5,225.48208441328856)(32.0,223.0825968532155)(32.5,224.10804876432195)(33.0,221.90592833522598)(33.5,225.22355862751044)(34.0,222.1330228922902)(34.5,225.0162523572967)(35.0,223.5792044212672)(35.5,228.7083808674691)(36.0,226.19562651257274)(36.5,224.59742098762618)(37.0,224.77888184758498)(37.5,224.8870061069472)(38.0,221.97453889642117)(38.5,225.39979243956031)(39.0,229.79391141046702)(39.5,227.49600203858995)(40.0,222.77794723424483)(40.5,223.84953192339566)(41.0,222.1163868540845)(41.5,225.007550740204)(42.0,223.82043587175093)(42.5,231.42897442183894)(43.0,223.35827895968123)(43.5,225.57452514073833)(44.0,223.79341812497864)(44.5,225.78302705972544)(45.0,126.0417817221087)(45.5,113.530632435396)(46.0,113.87066236305604)(46.5,115.49974903816668)(47.0,114.7120349568819)(47.5,116.94511212059501)(48.0,115.80345302099335)(48.5,118.46984870068792)(49.0,116.01300439666011)(49.5,120.41119146256173)(50.0,116.91457889812466)(50.5,120.05154972351541)(51.0,128.040050977027)(51.5,126.99895060560578)(52.0,126.29632738518501)(52.5,127.27807052947053)(53.0,126.43347808966418)(53.5,131.45894201749098)(54.0,126.62761296917995)(54.5,127.29501669559582)(55.0,126.73733012374001)(55.5,133.12057384031704)(56.0,126.46487489446744)(56.5,128.21100657701993)(57.0,126.85974703224721)(57.5,128.3662558629166)(58.0,126.96171516748693)(58.5,127.18419213935306)(59.0,124.69071426569113)(59.5,126.96921796911076)(60.0,126.96921796911076)
% };
% % \addlegendentry{TierBaseone}
% \addplot[color=c8,mark=none,line width=2.5pt] coordinates {
% (0.0,87.44947816788324)
% (0.5,87.44947816788324)(1.0,82.95976205459499)(1.5,84.56460548599317)(2.0,102.48860400270217)(2.5,83.16106699275976)(3.0,82.35824674520333)(3.5,83.35856895378024)(4.0,82.99586833769453)(4.5,85.13630968945522)(5.0,85.03794695945447)(5.5,82.67853466179128)(6.0,81.88946963853982)(6.5,82.1906191186546)(7.0,81.90572678521117)(7.5,83.03952198817868)(8.0,83.08328687407612)(8.5,86.22445464585282)(9.0,105.3710115021797)(9.5,82.43576602988915)(10.0,82.39953059260853)(10.5,82.44684925338186)(11.0,88.00088927350676)(11.5,85.11920103108257)(12.0,87.61209080650804)(12.5,86.63891403329583)(13.0,84.21319169742836)(13.5,83.87595751208025)(14.0,82.39864041319007)(14.5,82.86055258467024)(15.0,99.43528704777134)(15.5,105.61888489903473)(16.0,104.83634911890309)(16.5,106.92928205415396)(17.0,108.20038072624604)(17.5,106.99360536930817)(18.0,105.84193017586489)(18.5,108.04330003174118)(19.0,106.02356605141426)(19.5,107.1583711840482)(20.0,110.04042000211547)(20.5,107.31100891465121)(21.0,105.83572214182598)(21.5,110.51736372038263)(22.0,107.5457055727745)(22.5,112.40575899944996)(23.0,103.95644265386319)(23.5,107.2751614288245)(24.0,108.30510985109423)(24.5,106.81281627546244)(25.0,105.29082661469647)(25.5,105.96273848689736)(26.0,103.88133557812115)(26.5,105.53149227021058)(27.0,106.5989731747971)(27.5,106.59094641550678)(28.0,108.23103952234956)(28.5,106.08536219743362)(29.0,105.1638183545661)(29.5,107.5026875793562)(30.0,107.0673048306221)(30.5,107.5933266984355)(31.0,105.23103656186713)(31.5,106.78622888095109)(32.0,105.64311526950323)(32.5,106.69739999639464)(33.0,109.30305977332831)(33.5,115.03510469827208)(34.0,105.65350147768379)(34.5,108.06999662413051)(35.0,107.98693771146486)(35.5,107.06085439225227)(36.0,105.18614408032184)(36.5,111.30950792417678)(37.0,104.74598404018487)(37.5,106.70193047414028)(38.0,104.82087624614363)(38.5,105.84853740442847)(39.0,106.65177858376677)(39.5,110.72771245449167)(40.0,111.77453325800536)(40.5,109.63036817768102)(41.0,105.28896269506157)(41.5,106.25069411283853)(42.0,109.40669646538026)(42.5,111.54092489141055)(43.0,107.83685239577407)(43.5,110.49983343897205)(44.0,107.55769761567632)(44.5,111.25200498568773)(45.0,82.8196956487279)(45.5,82.80906679136706)(46.0,83.14052456170127)(46.5,86.1427614771356)(47.0,83.58758210168071)(47.5,85.0800532049019)(48.0,83.61720379499042)(48.5,82.40473372139834)(49.0,84.74377705108627)(49.5,82.78811022469736)(50.0,84.0027867847148)(50.5,83.14384759462835)(51.0,84.6269857917274)(51.5,88.16608918923353)(52.0,84.89220432243681)(52.5,81.85470481436576)(53.0,83.30746356765178)(53.5,85.67134018759018)(54.0,84.17133400322476)(54.5,85.0366251978628)(55.0,86.97222709367432)(55.5,82.9143744858047)(56.0,83.492217865383)(56.5,82.19823591356285)(57.0,83.1756)(57.5,83.09697915947567)(58.0,91.79862581889662)(58.5,83.59772374045656)(59.0,82.9901964005937)(59.5,82.50087478085186)(60.0,82.50087478085186)
% };
% % \addlegendentry{TierBasemul}
% \addplot[color=c1,mark=none,line width=2.5pt] coordinates {
% (0.0,109.92914684249139)
% (0.5,109.92914684249139)(1.0,113.41947549355405)(1.5,109.36446995794111)(2.0,172.62723025311146)(2.5,109.70838674643022)(3.0,109.45519110482087)(3.5,109.21936282850689)(4.0,109.29137740926777)(4.5,113.53246563246563)(5.0,109.10303405136345)(5.5,109.63306546419454)(6.0,109.27723539511857)(6.5,109.38148006620304)(7.0,109.71930649373351)(7.5,109.81888973834722)(8.0,110.98956381806069)(8.5,110.38550703245387)(9.0,140.94951365823772)(9.5,109.6078265288397)(10.0,108.27550612974017)(10.5,108.85897079514172)(11.0,108.93145721128235)(11.5,109.89222451324167)(12.0,111.07410628979142)(12.5,111.35699970199612)(13.0,113.15200011290204)(13.5,109.14339296256776)(14.0,110.05239740993763)(14.5,108.43198162474368)(15.0,173.9973726712295)(15.5,194.267227746253)(16.0,190.3240052492808)(16.5,188.48637619406077)(17.0,189.75402836434517)(17.5,195.78712051114522)(18.0,192.0820007487448)(18.5,191.03577737721602)(19.0,191.38884531485775)(19.5,191.7347626499735)(20.0,192.07781913747047)(20.5,191.14775119785247)(21.0,190.27650507678152)(21.5,193.23718380030056)(22.0,191.03705170120304)(22.5,197.34816280177864)(23.0,191.3226204608382)(23.5,189.75040372268273)(24.0,189.88521799245711)(24.5,195.3112188116283)(25.0,189.98798066626605)(25.5,191.48156130252855)(26.0,185.95613552877546)(26.5,188.39507710191356)(27.0,189.87546106318365)(27.5,190.36347028383565)(28.0,189.1249471263274)(28.5,189.8111882112516)(29.0,192.7949431861872)(29.5,191.49300557040812)(30.0,188.95748940646348)(30.5,189.57306471597312)(31.0,190.04244095315016)(31.5,187.04619375208063)(32.0,189.05999417088148)(32.5,189.515912896818)(33.0,189.62523857854035)(33.5,189.82154429878983)(34.0,192.03252988955353)(34.5,190.10176647897515)(35.0,189.53925136314058)(35.5,192.87932536751072)(36.0,191.7890785511874)(36.5,191.34476149222417)(37.0,188.96473304633582)(37.5,189.33093758635846)(38.0,188.95825521925488)(38.5,189.36255899989794)(39.0,189.31349590280897)(39.5,188.2462231810278)(40.0,190.35501293667267)(40.5,190.11996341139354)(41.0,189.6132355336264)(41.5,204.81648734114)(42.0,191.27138274737686)(42.5,193.1478707975619)(43.0,191.24297273452794)(43.5,192.97001348097663)(44.0,190.45888708609897)(44.5,191.56512070317922)(45.0,110.89134516742726)(45.5,108.65710485280174)(46.0,108.91392700816348)(46.5,109.41087044209553)(47.0,110.13645002695031)(47.5,109.31942180348872)(48.0,109.04439405829449)(48.5,112.3822336252174)(49.0,108.87205864320222)(49.5,109.01938802859856)(50.0,108.94763210852335)(50.5,110.93430864380127)(51.0,108.50718278432095)(51.5,109.32057203978894)(52.0,108.63983481707568)(52.5,110.75242311308097)(53.0,108.88822727026377)(53.5,109.62435388738874)(54.0,111.66363016807998)(54.5,108.60129899650815)(55.0,108.87897550332457)(55.5,108.33661219512194)(56.0,108.06637116508819)(56.5,109.04570819039637)(57.0,107.59753443848385)(57.5,110.33688316933353)(58.0,108.34641395963511)(58.5,108.5124728640177)(59.0,108.254016831049)(59.5,112.91032118085239)(60.0,112.91032118085239)
% };
% % \addlegendentry{redis}
% \addplot[color=c5,mark=none,line width=2.5pt] coordinates {
% (0.0,122.65161255528508)
% (0.5,122.65161255528508)(1.0,123.50341892723551)(1.5,119.9041769968901)(2.0,194.1338090340688)(2.5,119.3318166277459)(3.0,120.7543611027709)(3.5,118.43365683846386)(4.0,119.66251086724282)(4.5,119.91835340042576)(5.0,121.7929551222383)(5.5,121.89190415047648)(6.0,120.83230113105434)(6.5,120.74648826456968)(7.0,121.11469390220921)(7.5,120.86921756303141)(8.0,123.37330806274483)(8.5,120.65562482930476)(9.0,149.3295055112789)(9.5,120.17790419692669)(10.0,120.54501209864489)(10.5,118.99828835882684)(11.0,120.52526000165268)(11.5,118.76115640005582)(12.0,122.73964392519244)(12.5,121.2232720911147)(13.0,122.45114528974216)(13.5,120.68631525192137)(14.0,121.8775333291972)(14.5,119.36301777512013)(15.0,178.56898164966282)(15.5,208.18554973792686)(16.0,219.32778508561177)(16.5,217.0202683505784)(17.0,221.9404488195278)(17.5,220.45640299718093)(18.0,223.61659591678267)(18.5,196.7370000790775)(19.0,103.98746968939287)(19.5,103.35867138428821)(20.0,104.57089950943903)(20.5,103.47324448589313)(21.0,104.57599074220566)(21.5,104.48407265162554)(22.0,106.44811488010386)(22.5,103.91322660048422)(23.0,105.50345958097668)(23.5,102.05701240188705)(24.0,104.01164586141097)(24.5,104.74684084262022)(25.0,104.87756537147614)(25.5,103.33914527498678)(26.0,104.79745604698206)(26.5,104.89903283403947)(27.0,103.51515357599686)(27.5,106.49047623507442)(28.0,103.78373940818518)(28.5,102.32744006705515)(29.0,103.8612850286074)(29.5,105.62857403428171)(30.0,107.66664809861555)(30.5,103.5731612514806)(31.0,102.96857505523784)(31.5,105.02085345569597)(32.0,104.18017952110168)(32.5,103.02464917013886)(33.0,104.24661585599793)(33.5,104.28994451712995)(34.0,104.87278141661393)(34.5,103.78892183573171)(35.0,103.97050154838644)(35.5,104.75974490636597)(36.0,106.37703242269565)(36.5,103.4606905977216)(37.0,107.34734289947716)(37.5,103.71403361222232)(38.0,103.62848334977943)(38.5,103.4515703090413)(39.0,103.87518566733505)(39.5,102.41318617633293)(40.0,104.9160071751039)(40.5,106.16459092389098)(41.0,102.4319377092493)(41.5,102.50920701701679)(42.0,103.4405780887842)(42.5,105.93816076096152)(43.0,105.79385998681587)(43.5,105.18850968096305)(44.0,104.68584824823765)(44.5,104.54431782910922)(45.0,89.47197794710766)(45.5,84.09346635283899)(46.0,83.7098001263293)(46.5,85.45339322816855)(47.0,83.81532872760856)(47.5,85.96078423293548)(48.0,87.20793401178412)(48.5,102.92900591428068)(49.0,119.97692260506696)(49.5,120.63050239087485)(50.0,119.00266926238373)(50.5,132.1994168082821)(51.0,123.42512671429644)(51.5,122.85737533445294)(52.0,123.61925794897456)(52.5,121.69638696018262)(53.0,123.8165381534573)(53.5,124.54358609541728)(54.0,122.53489151145996)(54.5,122.92994641986789)(55.0,125.50513015838166)(55.5,123.71272707248698)(56.0,121.80287655398665)(56.5,125.25437331997728)(57.0,124.07372779225597)(57.5,125.20305883690688)(58.0,122.7956736150976)(58.5,123.27142837882205)(59.0,125.18522809654226)(59.5,125.73829574783693)(60.0,125.73829574783693)
% };
% % \addlegendentry{TierBase}
% \addplot[color=c3,mark=none,line width=2.5pt] coordinates {
% (0.0,130.2990568259863)
% (0.5,130.2990568259863)(1.0,155.8574072081721)(1.5,107.87139769994138)(2.0,180.4280819993374)(2.5,137.13689313332088)(3.0,103.89944888335552)(3.5,158.17262122234143)(4.0,106.38790301337792)(4.5,107.47725046862908)(5.0,113.35841895926809)(5.5,105.68438049503511)(6.0,108.21003293693421)(6.5,184.82161420092558)(7.0,105.40664890731065)(7.5,121.74787282996661)(8.0,105.84920021925652)(8.5,106.60459039904597)(9.0,128.78904041570485)(9.5,101.96493350409852)(10.0,101.80745324713645)(10.5,176.09960546725108)(11.0,110.09289487179365)(11.5,104.02394339260204)(12.0,105.14409261816442)(12.5,124.98944831619465)(13.0,110.47745559880445)(13.5,107.71533180642422)(14.0,107.64472024056082)(14.5,254.27076036629956)(15.0,145.46596419457956)(15.5,153.18322213926328)(16.0,147.97397276313188)(16.5,146.29970646089308)(17.0,148.72447443697166)(17.5,150.3434670876578)(18.0,145.2385902861772)(18.5,148.26911435246677)(19.0,145.04114271605863)(19.5,140.99707906779219)(20.0,141.927726446679)(20.5,141.05627274735195)(21.0,146.43683872594235)(21.5,146.42113054949914)(22.0,143.26633682603148)(22.5,146.56371966256458)(23.0,145.2839501593162)(23.5,143.97131917519465)(24.0,144.3763754386701)(24.5,142.9272072447978)(25.0,140.1392832734973)(25.5,140.40490266459778)(26.0,142.94927232679)(26.5,143.25817780614048)(27.0,143.74589696984785)(27.5,153.13256001869152)(28.0,143.98001341735466)(28.5,142.02254684181227)(29.0,143.50641902199305)(29.5,144.6723788948311)(30.0,144.3129441217564)(30.5,142.58873700321504)(31.0,144.81758220145295)(31.5,142.48284257844406)(32.0,141.97343792805975)(32.5,143.02260391444713)(33.0,143.63880941921187)(33.5,142.64908813277526)(34.0,142.66840877252395)(34.5,141.83005908466106)(35.0,142.84606071593802)(35.5,147.08449736998773)(36.0,145.90005414506072)(36.5,142.6607220197662)(37.0,144.2050260799187)(37.5,142.23515944352965)(38.0,143.25819824569567)(38.5,142.25302875477712)(39.0,143.88512417059127)(39.5,141.48969725670185)(40.0,142.95199577383252)(40.5,142.41285523478496)(41.0,144.59886588559607)(41.5,142.26554125124588)(42.0,142.20608910495514)(42.5,142.40148502396977)(43.0,143.8309403565541)(43.5,143.21376222993126)(44.0,144.9780992593546)(44.5,142.34880492260112)(45.0,99.89443230549973)(45.5,100.67790806263773)(46.0,123.52234457567131)(46.5,117.67650964638173)(47.0,114.81660499170893)(47.5,100.89652953418357)(48.0,113.8656535635283)(48.5,104.90329397487973)(49.0,105.01613761376137)(49.5,109.51479765557087)(50.0,104.43151858218494)(50.5,102.02550340142753)(51.0,101.05624167834969)(51.5,100.99477803612285)(52.0,102.16738900768178)(52.5,100.3046742735682)(53.0,103.46047410513088)(53.5,104.83472961992018)(54.0,101.96158248132913)(54.5,101.1152459251289)(55.0,102.30821159562353)(55.5,227.30760277912998)(56.0,219.47676415796604)(56.5,132.1441808538899)(57.0,102.05478566150404)(57.5,106.86522070607496)(58.0,102.42520713017825)(58.5,101.42056200846685)(59.0,101.7299439626889)(59.5,101.02595531689735)(60.0,101.02595531689735)
% };
% % \addlegendentry{redismul}
% \end{axis}
% \end{tikzpicture}
% }
% \caption{Latency}
% \vspace{-1mm}
%-----------------------突发流量QPS--------------------
\begin{tikzpicture}[scale=0.42]
\begin{axis}[
width=1\textwidth,
height=0.37\textwidth,
% grid=major, % 显示网格
xlabel={\textbf{\Huge time(s)}},
ylabel={\textbf{\Huge throughput ($k$ qps)}},
legend pos=north west, % 图例位置
legend style={at={(0.13,0.95)},legend columns=4,font=\huge,fill opacity=0.7, draw opacity=1, row sep=-4pt,draw=black, thick,},
legend image post style={line width=2pt, scale=1},%图例的线条长度
xlabel near ticks, % 将xlabel靠近x轴的刻度
ylabel near ticks,
scaled y ticks=false,
% tick label style={font=\large},
tickwidth=3pt,
axis line style={line width=2pt}, %加粗边线
xtick={0,10,20,30,40,50,60},
ytick={50000,100000,150000,200000,250000},
yticklabels={50,100,150,200,250},
tick label style={font=\huge},
xmin=0, % 确保x轴从0开始
ymin=0, % 确保y轴从0开始
xmax=60,
ymax=250000,
]
% 折线数据
\addplot[color=c4,mark=none,line width=2.5pt] coordinates {
(0.0,19488.0)(1.0,19488.0)(2.0,20000.0)(3.0,20000.0)(4.0,20000.0)(5.0,20000.0)(6.0,20000.0)(7.0,19999.0)(8.0,20001.0)(9.0,20000.0)(10.0,20000.0)(11.0,20000.0)(12.0,20000.0)(13.0,20000.0)(14.0,20000.0)(15.0,20000.0)(16.0,117079.0)(17.0,125656.0)(18.0,127974.0)(19.0,127606.0)(20.0,126807.0)(21.0,127185.0)(22.0,127744.0)(23.0,127534.0)(24.0,127745.0)(25.0,127004.0)(26.0,127434.0)(27.0,127843.0)(28.0,127844.0)(29.0,127726.0)(30.0,127855.0)(31.0,127595.0)(32.0,127419.0)(33.0,127957.0)(34.0,127515.0)(35.0,128424.0)(36.0,127045.0)(37.0,127111.0)(38.0,127226.0)(39.0,127681.0)(40.0,125741.0)(41.0,127648.0)(42.0,127846.0)(43.0,127109.0)(44.0,127494.0)(45.0,127964.0)(46.0,20004.0)(47.0,20000.0)(48.0,20000.0)(49.0,20000.0)(50.0,20000.0)(51.0,20000.0)(52.0,20000.0)(53.0,20000.0)(54.0,20000.0)(55.0,20000.0)(56.0,20000.0)(57.0,20000.0)(58.0,20000.0)(59.0,20000.0)(60.0,20000.0)
};
% \addlegendentry{tbaseone} % 图例条目
\addplot[color=c8,mark=none,line width=2.5pt] coordinates {
(0.0,19488.0)(1.0,19536.0)(2.0,19999.0)(3.0,20001.0)(4.0,20000.0)(5.0,20000.0)(6.0,20000.0)(7.0,20000.0)(8.0,19999.0)(9.0,20001.0)(10.0,20000.0)(11.0,20000.0)(12.0,20000.0)(13.0,20000.0)(14.0,20000.0)(15.0,20000.0)(16.0,201025.0)(17.0,230721.0)(18.0,231544.0)(19.0,231982.0)(20.0,231885.0)(21.0,232184.0)(22.0,232251.0)(23.0,231499.0)(24.0,231904.0)(25.0,231440.0)(26.0,231700.0)(27.0,231986.0)(28.0,233104.0)(29.0,231452.0)(30.0,231883.0)(31.0,232374.0)(32.0,232605.0)(33.0,232432.0)(34.0,224010.0)(35.0,232374.0)(36.0,232387.0)(37.0,231040.0)(38.0,230614.0)(39.0,231530.0)(40.0,231595.0)(41.0,230363.0)(42.0,232270.0)(43.0,232503.0)(44.0,232173.0)(45.0,232641.0)(46.0,20000.0)(47.0,19999.0)(48.0,20001.0)(49.0,20000.0)(50.0,20000.0)(51.0,20000.0)(52.0,20000.0)(53.0,20000.0)(54.0,20000.0)(55.0,20000.0)(56.0,20000.0)(57.0,20000.0)(58.0,19999.0)(59.0,20001.0)(60.0,20000.0)
};
% \addlegendentry{tbasemul} % 图例条目
\addplot[color=c1,mark=none,line width=2.5pt] coordinates {
(0.0,19536.0)(1.0,19536.0)(2.0,20000.0)(3.0,20000.0)(4.0,20000.0)(5.0,20000.0)(6.0,20000.0)(7.0,20000.0)(8.0,20000.0)(9.0,20000.0)(10.0,20000.0)(11.0,20000.0)(12.0,20000.0)(13.0,20000.0)(14.0,20000.0)(15.0,20000.0)(16.0,120388.0)(17.0,130602.0)(18.0,132450.0)(19.0,132997.0)(20.0,132966.0)(21.0,133058.0)(22.0,133003.0)(23.0,132950.0)(24.0,133370.0)(25.0,133042.0)(26.0,133252.0)(27.0,134094.0)(28.0,134062.0)(29.0,133764.0)(30.0,133300.0)(31.0,133865.0)(32.0,133665.0)(33.0,133749.0)(34.0,133206.0)(35.0,133259.0)(36.0,133309.0)(37.0,133216.0)(38.0,133887.0)(39.0,133845.0)(40.0,133726.0)(41.0,133714.0)(42.0,132199.0)(43.0,133033.0)(44.0,133242.0)(45.0,132800.0)(46.0,20001.0)(47.0,20000.0)(48.0,20000.0)(49.0,20000.0)(50.0,20000.0)(51.0,20000.0)(52.0,20000.0)(53.0,20000.0)(54.0,20000.0)(55.0,20000.0)(56.0,20000.0)(57.0,20000.0)(58.0,20000.0)(59.0,20000.0)(60.0,20000.0)
};
% \addlegendentry{redis}
\addplot[color=c5,mark=none,line width=2.5pt] coordinates {
(0.0,19516.48)(1.0,19516.48)(2.0,20000.0)(3.0,20000.0)(4.0,20000.0)(5.0,20000.0)(6.0,20000.0)(7.0,20000.0)(8.0,20000.0)(9.0,20000.0)(10.0,20000.0)(11.0,20000.0)(12.0,20000.0)(13.0,20000.0)(14.0,20000.0)(15.0,20000.0)(16.0,119579.0)(17.0,129090.0)(18.0,131563.0)(19.0,158616.0)(20.0,236259.0)(21.0,237313.0)(22.0,237910.0)(23.0,236167.0)(24.0,236718.0)(25.0,235826.0)(26.0,236400.0)(27.0,235382.0)(28.0,236266.0)(29.0,235692.0)(30.0,235949.0)(31.0,235648.0)(32.0,237195.0)(33.0,236669.0)(34.0,237532.0)(35.0,236905.0)(36.0,235698.0)(37.0,236585.0)(38.0,236028.0)(39.0,236046.0)(40.0,237090.0)(41.0,235845.0)(42.0,236865.0)(43.0,234758.0)(44.0,236447.0)(45.0,236306.0)(46.0,20000.0)(47.0,20000.0)(48.0,20000.0)(49.0,20000.0)(50.0,20000.0)(51.0,20000.0)(52.0,20000.0)(53.0,20000.0)(54.0,20000.0)(55.0,20000.0)(56.0,20000.0)(57.0,20000.0)(58.0,20000.0)(59.0,20000.0)(60.0,20000.0)
};
% \addlegendentry{TBase}
\addplot[color=c3,mark=none,line width=2.5pt] coordinates {
(0.0,19515.48)(1.0,19515.48)(2.0,19985.0)(3.0,20001.0)(4.0,20019.02)(5.0,20000.0)(6.0,19980.02)(7.0,19649.65)(8.0,20370.0)(9.0,20000.0)(10.0,20000.0)(11.0,19980.02)(12.0,20001.0)(13.0,20004.0)(14.0,19995.0)(15.0,20000.0)(16.0,154378.0)(17.0,172106.0)(18.0,175443.0)(19.0,175994.0)(20.0,177979.0)(21.0,178280.0)(22.0,176984.0)(23.0,177939.0)(24.0,177218.0)(25.0,178613.0)(26.0,179861.0)(27.0,179722.0)(28.0,180756.0)(29.0,184383.0)(30.0,184638.0)(31.0,185038.0)(32.0,184709.0)(33.0,185969.0)(34.0,185273.0)(35.0,184723.0)(36.0,184724.0)(37.0,185282.0)(38.0,185161.0)(39.0,185137.0)(40.0,185131.0)(41.0,185022.0)(42.0,185338.0)(43.0,184819.0)(44.0,185208.0)(45.0,185466.0)(46.0,20000.0)(47.0,20000.0)(48.0,20000.0)(49.0,20000.0)(50.0,20000.0)(51.0,20000.0)(52.0,20000.0)(53.0,20000.0)(54.0,20000.0)(55.0,20000.0)(56.0,18776.0)(57.0,21224.0)(58.0,20000.0)(59.0,20000.0)(60.0,20020.02)
};
% \addlegendentry{redismul}
\end{axis}
\end{tikzpicture}
\caption{Performance of TierBase and Redis for workload boosting}
\label{fig:elastic-thread}
\end{figure}
% \setlength{\textfloatsep}{10pt}
\subsection{Cost Evaluation} \label{sec:cost evaluation}
In the following two subsections, we evaluate the cost-effectiveness of TierBase and compare it with other representative systems under different configurations and synthetic workloads using the space-performance cost model.
\subsubsection{Evaluation setup}
We employ the framework introduced in Section \ref{sec:framework} to evaluate synthetic workloads generated by YCSB using public datasets for write operations. Our simulated workload comprises 10GB data with 80,000 QPS for caching systems, and 10GB data with 40,000 QPS for databases with persistence. While our cost model is applicable to various workloads, we selected these specific parameters as a representative miniature of typical workloads at Ant Group.
The cost unit presented is relative, based on a standard container with 1 CPU core and 4GB of memory. All systems are tested within this standard container on a single instance, with $CPQPS$ and $CPGB$ calculated accordingly.
This evaluation methodology allows us to assess the cost-effectiveness of various systems under controlled conditions.
For systems employing replication (e.g., Redis with AOF, TierBase with WAL, and TierBase with write-back policy), we implement a master-replica setup in the cache tier to ensure data reliability. This configuration effectively doubles the cache tier cost.
We denote single-thread, multi-thread, and elastic threading as $s$, $m$, and $e$ respectively. TierBase-PMem is for PMem activation in TierBase, and TierBase-Zstd and TierBase-PBC for compression. Redis-AOF and TierBase-WAL denote Redis with AOF and TierBase with WAL, respectively. Write-through and write-back policies in TierBase are abbreviated as $wt$ and $wb$. Workloads with a cache ratio of 10 are labeled as $10X$.
\input{figures/cost_model}
% % \hspace{0.3cm}
\input{figures/cost_per}
\subsubsection{Cost analysis for caching systems}
Figure \ref{in-memory cost} presents the cost results for caching systems. The primary cost driver for caching systems is memory storage expenses. Memcached has the lowest storage cost, followed by Dragonfly, while Redis and TierBase without additional features have relatively higher storage costs.
In terms of performance costs, TierBase, Redis, and Memcached exhibit similar low costs in single-thread mode, while Dragonfly shows a higher performance cost. When elastic threading is enabled, TierBase demonstrates improved throughput, leading to a significant reduction in performance costs, nearly half that of single-thread Redis, by efficiently utilizing surplus CPU resources within the containers.
Furthermore, when TierBase employs PMem to extend memory, it achieves a substantial 60\% reduction in storage costs compared to the base configuration, with minimal performance impact. This cost is considerably lower than that of Memcached. Activating compression in TierBase leads to an additional decrease in storage costs.
The results show that TierBase's features can effectively reduce both performance and storage costs. Similar trends are observed across different workload settings, as illustrated in Figure \ref{in-memory cost}(b).
%Figure \ref{in-memory cost} shows the cost results for caching systems. The primary determinant of the cost for caching systems is attributed to storage expenses. Specifically, Memcached has the lowest storage cost, followed by Dragonfly. The storage cost of both Redis and TierBase, without features enabled, is relatively higher. Regarding performance costs, in single-thread mode, TierBase, Redis, and Memcached exhibit similar and low performance cost. Conversely, Dragonfly demonstrates a higher performance cost.
% This efficiency is achieved through the optimized utilization of surplus CPU resources, which are approximately half compared to those required by a single-thread Redis configuration.
%Upon enabling elastic threading, TierBase demonstrates an enhanced throughput, leading to a significant reduction in performance costs, which are nearly half of that of single-thread Redis. Note that this efficiency is achieved through the optimized utilization of surplus CPU resources within the containers.
%Furthermore, when TierBase employs PMEM as an extension of memory, it achieves a substantial reduction in storage costs, dropping to 40\% of the original, while incurring minimal performance loss. This cost is significantly lower than that of Memcached. Additionally, when TierBase activates its compression feature, there is a further decrease in storage costs. The results clearly show that the features of \tbase can effectively reduce costs in both performance and storage. Similar trends can be observed in different worklaod settings as shown in Figure \ref{in-memory cost}(b).
% From the figure\ref{in-memory cost} representing the in-memory mode, it is observed that in terms of performance cost, TierBase with elastic threading exhibits the lowest, while Dragonfly in single-thread mode is the highest. Both Memcached and Redis perform better in single-thread than in multi-threads mode, whereas Dragonfly shows better performance in multi-threads mode than in single-thread. The variations of TierBase, including enabling zstd and pbc compression and using PMEM devices for storage, show performance close to most single-thread systems, except for Dragonfly.
% Regarding capacity cost, for storing the same amount of data, Redis and the default TierBase have higher memory space overhead, leading to higher storage costs. In contrast, Memcached has relatively lower storage costs. When TierBase enables memory compression, its storage cost significantly decreases to less than half of the original. Similarly, TierBase with PMEM enabled also demonstrates extremely low storage costs. In these modes, TierBase's storage cost is substantially lower than all compared systems.
%Although this results in some performance degradation in workloads with a higher frequency of write operations, storage costs remain the predominant factor. In workloads with more read operations, the performance of TierBase closely approximates its default memory mode, ensuring rapid data retrieval.
%-------------------persistence-----------------
\subsubsection{Cost analysis for databases with persistence}
Figure \ref{persis cost} presents the results for databases with persistence. The traditional key-value store like Cassandra and HBase are observed to have relatively high performance costs while the storage costs are notably low.
% It should be noted that for Hbase and Cassandra, the size of memory is not the primary factor affecting performance. Hence, their storage costs are mainly focused on the expenses of data residing on disk, resulting in relatively lower storage costs.
For Redis with AOF and TierBase with WAL, both systems ensure data persistence and adopt a dual-replica strategy for data safety. These approaches result in lower performance cost but significantly higher storage costs.
TierBase demonstrates a good balance in terms of both performance and storage costs. On the one hand, its inherent characteristics as a caching system enable high throughput. On the other hand, its persistence mechanism does not require storing all data in memory, which contributes to its overall lower costs. It is important to note that under the write-back approach, where data is stored in duplicate copies, the storage cost is higher compared to write-through. However, due to different data update characteristics, the write-back approach exhibits higher throughput in write-intensive scenarios, translating to lower performance costs. This advantage diminishes or even disappears in read-heavy scenarios.
Using PMem for data persistence is a cost-effective choice. Although its space cost is relatively higher compared to write-through and write-back, its performance cost is sufficiently low due to PMem's near-memory speed.
% \subsubsection{Cost analysis for compression}
% \input{exp_compress}
% \subsubsection{Break-even interval analysis.}
% In determining whether to enable additional features like compression or PMEM in TierBase, we calculate the break-even intervals for TierBase with and without these features, based on the analyses in Section 4.3. For a workload consisting of 50\% reads and 50\% writes, and focusing on the cities dataset (with an average data length of about 200 bytes), we can establish the break-even intervals between TierBase without any additional features and TierBase with each feature enabled.
% When the ratio of the workload's total data volume (cardinality) to the QPS is less than the calculated interval, opting for Mode A (TierBase without additional features) is more cost-effective. Conversely, if the ratio is higher, Mode B (TierBase with a specific feature) becomes the preferred choice.
% We note that in Table \ref{interval}, the interval memory mode with PMEM enabled is the shortest, lasting around 89 seconds. The interval for the system with compression enabled is approximately two and a half minutes. The interval with write-back mode is 134 seconds, and the longest interval observed is with write-through mode, reaching 169 seconds. This finding aligns with conventional wisdom: a system with lower storage costs but higher performance costs becomes a better choice when large amounts of data need to be stored with infrequent access requirements.
% This situation highlights the need to thoroughly evaluate the specific needs of a workload and the balance between different features when selecting the most cost-efficient setup for TierBase.
%
%\vspace{-2mm}
% \setlength{\textfloatsep}{10pt}
\subsection{Case Study}
\label{case_study}
TierBase is extensively utilized across a wide range of scenarios at Ant Group, with over 3,000 applications leveraging its capabilities. These applications span various use cases, employing hundreds of thousands of CPU cores and several petabytes of memory. Due to space constraints, we will focus on two representative case studies in this paper.
% \input{figures/case_study}
% \input{figures/tradeoff}
\noindent\textbf{Case 1: User Info Service.}
The User Info Service at Ant Group manages basic user profile data, serving numerous applications through a proprietary SDK with TierBase client. During peak hours on a typical day, this service handles approximately 500,000 updates and 16,000,000 reads per second, indicating a significantly read-heavy workload. Given the service's primary focus on online users, high availability and reliability are of paramount importance.
\subsubsection{Systems comparison}
To assess the cost-effectiveness of various systems, we replayed a real business trace with all databases configured for dual-replica reliability. Figure \ref{case study1} shows that in-memory stores like Redis, Memcached, and Dragonfly have low performance costs but higher storage expenses. TierBase, using compression, halves its original volume, significantly reducing costs compared to Redis. This is particularly advantageous in this read-heavy scenario where performance cost is not primary. The trade-off between performance and storage efficiency demonstrates TierBase's adaptability to specific workload characteristics, optimizing overall cost while maintaining performance efficiency. Activating compression in TierBase yields a 62\% cost reduction compared to TierBase-Raw, showcasing its effectiveness in balancing performance and storage requirements in read-heavy, availability-critical scenarios.
\input{figures/case_study}
\input{figures/tradeoff}
\subsubsection{Space-performance cost trade-offs}
We demonstrate the trade-off using our proposed cost model under use case 1. Figure \ref{Trade-off} shows the workload's space cost significantly exceeds its performance cost. We employ compression techniques, sacrificing some performance to save substantial space. We tested Zstd compression levels -50, -10, 1, 15, and 22, both with and without a dictionary. As shown in Figure \ref{Trade-off}(a), higher compression levels increase space savings but have an upper bound, beyond which compression ratio gains become marginal while performance costs grow considerably. Practically, we may select compression level 1 for better performance tolerance. Additionally, pre-trained compression yields more substantial cost savings compared to compression without pre-training.
We also evaluate the cost-effectiveness of TierBase with write-back policy using four cache ratios ranging from 2X to 5X. As shown in Figure \ref{Trade-off}(b), Higher cache ratios result in lower space costs but higher performance costs.
% Our analysis reveals that a 5X cache ratio achieves an approximately balanced trade-off in write-back mode, thus approaching cost optimality for the cache tier.
The result reveals that a cache ratio of 5X approximately achieves the optimal balance between performance and storage costs as predicted by our model. The results validate our cost model for accurately guiding cost optimization, confirming that the achieved effects align with expectations.
% \textcolor{red}{We also evaluate the cost-effectiveness of TierBase at different compression levels, and write-back at different cache ratios, to find the tradeoff between space cost and performance cost. We selected compression levels -50, -10, 1, 15, and 22 for Zstd compression, both with and without a dictionary, and we chose four write-back cache ratios from 2X-5X. PBC as well as cache-only(i.e. raw) modes have also been added as comparisons. As shown in the figure\ref{Trade-off}, higher compression levels as well as higher cache ratio result in lower space cost as well as higher performance cost. From the results, we find that level1 zstd compression and 5X write-back cache ratio are able to achieve a good tradeoff in their respective modes.}
% \input{figures/case_study}
% \input{figures/tradeoff}
\subsubsection{Break-even interval}
Furthermore, we calculate several sets of break-even intervals between the fast and slow storage configurations on TierBase based on the analyses in Section \ref{interval}. As shown in Table \ref{interval_table}, if the average access interval for a key in the workload is less than 98 seconds, the default TierBase is the most cost-effective choice. For access intervals between 98 and 264 seconds, TierBase with PMem mode is recommended. When the average access interval exceeds 264 seconds, employing compression becomes the optimal solution. By collecting the average access interval for a key in the real workload, we observe that it exceeds 1018 seconds. Consequently, TierBase is employed as a single-layer caching system, leveraging pre-trained compression (PBC) to optimize memory usage. This approach achieves a 25\% compression rate for values and realizes cost savings of 50\%, which is significant considering the hundreds of thousands of CPU cores utilized in this case.
\input{figures/interval}
% if a key is used more often than every 195 seconds, the standard TierBase is the cheapest option. If a key is used every 195 to 816 seconds, using TierBase with PMem mode is best. For use less often than every 816 seconds, using compression is the most cost-effective.
% if the average access inteis greater than 816s, compression mode is the best choice.
% Here's the rewritten version of the specified part in Section 6.5 Case 1:
% Furthermore, we calculate the break-even intervals between different configurations of TierBase, classified as fast and slow storage, based on the analyses in Section 5.3. Table 2 presents these break-even intervals. If the average access interval for a key in the workload is less than 195 seconds, the default TierBase configuration is the most cost-effective choice. For access intervals between 195 and 816 seconds, TierBase with PMem mode is recommended. When the average access interval exceeds 816 seconds, employing compression becomes the optimal solution.
% To determine the most suitable configuration for the user info service workload, we collect and analyze the average access interval for keys in the real-world traces. Our analysis reveals that the average access interval surpasses 1018 seconds. Based on this observation and the break-even intervals, we conclude that utilizing TierBase as a single-layer caching system with pre-trained compression (PBC) is the most cost-effective approach. By leveraging PBC, we achieve a 25% compression rate for values, resulting in a substantial 50% reduction in overall costs. Considering the extensive scale of the user info service, which involves hundreds of thousands of CPU cores, these cost savings are highly significant.
Although write-through caching could potentially be applicable in this scenario and achieve a 60\% cost reduction, the decision to prioritize compression over write-through caching is driven by the client's stringent requirements for low latency and high stability when serving online requests. TierBase's adaptability allows it to configure for aligning with the specific needs and priorities of each client, ensuring an optimal balance between cost efficiency and performance in real-world scenarios.
% \textbf{Online Transaction Session Data.} Another use case of TierBase at Ant Group involves storing session data related to online transactions. This session data is frequently accessed and updated immediately after the session occurs, resulting in a high cache hit rate. This use case highlights the temporal non-uniformity in data access patterns. \textcolor{red}{more introduction}
% The cost of this scenario is displayed in figure\ref{case study}b. Traditional NoSQL databases such as Hbase and Cassandra have high storage costs and performance costs. When write-through is enabled under Tier-base, storage costs are reduced by 70\% and performance costs are reduced by 40\% compared to cassandra. When you need to deal with high-throughput scenarios, turning on write-back or using pmem's persistence mode will further improve performance. With the same configuration, the performance can be 4.8X that of cassandra. Overall, Tier-base can reduce costs by more than 30\% compared to traditional databases in this scenario.
% In the production environment, TierBase with write-back mode observed hit rate is approximately 95\%, with only 3\% of the data residing in the cache tier.
% \input{figures/interval}
\noindent\textbf{Case 2: Capital Reconciliation.}
TierBase is also deployed in the capital reconciliation business at Ant Group. As a risk control scenario focused on financial auditing and verification, the capital reconciliation business is particularly sensitive to costs. During peak shopping seasons, the overall QPS for capital reconciliation can reach tens of millions. TierBase's write-through and write-back caching strategies are selectively employed based on different scenarios. For this case study, we choose one of the main scenarios where the read and write operations are close to a 1:1 ratio. In this scenario, data from different channels is written into TierBase and then read out by the reconciliation system for verification.
% As shown in Figure\ref{case study}(b), TierBase in all three persistence modes exhibits lower performance costs compared to cassandra as well as hbase, with the pmem mode being at least on par with the lower-cost Hbase in terms of storage costs, and with write-through or write-back turned on to demonstrate even lower costs.
Figure \ref{case study2} illustrates the cost breakdown for this scenario. Disk-based key-value stores like HBase and Cassandra exhibit low space and performance costs. When TierBase is configured with write-through, performance costs are lowered by 35\% compared to Cassandra. In high-throughput scenarios, enabling write-back mode further enhances performance. With the same configuration, TierBase can achieve 2.6x the performance of Cassandra. Overall, TierBase reduces costs by at least 37\% compared to both Cassandra and HBase. Additionally, it cuts costs by 70\% compared to TierBase default configuration.
The observations in the capital reconciliation case study reveal that recent data is frequently accessed in the cache, while long-term data is occasionally retrieved. Online statistics shows that TierBase with write-through mode achieves a cache hit rate of approximately 80\%, with only 1\% of the hottest data stored in the cache tier. This demonstrates the effectiveness of TierBase's cache-storage disaggregation in significantly reducing costs for workloads with temporal access skewness.
% Furthermore, it provides a cohesive operational interface for applications, facilitating easy integration.
\begin{figure}
\centering
\begin{tikzpicture}[scale=0.6]
\begin{axis}[
hide axis,
scale only axis,
height=0pt,
width=0pt,
xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
legend style={font=\fontsize{12}{10}\selectfont, legend columns=4, at={(0.5,0.9)}, anchor=north, row sep=0.5pt, column sep=2pt},
legend image post style={mark size=2.5pt, only marks}, % 仅显示标记,无线条
legend cell align={left},
]
% 根据您的要求添加图例项
% \addlegendimage{mark=square*, fill=Purple} \addlegendentry{Memcached-s}
\addlegendimage{mark=*, fill=Purple} \addlegendentry{Memcached-m}
\addlegendimage{mark=*, fill=American Yellow} \addlegendentry{Redis-s}
% \addlegendimage{mark=*, fill=American Yellow} \addlegendentry{Redis-m}
% \addlegendimage{mark=square*, fill=Moonstone, draw=black} \addlegendentry{Dragonfly-s}
\addlegendimage{mark=*, fill=Moonstone, draw=black} \addlegendentry{Dragonfly-m}
\addlegendimage{mark=square*, fill=Green2, draw=black} \addlegendentry{TierBase-s}
% \addlegendimage{mark=*, fill=Green2, draw=black} \addlegendentry{TierBase-m}
\addlegendimage{mark=halfsquare*, fill=Green2, draw=black} \addlegendentry{TierBase-e}
\addlegendimage{mark=triangle*, fill=Green2, draw=black} \addlegendentry{TierBase-Zstd}
\addlegendimage{mark=diamond*, fill=Green2, draw=black} \addlegendentry{TierBase-PBC}
\addlegendimage{mark=pentagon*, fill=Green2, draw=black} \addlegendentry{TierBase-PMem}
\end{axis}
\end{tikzpicture}
\par % 或者使用 \\
% \vspace{-2mm}
% \subfigure[100\%write]{
% \begin{tikzpicture}[scale = 0.7]
% \pgfplotsset{
% defaultmark/.style={draw=black, line width=0.25pt},
% mystyle/.style={
% only marks,
% y filter/.code={\pgfmathparse{\pgfmathresult*80000}\pgfmathresult},
% mark size=3pt,
% },
% scatter/classes={
% Memcached1={mark=square*, fill=Purple},
% Memcached4={mark=*, fill=Purple},
% Redis1={mark=square*, fill=American Yellow},
% Redis4={mark=*, fill=American Yellow},
% TBase1={mark=square*, fill=Green2, draw=black},
% TBase4={mark=*, fill=Green2, draw=black},
% TBaseAdaptive={mark=halfsquare*, fill=Green2, draw=black,mark size=4pt},
% TBaseZstd={mark=triangle*, fill=Green2, draw=black, mark size = 4pt},
% TBasePbc={mark=diamond*, fill=Green2, draw=black,mark size = 4pt},
% TBaseAEP={mark=pentagon*, fill=Green2, draw=black,mark size = 4pt},
% Dragonfly1={mark=square*, fill=Moonstone, draw=black},
% Dragonfly4={mark=*, fill=Moonstone, draw=black}
% }
% }
% \begin{axis}[
% height=7cm,
% width=7cm,
% xlabel=$cost(GB)$,
% ylabel=$cost(QPS)$,
% xticklabel={
% \pgfmathparse{\tick*10}
% \pgfmathprintnumber{\pgfmathresult}
% },
% yticklabel={
% \pgfmathprintnumber{\tick}
% },
% ytick={1,2,3,4,5,6},
% xtick={0,0.1,0.2,0.3,0.4,0.5,0.6},
% view={0}{90},
% domain=0:0.6,
% y domain=0:6,
% colormap={custom}{
% % color(0)=(red!5!yellow)
% % color(0.5)=(red!40!yellow)
% % color(1)=(red!70!yellow)
% color(0)=(color1)
% color(1)=(color2)
% % color(0.5)=(red!30!white)
% },
% samples=20,
% samples y=20,
% scaled y ticks=false,
% scaled x ticks=false,
% yticklabel style={/pgf/number format/fixed},
% xticklabel style={/pgf/number format/fixed},
% legend style={font=\tiny, legend columns=3,
% row sep=0.5pt,
% column sep=2pt
% },
% legend cell align={left},
% legend image post style={mark size=2.5pt},
% ]
% \addplot3[surf, shader=flat,forget plot] {max(x*10 , y)};
% \addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
% (0.382455544,0.0000089254,0) [Memcached1]
% (0.382737758,0.0000116300,0) [Memcached4]
% (0.49130154,0.0000085012,0) [Redis1]
% (0.491325842,0.0000205194,0) [Redis4]
% (0.500086233,0.0000088352,0) [TBase1]
% (0.50011367,0.0000047156*4,0) [TBase4]
% (0.50011367,0.0000047156,0) [TBaseAdaptive]
% (0.181467481,0.0000156296,0) [TBaseZstd]
% (0.161547881,0.0000188039,0) [TBasePbc]
% (0.185388687,0.0000099375,0) [TBaseAEP]
% (0.441613073,0.0000386186,0) [Dragonfly1]
% (0.448874594,0.0000119573,0) [Dragonfly4]
% % (0.554022927,0.0000213991,0) [RedisAof]
% % (0.039044776,0.0000576003686424,0) [TBaseWriteThrough5X]
% % (0.019522388,0.0000606869765748,0) [TBaseWriteThrough10X]
% % (0.078089552,0.0000250000000000,0) [TBaseWriteBack5X]
% % (0.039044776,0.0000256541816316,0) [TBaseWriteBack10X]
% };
% % \legend{Memcached1, Memcached4, Redis1, Redis4, TBase1, TBase adaptive thread, TBase zstd, TBase pbc, TBase AEP, Dragonfly1, Dragonfly4}
% \end{axis}
% \end{tikzpicture}
% % \caption{Workload 100\% write}
% }
%workloada
\subfigure[50\%write 50\%read]{
\begin{tikzpicture}[scale=0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*80000}\pgfmathresult},
mark size=3pt
},
scatter/classes={
% Memcached1={mark=square*, fill=Purple},
Memcached4={mark=*, fill=Purple},
Redis1={mark=*, fill=American Yellow},
% Redis4={mark=*, fill=American Yellow},
TBase1={mark=square*, fill=Green2, draw=black},
% TBase4={mark=*, fill=Green2, draw=black},
TBaseAdaptive={mark=halfsquare*, fill=Green2, draw=black,mark size=4pt},
TBaseZstd={mark=triangle*, fill=Green2, draw=black, mark size = 4pt},
TBasePbc={mark=diamond*, fill=Green2, draw=black,mark size = 4pt},
TBaseAEP={mark=pentagon*, fill=Green2, draw=black,mark size = 4pt},
% Dragonfly1={mark=square*, fill=Moonstone, draw=black},
Dragonfly4={mark=*, fill=Moonstone, draw=black}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$cost(GB)$,
ylabel=$cost(QPS)$,
xticklabel={
\pgfmathparse{\tick*10}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={1,2,3,4,5,6},
xtick={0,0.1,0.2,0.3,0.4,0.5,0.6},
% colorbar,
% colorbar style={
% title=Cost,
% ytick={1,2,3},
% yticklabels={$1$,$2$,$3$}
% },
view={0}{90},
domain=0:0.6,
y domain=0:6,
colormap={custom}{
color(0)=(color1)
color(1)=(color2)
},
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={font=\normalsize, at={(1.2,1.3)},legend columns=5},
legend image post style={mark size=2.5pt},
legend cell align={left},
]
\addplot3[surf, shader=flat,forget plot] {max(x*10 , y)};
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
% (0.382455544,0.0000078747,0) [Memcached1]
(0.382737758,0.0000105987,0) [Memcached4]
% (0.491325842,0.0000190488,0) [Redis4]
(0.500086233,0.0000076017,0) [TBase1]
(0.49130154,0.0000074033,0) [Redis1]
% (0.50011367,0.0000040523*4,0) [TBase4]
(0.50011367,0.0000040523,0) [TBaseAdaptive]
(0.181467481,0.0000134159,0) [TBaseZstd]
(0.161547881,0.0000141014,0) [TBasePbc]
(0.185388687,0.0000083526,0) [TBaseAEP]
% (0.441613073,0.0000367191,0) [Dragonfly1]
(0.448874594,0.0000115907,0) [Dragonfly4]
};
% \legend{Memcached1, Memcached4, Redis1, Redis4, TBase1, TBase adaptive thread, TBase zstd, TBase pbc, TBase AEP, Dragonfly1, Dragonfly4}
\end{axis}
\end{tikzpicture}
% \caption{Workload 50\% read 50\%write}
}
%workloadb
\subfigure[95\%read 5\%write]{
\begin{tikzpicture}[scale=0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*80000}\pgfmathresult},
mark size=3pt
},
scatter/classes={
% Memcached1={mark=square*, fill=Purple},
Memcached4={mark=*, fill=Purple},
Redis1={mark=*, fill=American Yellow},
% Redis4={mark=*, fill=American Yellow},
TBase1={mark=square*, fill=Green2, draw=black},
% TBase4={mark=*, fill=Green2, draw=black},
TBaseAdaptive={mark=halfsquare*, fill=Green2, draw=black,mark size=4pt},
TBaseZstd={mark=triangle*, fill=Green2, draw=black, mark size = 4pt},
TBasePbc={mark=diamond*, fill=Green2, draw=black,mark size = 4pt},
TBaseAEP={mark=pentagon*, fill=Green2, draw=black,mark size = 4pt},
% Dragonfly1={mark=square*, fill=Moonstone, draw=black},
Dragonfly4={mark=*, fill=Moonstone, draw=black}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$cost(GB)$,
ylabel=$cost(QPS)$,
xticklabel={
\pgfmathparse{\tick*10}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={1,2,3,4,5,6},
xtick={0,0.1,0.2,0.3,0.4,0.5,0.6},
colorbar,
colorbar style={
title=Cost,
ytick={1,3,5},
yticklabels={$1$,$3$,$5$}
},
view={0}{90},
domain=0:0.6,
y domain=0:6,
colormap={custom}{
color(0)=(color1)
color(1)=(color2)
},
samples=20,
samples y=20,
legend style={font=\tiny, legend columns=3},
legend image post style={mark size=2.5pt},
legend cell align={left},
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
]
\addplot3[surf, shader=flat,forget plot] {max(x*10 , y)};
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
% (0.382455544,0.0000080912,0) [Memcached1]
(0.382737758,0.0000102787,0) [Memcached4]
% (0.491325842,0.0000175564,0) [Redis4]
(0.500086233,0.0000073764,0) [TBase1]
(0.49130154,0.0000075829,0) [Redis1]
% (0.50011367,0.0000035196*4,0) [TBase4]
(0.50011367,0.0000035196,0) [TBaseAdaptive]
(0.181467481,0.0000103843,0) [TBaseZstd]
(0.161547881,0.0000095431,0) [TBasePbc]
(0.185388687,0.0000079092,0) [TBaseAEP]
% (0.441613073,0.0000361458,0) [Dragonfly1]
(0.448874594,0.0000112484,0) [Dragonfly4]
};
% \legend{Memcached1, Memcached4, Redis1, Redis4, TBase1, TBase adaptive thread, TBase zstd, TBase pbc, TBase AEP, Dragonfly1, Dragonfly4}
\end{axis}
\end{tikzpicture}
}
\caption{Cost of caching system}
\label{in-memory cost}
\end{figure}
\begin{figure}
\centering
\begin{tikzpicture}[scale = 0.6]
\begin{axis}[
hide axis,
scale only axis,
height=0pt,
width=0pt,
xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
legend style={font=\fontsize{12}{10}\selectfont,, legend columns=4, at={(0.5,0.9)}, anchor=north, row sep=0.5pt, column sep=2pt},
legend image post style={mark size=2.5pt, only marks}, % 仅显示标记,无线条
legend cell align={left},
]
% 根据您的要求添加图例项
\addlegendimage{mark=square*, fill=Giants Orange} \addlegendentry{Cassandra}
\addlegendimage{mark=square*, fill=American Yellow,mark size=4pt} \addlegendentry{Redis-AOF}
\addlegendimage{mark=*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wt-10X}
\addlegendimage{mark=pentagon*, fill=Green2, draw=black,mark size=4pt} \addlegendentry{TierBase-WAL-PMem}
\addlegendimage{mark=square*, fill=Blue Jeans,mark size=4pt} \addlegendentry{HBase}
\addlegendimage{mark=square*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-WAL}
% \addlegendimage{mark=halfcircle*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wt-5X}
% \addlegendimage{mark=halfdiamond*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wb-5X}
\addlegendimage{mark=diamond*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wb-10X}
\end{axis}
\end{tikzpicture}
\par % 或者使用 \\
% \vspace{-2mm}
% \subfigure[100\% write]{
% \begin{tikzpicture}[scale = 0.7]
% \pgfplotsset{
% defaultmark/.style={draw=black, line width=0.25pt},
% mystyle/.style={
% only marks,
% y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
% mark size=3.5pt,
% },
% scatter/classes={
% Cassandra={mark=square*, fill=Giants Orange},
% hbase={mark=square*, fill=Blue Jeans},
% RedisAof={mark=square*, fill=American Yellow},
% TBaseAof={mark=square*, fill=Green2},
% TBaseWriteThrough5X={mark=halfcircle*, fill=Green2},
% TBaseWriteThrough10X={mark=*, fill=Green2},
% TBaseWriteBack5X={mark=halfdiamond*, fill=Green2,mark size=5pt},
% TBaseWriteBack10X={mark=diamond*, fill=Green2,mark size=5pt},
% TBaseAEP={mark=pentagon*, fill=Green2, draw=black}
% }
% }
% \begin{axis}[
% height=7cm,
% width=7cm,
% xlabel=$cost(GB)$,
% ylabel=$cost(QPS)$,
% xticklabel={
% \pgfmathparse{\tick}
% \pgfmathprintnumber{\pgfmathresult}
% },
% yticklabel={
% \pgfmathprintnumber{\tick}
% },
% ytick={2,4,6,8,10},
% xtick={0,2,4,6,8,10},
% view={0}{90},
% domain=0:11,
% y domain=0:11,
% colormap={custom}{
% % color(0)=(red!5!yellow)
% % color(0.5)=(red!40!yellow)
% % color(1)=(red!70!yellow)
% color(0)=(color1)
% color(1)=(color2)
% % color(0.5)=(red!30!white)
% },
% samples=20,
% samples y=20,
% scaled y ticks=false,
% scaled x ticks=false,
% yticklabel style={/pgf/number format/fixed},
% xticklabel style={/pgf/number format/fixed},
% legend style={font=\tiny, legend columns=3,
% row sep=0.5pt,
% column sep=2pt
% },
% legend cell align={left},
% legend image post style={mark size=2.5pt},
% ]
% \addplot3[surf, shader=flat,forget plot] {max(x, y)};%这里x,y是算出来后的相对成本,不需要额外运算
% \addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
% (0.496651786,0.00009734965562559,0) [Cassandra]
% (0.496651786,0.00009892419933226,0) [hbase]
% (9.827410515,0.0000250100,0) [RedisAof]
% (10.00172466,0.0000285351,0) [TBaseAof]
% % (0.578500866,0.0000391270,0) [TBaseWriteThrough5X]
% (0.328457749,0.0000399070,0) [TBaseWriteThrough10X]
% (0.578500866,0.0000391270,0) [TBaseWriteThrough5X]
% (1.078587099,0.0000218082673430,0) [TBaseWriteBack5X]
% (0.578500866,0.0000227145800437,0) [TBaseWriteBack10X]
% (1.866645295,0.00001655821038862,0) [TBaseAEP]
% };
% % \legend{Cassandra, Hbase, Redis aof, TBase wt 5X, TBase wt 10X, TBase wb 5X, TBase wb 10X,TBase AEP}
% \end{axis}
% \end{tikzpicture}
% }
\subfigure[50\% read 50\%write]{
\begin{tikzpicture}[scale=0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt
},
scatter/classes={
Cassandra={mark=square*, fill=Giants Orange},
hbase={mark=square*, fill=Blue Jeans},
TBaseAof={mark=square*, fill=Green2},
RedisAof={mark=square*, fill=American Yellow},
% TBaseWriteThrough5X={mark=halfcircle*, fill=Green2},
TBaseWriteThrough10X={mark=*, fill=Green2},
% TBaseWriteBack5X={mark=halfdiamond*, fill=Green2,mark size=5pt},
TBaseWriteBack10X={mark=diamond*, fill=Green2,mark size=5pt},
TBaseAEP={mark=pentagon*, fill=Green2, draw=black}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$Space Cost$,
ylabel=$Performance Cost$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8,10},
xtick={0,2,4,6,8,10},
view={0}{90},
domain=0:11,
y domain=0:11,
colormap={custom}{
color(0)=(color1)
color(1)=(color2)
},
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={font=\tiny, legend columns=3},
legend image post style={mark size=2.5pt},
legend cell align={left},
]
\addplot3[surf, shader=flat,forget plot] {max(x , y)};
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
(0.496651786,0.0000825730,0) [Cassandra]
(0.496651786,0.0001110618,0) [hbase]
(10.00172466,0.0000100245,0) [TBaseAof]
(9.827410515,0.0000164901,0) [RedisAof]
% (1.078587099,0.0000211753494132,0) [TBaseWriteBack5X]
(0.578500866,0.0000216638748085,0) [TBaseWriteBack10X]
(0.328457749,0.0000286632,0) [TBaseWriteThrough10X]
% (0.578500866,0.0000275775,0) [TBaseWriteThrough5X]
(1.866645295,0.0000120607,0) [TBaseAEP]
};
% \legend{Cassandra, Hbase, Redis aof, TBase wt 5X, TBase wt 10X, TBase wb 5X, TBase wb 10X,TBaseAEP}
\end{axis}
\end{tikzpicture}
}
\subfigure[95\% read 5\%write]{
\begin{tikzpicture}[scale=0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt
},
scatter/classes={
Cassandra={mark=square*, fill=Giants Orange},
hbase={mark=square*, fill=Blue Jeans},
TBaseAof={mark=square*, fill=Green2},
RedisAof={mark=square*, fill=American Yellow},
% TBaseWriteThrough5X={mark=halfcircle*, fill=Green2},
TBaseWriteThrough10X={mark=*, fill=Green2},
% TBaseWriteBack5X={mark=halfdiamond*, fill=Green2,mark size=5pt},
TBaseWriteBack10X={mark=diamond*, fill=Green2,mark size=5pt},
TBaseAEP={mark=pentagon*, fill=Green2, draw=black}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$Space Cost$,
ylabel=$Performance Cost$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8,10},
xtick={0,2,4,6,8,10},
colorbar,
colorbar style={
title=Cost,
ytick={1,5,10},
yticklabels={$1$,$5$,$10$}
},
view={0}{90},
domain=0:11,
y domain=0:11,
colormap={custom}{
color(0)=(color1)
color(1)=(color2)
},
samples=20,
samples y=20,
legend style={font=\tiny, legend columns=3},
legend image post style={mark size=2.5pt},
legend cell align={left},
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
]
\addplot3[surf, shader=flat,forget plot] {max(x , y)};
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
(0.496651786,0.0000806403,0) [Cassandra]
(0.496651786,0.0000862645,0) [hbase]
(10.00172466,0.0000077198,0) [TBaseAof]
(9.827410515,0.0000157161,0) [RedisAof]
% (1.078587099,0.0000198588661831,0) [TBaseWriteBack5X]
(0.578500866,0.0000206928530260,0) [TBaseWriteBack10X]
(0.328457749,0.0000199558,0) [TBaseWriteThrough10X]
% (0.578500866,0.0000181014,0) [TBaseWriteThrough5X]
(1.866645295,0.0000088876,0) [TBaseAEP]
};
% \legend{Cassandra, Hbase, Redis aof, TBase wt 5X, TBase wt 10X, TBase wb 5X, TBase wb 10X,TBaseAEP}
\end{axis}
\end{tikzpicture}
}
\caption{Cost of database with persistence}
\label{persis cost}
\end{figure}
\begin{figure}
\centering
\begin{tikzpicture}[scale = 0.6]
\begin{axis}[
hide axis,
scale only axis,
height=0pt,
width=0pt,
xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
legend style={font=\fontsize{12}{10}\selectfont, legend columns=4, at={(0.5,1)}, anchor=north, row sep=0.5pt, column sep=2pt},
legend image post style={mark size=2.5pt, only marks}, % 仅显示标记,无线条
legend cell align={left},
]
% 根据您的要求添加图例项
\addlegendimage{mark=square*, fill=Giants Orange} \addlegendentry{Cassandra}
\addlegendimage{mark=square*, fill=Blue Jeans,mark size=4pt} \addlegendentry{HBase}
\addlegendimage{mark=*, fill=American Yellow,mark size=4pt} \addlegendentry{Redis}
\addlegendimage{mark=*, fill=Purple, mark size=4pt} \addlegendentry{Memcached}
\addlegendimage{mark=*, fill=Moonstone, draw=black, mark size=4pt} \addlegendentry{Dragonfly}
\addlegendimage{mark=*, fill=Green2, draw=black, mark size=4pt} \addlegendentry{TierBase-Raw}
\addlegendimage{mark=triangle*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-e}
\addlegendimage{mark=halfcircle*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-PMem}
\addlegendimage{mark=diamond*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wt-4X}
\addlegendimage{mark=halfdiamond*, fill=Green2,mark size=4pt} \addlegendentry{TierBase-wb-4X}
\addlegendimage{mark=pentagon*, fill=Green2, draw=black,mark size=4pt}
\addlegendentry{TierBase-PBC}
\end{axis}
\end{tikzpicture}
\par % 或者使用 \\
\vspace{-2mm}
\subfigure[User Info Service]{
\label{case study1}
\begin{tikzpicture}[scale = 0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt,
},
scatter/classes={
Cassandra={mark=square*, fill=Giants Orange},
Hbase={mark=square*, fill=Blue Jeans},
Redis={mark=*, fill=American Yellow, mark size=4pt},
Dragonfly={mark=*, fill=Moonstone, draw=black, mark size=4pt},
Memcached={mark=*, fill=Purple, mark size=4pt},
TierBase-raw={mark=*, fill=Green2, draw=black, mark size=4pt},
TierBase-pmem={mark=halfcircle*, fill=Green2,mark size=4pt},
TierBase-wb={mark=halfdiamond*, fill=Green2,mark size=4pt},
TierBase-wt={mark=diamond*, fill=Green2,mark size=4pt},
TierBase-compression={mark=pentagon*, fill=Green2, draw=black,mark size=4pt},
TierBase-e={mark=triangle*, fill=Green2,mark size=4pt}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$cost(GB)$,
ylabel=$cost(QPS)$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8},
xtick={0,2,4,6,8},
view={0}{90},
domain=0:8,
y domain=0:8,
colormap={custom}{
% color(0)=(red!5!yellow)
% color(0.5)=(red!40!yellow)
% color(1)=(red!70!yellow)
color(0)=(color1)
color(1)=(color2)
% color(0.5)=(red!30!white)
},
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={font=\tiny, legend columns=3,
row sep=0.5pt,
column sep=2pt
},
legend cell align={left},
legend image post style={mark size=2.5pt},
]
\addplot3[surf, shader=flat,forget plot] {max(x, y)};%这里x,y是算出来后的相对成本,不需要额外运算
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
(0.993303571,0.000134282,0) [Cassandra]
(0.993303571,0.000130839,0) [Hbase]
(2*3.430351257,0.000010850,0) [Redis]
(2*2.847989082,0.000014454,0) [Dragonfly]
(2*3.718143463,0.000009500,0) [Memcached]
(2*3.297821045,0.000011431,0) [TierBase-raw]
(0.762985343,0.000034125,0) [TierBase-wt]
(1.422549552,0.000032339,0) [TierBase-wb]
% (1.685328484,0.000024872,0) [TierBase-compression]
(2*1.331118,0.00002016,0)[TierBase-compression]
(2*2.293272972,0.000013222,0) [TierBase-pmem]
(2*3.297821045,0.000003850,0) [TierBase-e]
};
% \legend{Cassandra, Hbase, Redis aof, TBase wt 5X, TBase wt 10X, TBase wb 5X, TBase wb 10X,TBase AEP}
\end{axis}
\end{tikzpicture}
}
\subfigure[Capital Reconciliation]{
\label{case study2}
\begin{tikzpicture}[scale = 0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt,
},
scatter/classes={
Cassandra={mark=square*, fill=Giants Orange},
Hbase={mark=square*, fill=Blue Jeans},
Redis={mark=*, fill=American Yellow, mark size=4pt},
Dragonfly={mark=*, fill=Moonstone, draw=black ,mark size=4pt},
Memcached={mark=*, fill=Purple, mark size=4pt},
TierBase-raw={mark=*, fill=Green2, draw=black, mark size=4pt},
TierBase-pmem={mark=halfcircle*, fill=Green2,mark size=4pt},
TierBase-wb={mark=halfdiamond*, fill=Green2,mark size=4pt},
TierBase-compression={mark=pentagon*, fill=Green2, draw=black,mark size=4pt},
TierBase-wt={mark=diamond*, fill=Green2,mark size=4pt},
TierBase-e={mark=triangle*, fill=Green2,mark size=4pt}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$cost(GB)$,
ylabel=$cost(QPS)$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8},
xtick={0,2,4,6,8},
view={0}{90},
domain=0:8,
y domain=0:8,
colormap={custom}{
% color(0)=(red!5!yellow)
% color(0.5)=(red!40!yellow)
% color(1)=(red!70!yellow)
color(0)=(color1)
color(1)=(color2)
% color(0.5)=(red!30!white)
},
% colorbar,
% colorbar style={
% title=Cost,
% ytick={2,4,6},
% yticklabels={$2$,$4$,$6$}
% },
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={font=\tiny, legend columns=3,
row sep=0.5pt,
column sep=2pt
},
legend cell align={left},
legend image post style={mark size=2.5pt},
]
\addplot3[surf, shader=flat,forget plot] {max(x, y)};%这里x,y是算出来后的相对成本,不需要额外运算
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
(2*3.491230011,0.000010061,0) [Memcached]
(2*3.61715126,0.000013230,0) [Redis]
(2*3.025972366,0.000012971,0) [Dragonfly]
(0.993303571,0.000072177,0) [Cassandra]
(0.993303571,0.000094415,0) [Hbase]
(2*3.844118118,0.000012241,0) [TierBase-raw]
(1.081582783,0.000042850,0) [TierBase-wt]
(2.042612312,0.000025299,0) [TierBase-wb]
(2*3.719650269,0.000043146,0) [TierBase-compression]
(2*2.661312543,0.000012898,0) [TierBase-pmem]
(2*3.844118118,0.000007357,0) [TierBase-e]
};
% \legend{Cassandra, Hbase, Redis aof, TBase wt 5X, TBase wt 10X, TBase wb 5X, TBase wb 10X,TBase AEP}
\end{axis}
\end{tikzpicture}
}
\caption{Cost of case study}
% \label{case study}
\end{figure}
\begin{figure}
\centering
% \begin{tikzpicture}[scale = 0.93]
% \begin{axis}[
% hide axis,
% scale only axis,
% height=0pt,
% width=0pt,
% xmin=0, xmax=1, ymin=0, ymax=1, % 设置轴范围
% legend style={font=\small, legend columns=4, at={(0.5,1)}, anchor=north, row sep=0.5pt, column sep=2pt},
% legend image post style={mark size=2.5pt, only marks}, % 仅显示标记,无线条
% legend cell align={left},
% ]
% % 根据您的要求添加图例项
% \addlegendimage{mark=square*, fill=Giants Orange} \addlegendentry{L-500}
% \addlegendimage{mark=square*, fill=Blue Jeans,mark size=4pt} \addlegendentry{L-100}
% \addlegendimage{mark=square*, fill=American Yellow,mark size=4pt} \addlegendentry{L-50}
% \addlegendimage{mark=square*, fill=Moonstone, draw=black, mark size=4pt} \addlegendentry{L-10}
% \addlegendimage{mark=square*, fill=Purple, mark size=4pt} \addlegendentry{L1}
% \addlegendimage{mark=square*, fill=Green2, draw=black, mark size=4pt} \addlegendentry{L10}
% \addlegendimage{mark=square*, fill=Olive, draw=black, mark size=4pt} \addlegendentry{L15}
% \addlegendimage{mark=square*, fill=Blood, draw=black, mark size=4pt} \addlegendentry{L22}
% \addlegendimage{mark=*, fill=American Yellow,mark size=4pt} \addlegendentry{L-50nd}
% \addlegendimage{mark=*, fill=Moonstone, draw=black, mark size=4pt} \addlegendentry{L-10nd}
% \addlegendimage{mark=*, fill=Purple, mark size=4pt} \addlegendentry{L1nd}
% \addlegendimage{mark=*, fill=Blood, draw=black, mark size=4pt} \addlegendentry{L22nd}
% \end{axis}
% \end{tikzpicture}
% \par % 或者使用 \\
% \vspace{-2mm}
\subfigure[Compression level trade-offs]{
\label{compression_tradeoff}
\begin{tikzpicture}[scale = 0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt,
},
scatter/classes={
Full={mark=*, fill=Olive, mark size=4.5pt},
% L-100={mark=square*, fill=Blue Jeans},
% L-50={mark=square*, fill=American Yellow, mark size=4pt},
% L-10={mark=pentagon*, fill=Moonstone, draw=black, mark size=4pt},
% L1={mark=square*, fill=Moonstone, mark size=3pt},
% L10={mark=diamond*, fill=Moonstone, draw=black, mark size=4pt},
% L15={mark=square*, fill=Olive, draw=black, mark size=4pt},
L22={mark=triangle*, fill=Moonstone, draw=black, mark size=4pt},
% L-50nd={mark=*, fill=American Yellow, mark size=4pt},
% L-10nd={mark=pentagon*, fill=Purple, draw=black, mark size=4pt},
L1nd={mark=square*, fill=Purple, mark size=3pt},
% L10nd={mark=diamond*, fill=Purple, draw=black, mark size=4pt},
% L22nd={mark=triangle*, fill=Purple, draw=black, mark size=4pt},
PBC={mark=pentagon*, fill=Green2, draw=black,mark size=4pt}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$Space Cost$,
ylabel=$Performance Cost$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8},
xtick={0,2,4,6,8},
view={0}{90},
domain=0:8,
y domain=0:8,
colormap={custom}{
% color(0)=(red!5!yellow)
% color(0.5)=(red!40!yellow)
% color(1)=(red!70!yellow)
color(0)=(color1)
color(1)=(color2)
% color(0.5)=(red!30!white)
},
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={font=\fontsize{12}{10}\selectfont,
legend columns=4,
at={(1,1.2)},
row sep=0.5pt,
column sep=2pt
},
legend cell align={left},
legend image post style={mark size=3.5pt},
]
\addplot3[surf, shader=flat,forget plot] {max(x, y)};%这里x,y是算出来后的相对成本,不需要额外运算
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
(2*3.243796 ,0.00001189,0) [Full]
(2*2.048442,0.00001465,0) [L22] %-50
(2*1.768524,0.00001683,0) [L22] %-10
(2*1.495251,0.00001918,0) [L22] %1
(2*1.431094,0.00002005,0) [L22] %10
% (1.417696,0.00002147,0) [L15]
(2*1.415869,0.00003107,0) [L22]% 22
(2*3.231505,0.000012,0) [L1nd] %-50
(2*2.9,0.000016,0) [L1nd]%-10
(2*2.548791,0.000025,0) [L1nd] %1
(2*2.526948,0.000036,0) [L1nd] %10
(2*2.521176,0.000042,0) [L1nd] %22
(2*1.331118,0.00002016,0) [PBC]
};
\legend{Raw,Zstd-dict,Zstd,PBC}
\end{axis}
\end{tikzpicture}
}
\hspace{1mm}
\subfigure[Cache ratio trade-off ]{
\label{Tier_tradeoff}
\begin{tikzpicture}[scale = 0.52]
\pgfplotsset{
defaultmark/.style={draw=black, line width=0.25pt},
mystyle/.style={
only marks,
y filter/.code={\pgfmathparse{\pgfmathresult*40000}\pgfmathresult},
mark size=3.5pt,
},
scatter/classes={
Full={mark=*, fill=Olive, mark size=4.5pt},
WB2X={mark=square*, fill=Purple, mark size=3pt},
WB3X={mark=square*, fill=Moonstone, draw=black, mark size=3pt},
WB4X={mark=square*, fill=American Yellow, mark size=3pt},
WB5X={mark=square*, fill=Green2, draw=black, mark size=3pt}
% WB6X={mark=square*, fill=Blue Jeans},
% WB12X={mark=square*, fill=Giants Orange}
}
}
\begin{axis}[
height=7cm,
width=7cm,
xlabel=$Space Cost$,
ylabel=$Performance Cost$,
xticklabel={
\pgfmathparse{\tick}
\pgfmathprintnumber{\pgfmathresult}
},
yticklabel={
\pgfmathprintnumber{\tick}
},
ytick={2,4,6,8},
xtick={0,2,4,6,8},
view={0}{90},
domain=0:8,
y domain=0:8,
colormap={custom}{
% color(0)=(red!5!yellow)
% color(0.5)=(red!40!yellow)
% color(1)=(red!70!yellow)
color(0)=(color1)
color(1)=(color2)
% color(0.5)=(red!30!white)
},
samples=20,
samples y=20,
scaled y ticks=false,
scaled x ticks=false,
yticklabel style={/pgf/number format/fixed},
xticklabel style={/pgf/number format/fixed},
legend style={
font=\fontsize{12}{10}\selectfont,
legend columns=3,
at={(1,1.3)},
legend columns=3,
row sep=0.5pt,
column sep=2pt
},
legend cell align={left},
legend image post style={mark size=3pt},
]
\addplot3[surf, shader=flat,forget plot] {max(x, y)};%这里x,y是算出来后的相对成本,不需要额外运算
\addplot3[mystyle, defaultmark, scatter, scatter src=explicit symbolic] coordinates {
% (0.602671451,0.00003784,0) [WB12X]
% (1.105258341,0.00003705,0) [WB6X]
(1.607845231,0.00003258,0) [WB4X]
(2.110432121,0.00003234,0) [WB3X]
(3.015521338,0.00003231,0) [WB2X]
(6.487591315,0.00001189,0) [Full]
(1.376655262,0.0000340,0) [WB5X]
% (1.376325335,0.00005739,0) [WT12X]
% (2.376325335,0.00005533,0) [WT6X]
% (3.376325335,0.00004627,0) [WT4X]
% (4.376325335,0.00004976,0) [WT3X]
% (6.376325335,0.00004550,0) [WT2X]
};
\legend{In-mem,wb-2X,wb-3X,wb-4X,wb-5X}
\end{axis}
\end{tikzpicture}
}
\caption{Space-Performance Cost Trade-offs}
\label{Trade-off}
\end{figure}
% \begin{table}[]
% \begin{tabular}{@{}ccc@{}}
% \toprule
% Fast Storage & Slow Storage & Time Interval(s) \\ \midrule
% Raw & PMem & 195 \\
% Raw & Compression(PBC) & 367 \\
% PMem & Compression(PBC) & 816\\ \bottomrule
% \end{tabular}
% % \vspace{11pt}
% \caption{Break-even interval between different configurations.}
% \label{interval_table}
% % \vspace{-8pt}
% \end{table}
\begin{table}[htbp]
\centering
\caption{Break-even interval between different configurations.}
\begin{tabular}{ccc}
\toprule
Fast Storage & Slow Storage & Time Interval(s) \\
\midrule
Raw & PMem & 98 \\
Raw & Compression(PBC) & 184 \\
PMem & Compression(PBC) & 264 \\
\bottomrule
\end{tabular}
\label{interval_table}
\end{table}
\vspace{-7mm} %取vldb6
\section{Related Work}
\subsection{Key-Value Stores}
%\textbf{\textcolor{red}{TODO Add more details of Redis, Mememcached, Dragonfly etc. @Weibo}}
Key-value stores, a type of NoSQL databases, play a crucial role in Internet applications. Diverging from traditional relational databases, they provide fast, scalable, and efficient data access essential for a wide range of online applications.
Memcached \cite{memcached} is a distributed caching system enhancing web application performance by minimizing database load and optimizing memory across servers.
Redis \cite{redis}, unlike Memcached's focus on caching, is a multifunctional in-memory database with a wide variety of data types, extended functionality, and persistence, suitable for complex, high-performance applications.
KeyDB \cite{keydb} enhances Redis with multi-threading. Dragonfly \cite{dragonflydb} offers compatibility with Redis and Memcached, using multi-threaded, shared-nothing architecture. Etcd \cite{etcd} is crucial for Kubernetes, providing consistent configuration across clusters. EVCached \cite{evcache}, ElastiCache \cite{elasticache}, and Azure Cache for Redis \cite{azurecache} are managed caching solutions, improving cloud applications by reducing database loads and enabling quick data access.
\subsection{Cost Optimization}
\subsubsection{Cost model} Constructing a reasonable cost model is crucial for the optimization of database costs. Total Cost of Ownership (TCO)\cite{tco} refers to the sum of all related costs throughout the entire lifecycle of an item or service, including purchasing, operating, maintaining, and disposing of it. This concept is widely applied across various fields. Some cost models \cite{10.5555/1287369.1287387, 10.1007/s00778-021-00660-x, 9835426} primarily focus on estimating or optimizing query execution time or overall system performance. They consider factors like memory access patterns, cache behavior, and data structure efficiency to predict or improve query processing speed. Other cost models \cite{10.14778/3551793.3551837, 10.1145/2213836.2213844} explicitly consider financial costs, such as the cost of operating cloud resources or the cost differences between different types of storage medium.
However, these methods often struggle to adequately represent the complex relationships between configurations and costs, especially when considering diverse workload characteristics. As a result, they are not directly applicable to our study's objective.
\subsubsection{Optimization strategy} Contrasting with TierBase, which concentrates on a comprehensive cost model that balances performance and storage expenses, some studies \cite{anna, 10.1145/1989323.1989357, 8741093, 10597997} achieve more effective resource allocation or configuration parameter adjustments by monitoring workload variations within databases, thereby enhancing resource utilization and reducing costs. Cosine \cite{cosine} actively tailors its storage engine architecture to optimize costs, adapting to workload demands, cloud budgets, and specific performance objectives.
\subsubsection{Compression}
In database technology, Lempel-Ziv(LZ) algorithms are widely used for data compression to improve storage and transfer efficiency. TiDB \cite{tidb} and Hadoop \cite{hadoop} use LZ4, while LevelDB \cite{leveldb} uses Snappy \cite{snappy}. Zstandard (Zstd) \cite{zstd} is chosen by Facebook's RocksDB \cite{rocksdb} and Redshift \cite{redshift} for its efficiency. Apache Cassandra \cite{Cassandra} also uses compression to reduce disk space use. For memory efficiency, SlimCache \cite{SlimCache} and zExpander \cite{zExpander} compress data in caches, and COLLATE \cite{COLLATE} applies lightweight compression in in-memory databases.
\subsubsection{Thread management}
%弹性线程
Thread management techniques play a pivotal role in DBMSs by optimizing the handling of concurrent client requests and maximizing resource utilization.
In systems like \cite{rocksdb,riak,oracle,mysql}, dynamic adjustment of thread pools is utilized to efficiently handle fluctuating workloads. On the other hand, databases such as \cite{memcached,redis} maintain a fixed thread count, ensuring consistent resource allocation. \cite{tarantool,mongodb, coroutines1,coroutines2}, use coroutines in certain scenarios for managing concurrent requests, balancing thread overhead with concurrency. \cite{numa_aware_thread} discusses thread management in the NUMA-aware task scheduling. \cite{aerospike} merges these approaches, applying dynamic thread pools for general requests and fixed threads for specific tasks.
\subsubsection{Persistent memory}
Non-volatile memory, also known as persistent memory is a type of memory that keeps its data even when the power is turned off.
% Intel's Optane DC Persistent Memory, a commercial product of non-volatile memory, combines DRAM speed with persistent storage, retaining data without power and outperforming traditional storage.
Many current efforts are integrating PMem into storage systems \cite{Viper,Tair-PMem,ChameleonDB,ByteDance_pmem,NV-SQL,lsmnvm,zen} to enhance performance. However, PMem has its own set of challenges and issues. Some studies \cite{costmodel_pmem,PerMA-Bench,manage_nvmsystem} are exploring how systems should navigate between PMem and DRAM, addressing concerns about optimal choice and management.
% \bibliography{references}
% \bibliographystyle{ieeetr}
\section{Conclusion}
%In conclusion, this paper introduces a novel distributed NoSQL database system, emphasizing its disaggregated cache-storage architecture designed to efficiently manage large-scale data while optimizing costs. Key features include pre-trained compression mechanism, elastic threading technique, persistent memory utilization and innovative caching policies. Another contribution is the development of a tailored cost model, aligning with the Five Minute Rule for modern storage systems. The paper substantiates TierBase's effectiveness through comprehensive evaluations, demonstrating its cost-efficiency compared to existing solutions.
% In this paper, we introduce TierBase, a distributed NoSQL database system developed by Ant Group to address the challenges of managing large-scale online data serving systems. TierBase employs a disaggregated cache-storage architecture and incorporates cost-effective optimizations, including pre-trained compression, elastic threading, and the use of persistent memory. We propose a cost model that simplifies the computation of costs for NoSQL database systems, focusing on Performance Cost and Capacity Cost metrics. Extensive evaluations using both public and real-world workloads demonstrate TierBase's superior cost-effectiveness compared to existing solutions. %showcasing its ability to achieve a 50\% reduction in costs in primary scenarios.
This paper introduces TierBase, a distributed key-value store developed by Ant Group to address the challenges of managing large-scale online data serving systems. TierBase employs a tiered storage architecture and incorporates cost-effective optimizations. We propose a space-performance cost model to guide the selection of optimal storage configurations for diverse workloads. Extensive evaluations using both synthetic benchmarks and real-world workloads demonstrate TierBase's superior cost-effectiveness compared to existing solutions.
\section*{Acknowledgment}
We thank everyone who contributed to the design and development of the TierBase system and its cost model. This work was supported by Ant Group Research Fund.
\begin{thebibliography}{10}
\bibitem{cities}
Cities.
\newblock \url{https://www.geonames.org/search.html?q=&country=}.
\bibitem{aerospike}
Inc. Aerospike.
\newblock Aerospike: The flash-optimized, in-memory nosql database.
\newblock 2010.
\bibitem{redshift}
Amazon.
\newblock Redshift.
\newblock https://aws.amazon.com/cn/redshift/.
\bibitem{Amdahl}
Gene~M. Amdahl.
\newblock Validity of the single processor approach to achieving large scale computing capabilities.
\newblock In {\em American Federation of Information Processing Societies: Proceedings of the {AFIPS} '67 Spring Joint Computer Conference, April 18-20, 1967, Atlantic City, New Jersey, {USA}}, volume~30 of {\em {AFIPS} Conference Proceedings}, pages 483--485. {AFIPS} / {ACM} / Thomson Book Company, Washington {D.C.}, 1967.
\bibitem{NV-SQL}
Mijin An, Jonghyeok Park, Tianzheng Wang, Beomseok Nam, and Sang{-}Won Lee.
\newblock {NV-SQL:} boosting {OLTP} performance with non-volatile dimms.
\newblock {\em Proc. {VLDB} Endow.}, 16(6):1453--1465, 2023.
\bibitem{github_pbc}
{Ant Group}.
\newblock {PBC}.
\newblock \url{https://github.com/antgroup/pbc}, 2024.
\bibitem{vsag}
AntGroup.
\newblock Vsag.
\newblock \url{https://github.com/alipay/vsag}.
\bibitem{five30}
Raja Appuswamy, Renata Borovica{-}Gajic, Goetz Graefe, and Anastasia Ailamaki.
\newblock The five-minute rule thirty years later and its impact on the storage hierarchy.
\newblock In Rajesh Bordawekar and Tirthankar Lahiri, editors, {\em International Workshop on Accelerating Analytics and Data Management Systems Using Modern Processor and Storage Architectures, ADMS@VLDB 2017, Munich, Germany, September 1, 2017}, pages 1--8, 2017.
\bibitem{Viper}
Lawrence Benson, Hendrik Makait, and Tilmann Rabl.
\newblock Viper: An efficient hybrid pmem-dram key-value store.
\newblock {\em Proc. {VLDB} Endow.}, 14(9):1544--1556, 2021.
\bibitem{PerMA-Bench}
Lawrence Benson, Leon Papke, and Tilmann Rabl.
\newblock Perma-bench: Benchmarking persistent memory access.
\newblock {\em Proc. {VLDB} Endow.}, 15(11):2463--2476, 2022.
\bibitem{cosine}
Subarna Chatterjee, Meena Jagadeesan, Wilson Qin, and Stratos Idreos.
\newblock Cosine: {A} cloud-cost optimized self-designing key-value storage engine.
\newblock {\em Proc. {VLDB} Endow.}, 15(1):112--126, 2021.
\bibitem{lsmnvm}
Lixiang Chen, Ruihao Chen, Chengcheng Yang, Yuxing Han, Rong Zhang, Xuan Zhou, Peiquan Jin, and Weining Qian.
\newblock Workload-aware log-structured merge key-value store for {NVM-SSD} hybrid storage.
\newblock In {\em 39th {IEEE} International Conference on Data Engineering, {ICDE} 2023, Anaheim, CA, USA, April 3-7, 2023}, pages 2207--2219. {IEEE}, 2023.
\bibitem{mongodb}
Kristina Chodorow.
\newblock Mongodb: A scalable, high-performance, open source {NoSQL} database.
\newblock 2010.
\bibitem{zstd}
Yann Collet and Murray~S. Kucherawy.
\newblock Zstandard compression and the application/zstd media type.
\newblock {\em RFC}, 8878:1--45, 2018.
\bibitem{ycsb}
Brian~F. Cooper, Adam Silberstein, Erwin Tam, Raghu Ramakrishnan, and Russell Sears.
\newblock Benchmarking cloud serving systems with {YCSB}.
\newblock In Joseph~M. Hellerstein, Surajit Chaudhuri, and Mendel Rosenblum, editors, {\em Proceedings of the 1st {ACM} Symposium on Cloud Computing, SoCC 2010, Indianapolis, Indiana, USA, June 10-11, 2010}, pages 143--154. {ACM}, 2010.
\bibitem{10.1145/1989323.1989357}
Carlo Curino, Evan~P.C. Jones, Samuel Madden, and Hari Balakrishnan.
\newblock Workload-aware database monitoring and consolidation.
\newblock In {\em Proceedings of the 2011 ACM SIGMOD International Conference on Management of Data}, SIGMOD '11, page 313–324, New York, NY, USA, 2011. Association for Computing Machinery.
\bibitem{dragonflydb}
DragonflyDB.
\newblock Dragonflydb.
\newblock https://www.dragonflydb.io/.
\bibitem{rocksdb}
Facebook.
\newblock Rocksdb.
\newblock https://github.com/facebook/rocksdb.
\bibitem{Tair-PMem}
Caixin Gong, Chengjin Tian, Zhengheng Wang, Sheng Wang, Xiyu Wang, Qiulei Fu, Wu~Qin, Qian Long, Rui Chen, Jiang Qi, Ruo Wang, Guoyun Zhu, Chenghu Yang, Wei Zhang, and Feifei Li.
\newblock Tair-pmem: a fully durable non-volatile memory database.
\newblock {\em Proc. {VLDB} Endow.}, 15(12):3346--3358, 2022.
\bibitem{leveldb}
Google.
\newblock Leveldb.
\newblock https://github.com/google/leveldb.
\bibitem{snappy}
Google.
\newblock Snappy compression library.
\newblock \url{https://github.com/google/snappy}.
\bibitem{five20}
Goetz Graefe.
\newblock The five-minute rule 20 years later (and how flash memory changes the rules).
\newblock {\em Commun. {ACM}}, 52(7):48--59, 2009.
\bibitem{gray19875}
Jim Gray and Franco Putzolu.
\newblock The 5 minute rule for trading memory for disc accesses and the 10 byte rule for trading memory for cpu time.
\newblock {\em ACM SIGMOD Record}, 16(3):395--398, 1987.
\bibitem{tarantool}
Mail.Ru Group.
\newblock Tarantool: An in-memory database and application server.
\newblock 2012.
\bibitem{8741093}
Rui Han, Chi~Harold Liu, Zan Zong, Lydia~Y. Chen, Wending Liu, Siyi Wang, and Jianfeng Zhan.
\newblock Workload-adaptive configuration tuning for hierarchical cloud schedulers.
\newblock {\em IEEE Transactions on Parallel and Distributed Systems}, 30(12):2879--2895, 2019.
\bibitem{coroutines2}
Yongjun He, Jiacheng Lu, and Tianzheng Wang.
\newblock Corobase: Coroutine-oriented main-memory database engine.
\newblock {\em Proc. {VLDB} Endow.}, 14(3):431--444, 2020.
\bibitem{10.1007/s00778-021-00660-x}
Moditha Hewasinghage, Alberto Abell\'{o}, Jovan Varga, and Esteban Zim\'{a}nyi.
\newblock A cost model for random access queries in document stores.
\newblock {\em The VLDB Journal}, 30(4):559–578, mar 2021.
\bibitem{COLLATE}
Juliana Hildebrandt, Dirk Habich, Patrick Damme, and Wolfgang Lehner.
\newblock Compression-aware in-memory query processing: Vision, system design and beyond.
\newblock In Spyros Blanas, Rajesh Bordawekar, Tirthankar Lahiri, Justin Levandoski, and Andrew Pavlo, editors, {\em Data Management on New Hardware}, pages 40--56, Cham, 2017. Springer International Publishing.
\bibitem{10.1145/3185751}
Xiameng Hu, Xiaolin Wang, Lan Zhou, Yingwei Luo, Zhenlin Wang, Chen Ding, and Chencheng Ye.
\newblock Fast miss ratio curve modeling for storage cache.
\newblock {\em ACM Trans. Storage}, 14(2), apr 2018.
\bibitem{tidb}
Dongxu Huang, Qi~Liu, Qiu Cui, Zhuhe Fang, Xiaoyu Ma, Fei Xu, Li~Shen, Liu Tang, Yuxing Zhou, Menglong Huang, Wan Wei, Cong Liu, Jian Zhang, Jianjun Li, Xuelian Wu, Lingyu Song, Ruoxi Sun, Shuaipeng Yu, Lei Zhao, Nicholas Cameron, Liquan Pei, and Xin Tang.
\newblock Tidb: A raft-based htap database.
\newblock {\em Proc. VLDB Endow.}, 13(12):3072–3084, aug 2020.
\bibitem{memcached}
Danga Interactive.
\newblock Memcached.
\newblock \url{http://memcached.org/}.
\bibitem{10597997}
Zhaoxuan Ji, Zhongle Xie, Yuncheng Wu, and Meihui Zhang.
\newblock Lbsc: A cost-aware caching framework for cloud databases.
\newblock In {\em 2024 IEEE 40th International Conference on Data Engineering (ICDE)}, pages 4911--4924, 2024.
\bibitem{SlimCache}
Yichen Jia, Zili Shao, and Feng Chen.
\newblock Slimcache: An efficient data compression scheme for flash-based key-value caching.
\newblock {\em ACM Trans. Storage}, 16(2), jun 2020.
\bibitem{keydb}
KeyDB.
\newblock Keydb.
\newblock \url{https://docs.keydb.dev/docs/}.
\bibitem{Cassandra}
Avinash Lakshman and Prashant Malik.
\newblock Cassandra: a decentralized structured storage system.
\newblock {\em {ACM} {SIGOPS} Oper. Syst. Rev.}, 44(2):35--40, 2010.
\bibitem{10.14778/3551793.3551837}
Robert Lasch, Thomas Legler, Norman May, Bernhard Scheirle, and Kai-Uwe Sattler.
\newblock Cost modelling for optimal data placement in heterogeneous main memory.
\newblock {\em Proc. VLDB Endow.}, 15(11):2867–2880, jul 2022.
\bibitem{costmodel_pmem}
Robert Lasch, Thomas Legler, Norman May, Bernhard Scheirle, and Kai{-}Uwe Sattler.
\newblock Cost modelling for optimal data placement in heterogeneous main memory.
\newblock {\em Proc. {VLDB} Endow.}, 15(11):2867--2880, 2022.
\bibitem{9835426}
Yan Li, Liwei Wang, Sheng Wang, Yuan Sun, and Zhiyong Peng.
\newblock A resource-aware deep cost model for big data query processing.
\newblock In {\em 2022 IEEE 38th International Conference on Data Engineering (ICDE)}, pages 885--897, 2022.
\bibitem{zen}
Gang Liu, Leying Chen, and Shimin Chen.
\newblock Zen+: a robust {NUMA}-aware {OLTP} engine optimized for non-volatile main memory.
\newblock {\em {VLDB} J.}, 32(1):123--148, 2023.
\bibitem{10.5555/1287369.1287387}
Stefan Manegold, Peter Boncz, and Martin~L. Kersten.
\newblock Generic database cost models for hierarchical memory systems.
\newblock In {\em Proceedings of the 28th International Conference on Very Large Data Bases}, VLDB '02, page 191–202. VLDB Endowment, 2002.
\bibitem{azurecache}
Microsoft.
\newblock Azure cache for {R}edis.
\newblock \url{https://azure.microsoft.com/en-us/services/cache/}.
\bibitem{tco}
Lars Mieritz and Bill Kirwin.
\newblock Defining gartner total cost of ownership.
\newblock {\em L. Mieritz, B. Kirwin}, 2005.
\bibitem{evcache}
Netflix.
\newblock Evcache.
\newblock \url{https://github.com/Netflix/EVCache}.
\bibitem{oracle}
Oracle.
\newblock Oracle database concepts.
\newblock \url{https://www.oracle.com/}, 2020.
\bibitem{mysql}
Oracle.
\newblock Mysql.
\newblock \url{https://www.mysql.com}, 2021.
\bibitem{10.1145/2213836.2213844}
Andrew Pavlo, Carlo Curino, and Stanley Zdonik.
\newblock Skew-aware automatic database partitioning in shared-nothing, parallel oltp systems.
\newblock In {\em Proceedings of the 2012 ACM SIGMOD International Conference on Management of Data}, SIGMOD '12, page 61–72, New York, NY, USA, 2012. Association for Computing Machinery.
\bibitem{etcd}
Brandon Philips.
\newblock etcd: A reliable distributed key value store.
\newblock In {\em CoreOS Fest}, 2015.
\bibitem{coroutines1}
Georgios Psaropoulos, Thomas Legler, Norman May, and Anastasia Ailamaki.
\newblock Interleaving with coroutines: {A} practical approach for robust index joins.
\newblock {\em Proc. {VLDB} Endow.}, 11(2):230--242, 2017.
\bibitem{numa_aware_thread}
Iraklis Psaroudakis, Tobias Scheuer, Norman May, Abdelkader Sellami, and Anastasia Ailamaki.
\newblock Scaling up concurrent main-memory column-store scans: Towards adaptive numa-aware data and task placement.
\newblock {\em Proc. {VLDB} Endow.}, 8(12):1442--1453, 2015.
\bibitem{redis}
Redis.
\newblock Redis.
\newblock \url{https://redis.io/}, 2009.
\bibitem{Cougar}
Bo~Sang, Shuwei Gu, Xiaojun Zhan, Mingjie Tang, Jian Liu, Xuan Chen, Jie Tan, Haoyuan Ge, Ke~Zhang, Ruoyi Ruan, and Wei Yan.
\newblock Cougar: A general framework for jobs optimization in cloud.
\newblock In {\em 2023 IEEE 39th International Conference on Data Engineering (ICDE)}, pages 3417--3429, 2023.
\bibitem{elasticache}
Amazon~Web Services.
\newblock Amazon elasticache.
\newblock \url{https://aws.amazon.com/elasticache/}.
\bibitem{riak}
Justin Sheehy and David Smith.
\newblock Bitcask: A log-structured hash table for fast key/value data.
\newblock {\em Basho White Paper}, 2010.
\bibitem{hadoop}
Konstantin Shvachko, Hairong Kuang, Sanjay Radia, and Robert Chansler.
\newblock The hadoop distributed file system.
\newblock In {\em 2010 IEEE 26th Symposium on Mass Storage Systems and Technologies (MSST)}, pages 1--10, 2010.
\bibitem{ByteDance_pmem}
Jason Sun, Haoxiang Ma, Li~Zhang, Huicong Liu, Haiyang Shi, Shangyu Luo, Kai Wu, Kevin Bruhwiler, Cheng Zhu, Yuanyuan Nie, Jianjun Chen, Lei Zhang, and Yuming Liang.
\newblock Accelerating cloud-native databases with distributed pmem stores.
\newblock In {\em 39th {IEEE} International Conference on Data Engineering, {ICDE} 2023, Anaheim, CA, USA, April 3-7, 2023}, pages 3043--3057. {IEEE}, 2023.
\bibitem{manage_nvmsystem}
Alexander van Renen, Viktor Leis, Alfons Kemper, Thomas Neumann, Takushi Hashida, Kazuichi Oe, Yoshiyasu Doi, Lilian Harada, and Mitsuru Sato.
\newblock Managing non-volatile memory in database systems.
\newblock In Gautam Das, Christopher~M. Jermaine, and Philip~A. Bernstein, editors, {\em Proceedings of the 2018 International Conference on Management of Data, {SIGMOD} Conference 2018, Houston, TX, USA, June 10-15, 2018}, pages 1541--1555. {ACM}, 2018.
\bibitem{anna}
Chenggang Wu, Vikram Sreekanti, and Joseph~M. Hellerstein.
\newblock Autoscaling tiered cloud storage in anna.
\newblock {\em Proc. {VLDB} Endow.}, 12(6):624--638, 2019.
\bibitem{zExpander}
Xingbo Wu, Li~Zhang, Yandong Wang, Yufei Ren, Michel Hack, and Song Jiang.
\newblock Zexpander: A key-value cache with both high performance and fewer misses.
\newblock In {\em Proceedings of the Eleventh European Conference on Computer Systems}, EuroSys '16, New York, NY, USA, 2016. Association for Computing Machinery.
\bibitem{pbc}
Jiujing Zhang, Zhitao Shen, Shiyu Yang, Lingkai Meng, Chuan Xiao, Wei Jia, Yue Li, Qinhui Sun, Wenjie Zhang, and Xuemin Lin.
\newblock High-ratio compression for machine-generated data.
\newblock {\em Proc. {ACM} Manag. Data}, 1(4):245:1--245:27, 2023.
\bibitem{ChameleonDB}
Wenhui Zhang, Xingsheng Zhao, Song Jiang, and Hong Jiang.
\newblock Chameleondb: a key-value store for optane persistent memory.
\newblock In Antonio Barbalace, Pramod Bhatotia, Lorenzo Alvisi, and Cristian Cadar, editors, {\em EuroSys '21: Sixteenth European Conference on Computer Systems, Online Event, United Kingdom, April 26-28, 2021}, pages 194--209. {ACM}, 2021.
\end{thebibliography}