微软并发Key-Value存储库FASTER介绍
微软支持并发的Key-Value 存储库有C++与C#两个版本。号称迄今为止最快的并发键值存储。下面是C#版本翻译:
FASTER C#可在.NET Framework和.NET Core中运行,并且可以在单线程和并发设置中使用。经过测试,可以在Windows和Linux上使用。它公开了一种API,该API可以执行读取,盲更新(Upserts)和读取-修改-写入(RMW)操作的混合。它支持大于内存的数据,并接受IDevice将日志存储在文件中的实现。提供了IDevice本地文件系统的实现,也可以写入远程文件系统。或者将远程存储映射到本地文件系统中。FASTER可以用作传统并发数据结构类似ConcurrentDictionary的高性能替代品,并且还支持大于内存的数据。它支持增量或非增量数据结构类型的检查点。
FASTER支持三种基本操作:
- Read:从键值存储中读取数据
- Upsert:将值盲目向上插入到存储中(不检查先前的值)
- Read-Modify-Write:更新存储区中的值,用于实现“求和”和“计数”之类的操作。
构建
在实例化FASTER之前,您需要创建FASTER将使用的存储设备。如果使用的是可移植类型(byte、int、double)类型,则仅需要混合日志设备。如果使用对象,则需要创建一个单独的对象日志设备。
IDevice log = Devices.CreateLogDevice("C:\\Temp\\hybridlog_native.log");
然后,按如下方式创建一个FASTER实例:
fht = new FasterKV<Key, Value, Input, Output, Empty, Functions>
(1L << 20, new Functions(), new LogSettings { LogDevice = log });
构造函数的类型参数
有六个基本概念,在实例化FASTER时作为通用类型参数提供:
- Key:这是键的类型,例如long。
- Value:这是存储在FASTER中的值的类型。
- Input:这是调用Read或RMW时提供给FASTER的输入类型。它可以被视为读取或RMW操作的参数。例如,对于RMW,可是增量累加到值。
- Output:这是读操作的输出类型,将值的相关部分复制到输出。
- Context:操作的用户定义上下文,如果没有必要使用Empty。
- Functions:需要回调时,使用IFunctions<>调用。
回调函数
用户提供一个实例化IFunctions<>。此类型封装了所有回调,下面将对其进行介绍:
- SingleReader和并发读ConcurrentReader:这些用于读取存储值并将它们复制到Output。单个读取器可以假定没有并发操作。
- SingleWriter和ConcurrentWriter:这些用于将值从源值写入存储。
- Completion callbacks完成回调:各种操作完成时调用。
- RMWUpdaters:用户指定了三个更新器,InitialUpdater,InPlaceUpdater和CopyUpdater。它们一起用于实现RMW操作。
- Hash Table Siz哈希表大小:这是分配给FASTER的存储行数,其中每个行为64字节。
- LogSettings 日志设置:这些设置与日志的大小、设备。
- Checkpoint设置:这些是与检查相关的设置,例如检查类型和文件夹。
- Serialization序列化设置:用于为键和值类型提供自定义序列化程序。序列化程序实现IObjectSerializer<Key>键和IObjectSerializer<Value>值。只有C#类对象非可移植类型才需要这些。
- Key比较器:用于为key提供更好的比较器IFasterEqualityComparer<Key>。
构造函数参数
FASTER的总内存占用量由以下参数控制:
- 哈希表大小:此参数(第一个构造函数参数)乘以64是内存中哈希表的大小(以字节为单位)。
- 日志大小:logSettings.MemorySizeBits表示混合日志的内存部分的大小(以位为单位)。换句话说对于参数设置B,日志的大小为2 ^ B字节。如果日志指向类对象,则此大小不包括对象的大小,因为FASTER无法访问此信息。日志的较旧部分溢出到存储中。
Sessions (Threads)会话(线程)
实例化FASTER之后,线程可以使用Session来使用FASTER
fht.StartSession();
fht.StopSession();
当所有线程都在FASTER上完成操作后,您最终销毁FASTER实例:
fht.Dispose();
示例
以下是一个简单示例,其中所有数据都在内存中,因此我们不必担心挂起的I / O操作。在此示例中也没有检查点。
public static void Test()
{
var log = Devices.CreateLogDevice("C:\\Temp\\hlog.log");
var fht = new FasterKV<long, long, long, long, Empty, Funcs>
(1L << 20, new Funcs(), new LogSettings { LogDevice = log });
fht.StartSession();
long key = 1, value = 1, input = 10, output = 0;
fht.Upsert(ref key, ref value, Empty.Default, 0);
fht.Read(ref key, ref input, ref output, Empty.Default, 0);
Debug.Assert(output == value);
fht.RMW(ref key, ref input, Empty.Default, 0);
fht.RMW(ref key, ref input, Empty.Default, 0);
fht.Read(ref key, ref input, ref output, Empty.Default, 0);
Debug.Assert(output == value + 20);
fht.StopSession();
fht.Dispose();
log.Close();
}
此示例的函数:
public class Funcs : IFunctions<long, long, long, long, Empty>
{
public void SingleReader(ref long key, ref long input, ref long value, ref long dst) => dst = value;
public void SingleWriter(ref long key, ref long src, ref long dst) => dst = src;
public void ConcurrentReader(ref long key, ref long input, ref long value, ref long dst) => dst = value;
public void ConcurrentWriter(ref long key, ref long src, ref long dst) => dst = src;
public void InitialUpdater(ref long key, ref long input, ref long value) => value = input;
public void CopyUpdater(ref long key, ref long input, ref long oldv, ref long newv) => newv = oldv + input;
public void InPlaceUpdater(ref long key, ref long input, ref long value) => value += input;
public void UpsertCompletionCallback(ref long key, ref long value, Empty ctx) { }
public void ReadCompletionCallback(ref long key, ref long input, ref long output, Empty ctx, Status s) { }
public void RMWCompletionCallback(ref long key, ref long input, Empty ctx, Status s) { }
public void CheckpointCompletionCallback(Guid sessionId, long serialNum) { }
}
更多例子
检查点和恢复
FASTER支持基于检查点的恢复。每个新的检查点都会保留(或使之持久)其他用户操作(读取,更新或RMW)。FASTER允许客户端线程跟踪已持久的操作和未使用基于会话的API的操作。
回想一下,每个FASTER线程都会启动一个与唯一的Guid相关联的会话。所有FASTER线程操作(读取,Upsert,RMW)都带有单调序列号。在任何时间点,都可以调用Checkpoint以启动FASTER的异步检查点。在调用之后Checkpoint,(最终)向每个FASTER线程通知一个序列号,这样可以确保直到该序列号之前的所有操作以及在该序列号之后没有任何操作被保留为该检查点的一部分。FASTER线程可以使用此序列号来清除等待执行的操作的任何内存缓冲区。
在恢复期间,线程可以使用继续使用相同的Guid进行会话ContinueSession。该函数返回线程本地序列号,直到恢复该会话哈希为止。从那时起,新线程可以使用此信息来重播所有未提交的操作。
下面一个单线程的简单恢复示例。
public class PersistenceExample
{
private FasterKV<long, long, long, long, Empty, Funcs> fht;
private IDevice log;
public PersistenceExample()
{
log = Devices.CreateLogDevice("C:\\Temp\\hlog.log");
fht = new FasterKV<long, long, long, long, Empty, Funcs>
(1L << 20, new Funcs(), new LogSettings { LogDevice = log });
}
public void Run()
{
IssuePeriodicCheckpoints();
RunSession();
}
public void Continue()
{
fht.Recover();
IssuePeriodicCheckpoints();
ContinueSession();
}
/* Helper Functions */
private void RunSession()
{
Guid guid = fht.StartSession();
System.IO.File.WriteAllText(@"C:\\Temp\\session1.txt", guid.ToString());
long seq = 0; // sequence identifier
long key = 1, input = 10;
while(true)
{
key = (seq % 1L << 20);
fht.RMW(ref key, ref input, Empty.Default, seq);
seq++;
}
// fht.StopSession() - outside infinite loop
}
private void ContinueSession()
{
string guidText = System.IO.File.ReadAllText(@"C:\\Temp\session1.txt");
Guid sessionGuid = Guid.Parse(guidText);
long seq = fht.ContinueSession(sessionGuid); // recovered seq identifier
seq++;
long key = 1, input = 10;
while(true)
{
key = (seq % 1L << 20);
fht.RMW(ref key, ref input, Empty.Default, seq);
seq++;
}
}
private void IssuePeriodicCheckpoints()
{
var t = new Thread(() =>
{
while(true)
{
Thread.Sleep(10000);
fht.StartSession();
fht.TakeCheckpoint(out Guid token);
fht.CompleteCheckpoint(token, true);
fht.StopSession();
}
});
t.Start();
}
}
FASTER支持两种检查点概念:“快照”和“折叠”。前者是将内存中的完整快照复制到一个单独的快照文件中,而后者是自上一个检查点以来更改的增量检查点。折叠有效地将混合日志的只读标记移到尾部,因此所有数据都作为同一混合日志的一部分保留(没有单独的快照文件)。所有后续更新均写入新的混合日志尾部位置,这使Fold-Over具有增量性质。
项目路径:
https://github.com/Microsoft/FASTER/tree/master/cs
微软并发Key-Value存储库FASTER介绍的更多相关文章
- 每秒高达1.6亿次操作的并发键值存储库 FASTER 诞生
FASTER 在过去十年中,云中的数据密集型应用程序和服务有了巨大的增长.数据在各种边设施(例如,设备,浏览器和服务器)上创建,并由云应用程序处理用来获得数据价值或做出决策.应用程序和服务可以处理收集 ...
- 微软开放技术发布开源 Jenkins 插件以将 Windows Azure Blob 服务用的开作存储库
发布于 2014-02-10 作者 陈 忠岳 持续集成 (CI) 的历史源远流长, 其宗旨在于软件团队在敏捷环境中不断将他们的工作整合为持续构建.管理 CI 进程的工具已存在一段时间.过去几年中 ...
- 94、存储库之MongoDB、mysql
本篇导航: 简介 MongoDB基础知识 安装 基本数据类型 CRUD操作 其它 存储库之mysql 一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1.易用性 MongoDB是 ...
- 存储库之MongoDB、mysql
本篇导航: 简介 MongoDB基础知识 安装 基本数据类型 CRUD操作 其它 存储库之mysql 一.简介 MongoDB是一款强大.灵活.且易于扩展的通用型数据库1.易用性 MongoDB是 ...
- android高仿小视频、应用锁、3种存储库、QQ小红点动画、仿支付宝图表等源码
Android精选源码 android模仿支付宝app"记账本"模块源码 android一个超轻量级剪贴板历史记录管理软件源码 android模仿QQ拖动红点消失动画效果源码 展示 ...
- 结合实体框架(代码优先)、工作单元测试、Web API、ASP. net等,以存储库设计模式开发示例项目。NET MVC 5和引导
介绍 这篇文章将帮助你理解在库模式.实体框架.Web API.SQL Server 2012.ASP中的工作单元测试的帮助下设计一个项目.净MVC应用程序.我们正在开发一个图书实体和作者专用的样例图书 ...
- git-secret:在 Git 存储库中加密和存储密钥(上)
当涉及处理机密信息(如密码.令牌.密钥文件等)等,以下问题值得考虑: 安全性十分重要,但高安全性往往伴随着高度的不便. 在团队中,共享某些密钥有时无法避免(因此现在我们需要考虑在多人之间分发和更新密钥 ...
- g4e基础篇#4 了解Git存储库(Repo)
章节目录 前言 1. 基础篇: 为什么要使用版本控制系统 Git 分布式版本控制系统的优势 Git 安装和设置 了解Git存储库(Repo) 起步 1 – 创建分支和保存代码 起步 2 – 了解Git ...
- 2.1、CDH 搭建Hadoop在安装(为Cloudera Manager配置存储库)
步骤1:为Cloudera Manager配置存储库 使用包管理工具安装Cloudera Manager yum 对于RHEL兼容系统, zypper对于SLES,和 apt-get对于Ubuntu. ...
随机推荐
- 彻底关闭Windows10的更新
Windows10的自动更新太恶心,关闭之后总能死灰复燃,更新偶尔占用大量的CPU内存,非常影响使用.而网上大多数都是关闭服务之类的方法,但是关闭之后没过多久又会重新自动启动,如何彻底摆脱wiondo ...
- Spring 事务注解@Transactional
事务管理一般有编程式和声明式两种,编程式是直接在代码中进行编写事物处理过程,而声名式则是通过注解方式或者是在xml文件中进行配置,相对编程式很方便. 而注解方式通过@Transactional 是常见 ...
- 阿里云服务器CentOS6.9安装Tomcat
上篇讲了CentOS6.9安装jdk,这篇来讲Tomcat的安装,本来准备使用yum命令安装的,但是通过 yum search tomcat 发现只有tomcat6,所以就在官网下了一个tomcat8 ...
- 1. SOFAJRaft源码分析— SOFAJRaft启动时做了什么?
我们这次依然用上次的例子CounterServer来进行讲解: 我这里就不贴整个代码了 public static void main(final String[] args) throws IOEx ...
- 【Java基础】让编码不再让你困惑
目录 1. ASCII编码 2. Unicode编码 3. UTF-8编码 4. UTF8.UTF16和UTF32之间的区别 5. GBK.GB2312和GB18030之间的区别 6. Java中的编 ...
- group by 如何合并字符串优化记?
sqlserver 2005及以上版本 表(tb) id value 1 aa 2 cc 3 bb 3 dd 4 aa 4 cc 4 dd ...
- B-微积分-sign(符号)函数
目录 sign(符号)函数 一.sign函数概述 二.python实现sign函数 更新.更全的<机器学习>的更新网站,更有python.go.数据结构与算法.爬虫.人工智能教学等着你:h ...
- 网页布局——grid语法属性详解
grid目前兼容性目前还可以,主流浏览器对它的支持力度很大,ie9,10宣布它未来不久会对它有很好的支持,目前则需要使用过时的语法.我相信不久的将来grid将成为每一个前端工作人员必备的布局技能. 属 ...
- .Net TCP探索(一)——TCP服务端开发(同时监听多个客户端请求)
最近在园子里看了大神写的(面试官,不要再问我三次握手和四次挥手),忍不住写段程序来测试一番. 在网上找了很多例子,大多只实现了TCP点对点通讯,但实际应用中,一个服务器端口往往要监听多 ...
- HeidiSQL、Navicat、mysql命令和source命令导入sql脚本的速度比较
一.四种导入方式的比较 1.heidisql客户端是一条一条插入的,速度最慢,而且很脆弱比较容易崩溃: 2.mysql命令导入380万记录用时1小时13分(属于前台运行的命令,ctrl+c就可以结束) ...