.Net Faster介绍

Github地址:https://github.com/microsoft/FASTER
官网网址:https://microsoft.github.io/FASTER/
官方文档地址:https://microsoft.github.io/FASTER/docs/quick-start-guide/

1.介绍

Faster 项目提供了两个工件

  • Faster KV [一个并发键值存储 + 缓存(在 C# 和 C++ 中提供),C# 中的 FasterKV 键值存储和缓存适用于 .NET Framework 和 .NET core,并且可以在单线程和高并发设置中使用。Faster KV 可用作传统并发数据结构(例如 .NET ConcurrentDictionary)的高性能替代品,并且还支持大于内存的数据。]
  • Faster Log[C# 中的高性能并发持久可恢复日志、迭代器和随机读取器库。它支持非常频繁的低延迟提交操作,并且可以快速使磁盘带宽饱和。]
    本文介绍的是Faster KV
    Java中也有类似的高性能的内存缓存-Caffeine

2.测试

1.新建项目[略]
2.安装依赖
dotnet add package Microsoft.FASTER.Core --version 2.5.14
3.使用
// See https://aka.ms/new-console-template for more information

using FASTER.core;

InMemorySample();
DiskSample();
Console.WriteLine("Press <ENTER> to end");
Console.ReadLine();

static void InMemorySample()
{
    Console.WriteLine("In-Memory Sample:\n");
    
    // 数据存储在“d:/coreqi”中
    //using var settings = new FasterKVSettings<long, string>("d:/coreqi");
    // 若传递控制,则缓存数据则纯粹的保存在内存中
    using var settings = new FasterKVSettings<long, long>(null);
    
    using var store = new FasterKV<long, long>(settings);

    // 创建一个回调函数
    // 可以通过扩展this或FunctionsBase来编写自己的。
    var funcs = new SimpleFunctions<long, long>((a, b) => a + b);

    // 对faster的每个逻辑调用序列都与一个faster会话相关联。
    // 单个会话内不允许并发
    using var session = store.NewSession(funcs);

    long key = 1, value = 1, output = 0;
    // 将值盲目更新到存储中(不检查先前的值)
    session.Upsert(ref key, ref value);

    // 从内存读取并同步返回
    var status = session.Read(ref key, ref output);
    if (status.Found && output == value)
    {
        Console.WriteLine("(1) Success!");
    }
    else
    {
        Console.WriteLine("(1) Error!");
    }
    
    /// 删除
    session.Delete(ref key);

    status = session.Read(ref key, ref output);
    if (status.Found)
    {
        Console.WriteLine("(2) Error!"); 
    }
    else
    {
        Console.WriteLine("(2) Success!"); 
    }
    
    // 执行两次读取-修改-写入(求和),验证结果
    key = 2;
    long input1 = 25, input2 = 27;

    session.RMW(ref key, ref input1);
    session.RMW(ref key, ref input2);

    status = session.Read(ref key, ref output);

    if (status.Found && output == input1 + input2)
    {
        Console.WriteLine("(3) Success!");
    }
    else
    {
        Console.WriteLine("(3) Error!");
    }



    // 使用RMW和自定义函数执行TryAdd
    using var tryAddSession = store.NewSession(new TryAddFunctions<long, long>());
    key = 3; input1 = 30; input2 = 31;

    // 首次尝试添加-成功;状态应为NotFound(不存在)
    status = tryAddSession.RMW(ref key, ref input1);

    // 第二次TryAdd-失败;状态应为“已找到”(已存在)
    var status2 = tryAddSession.RMW(ref key, ref input2);

    // 读取,结果应为input1(第一个TryAdd)
    var status3 = session.Read(ref key, ref output);

    if (status.NotFound && status2.Found && status3.Found && output == input1)
    {
        Console.WriteLine("(4) Success!");
    }
    else
    {
        Console.WriteLine("(4) Error!");
    }
}

static void DiskSample()
{
    Console.WriteLine("\nDisk Sample:\n");

    long key = 1, value = 1, output = 0;

    // 根据指定的基本目录路径创建FasterKV配置。
    using var config = new FasterKVSettings<long, long>("./database") { TryRecoverLatest = true };
    Console.WriteLine($"FasterKV config:\n{config}\n");

    // 使用指定的配置创建存储
    using var store = new FasterKV<long, long>(config);
    
    var funcs = new SimpleFunctions<long, long>((a, b) => a + b);
    using var session = store.NewSession(funcs);

    if (store.RecoveredVersion == 1) // 没有恢复
    {
        Console.WriteLine("Clean start; upserting key-value pair");

        // // 将值盲目更新到存储中(不检查先前的值)
        session.Upsert(ref key, ref value);

        // 获取检查点,以便持久化数据以进行恢复
        Console.WriteLine("Taking full checkpoint");
        store.TryInitiateFullCheckpoint(out _, CheckpointType.Snapshot);
        store.CompleteCheckpointAsync().AsTask().GetAwaiter().GetResult();
    }
    else
    {
        Console.WriteLine($"Recovered store to version {store.RecoveredVersion}");
    }

    // 读取从内存返回并同步返回
    var status = session.Read(ref key, ref output);
    if (status.Found && output == value)
    {
        Console.WriteLine("(1) Success!");
    }
    else
    {
        Console.WriteLine("(1) Error!");
    }
    
        

    // 强制将记录刷新到磁盘并从内存中逐出,以便从磁盘进行下一次读取
    store.Log.FlushAndEvict(true);

    // 从磁盘读取将返回PENDING状态,结果可通过异步IFunctions回调获得
    // 或通过在此线程上CompletePendingWithOutputs,如下所示
    status = session.Read(ref key, ref output);
    if (status.IsPending)
    {
        session.CompletePendingWithOutputs(out var iter, true);
        while (iter.Next())
        {
            if (iter.Current.Status.Found && iter.Current.Output == value)
            {
                Console.WriteLine("(2) Success!"); 
            }
            else
            {
                Console.WriteLine("(2) Error!");
            }
        }
        iter.Dispose();
    }
    else
    {
        Console.WriteLine("(2) Error!");
    }
    
    /// 删除密key,读取以验证删除
    session.Delete(ref key);

    status = session.Read(ref key, ref output);
    if (status.Found)
    {
        Console.WriteLine("(3) Error!");
    }
    else
    {
        Console.WriteLine("(3) Success!"); 
    }
    

    // 执行两次读取-修改-写入(求和),验证结果
    key = 2;
    long input1 = 25, input2 = 27;

    session.RMW(ref key, ref input1);
    session.RMW(ref key, ref input2);

    status = session.Read(ref key, ref output);

    if (status.Found && output == input1 + input2)
    {
        Console.WriteLine("(4) Success!");
    }
    else
    {
        Console.WriteLine("(4) Error!");
    }
    
    // 使用RMW和自定义函数执行TryAdd
    using var tryAddSession = store.NewSession(new TryAddFunctions<long, long>());
    key = 3; input1 = 30; input2 = 31;

    // 首次尝试添加-成功;状态应为NOTFOUND(不存在)
    status = tryAddSession.RMW(ref key, ref input1);

    // 第二次TryAdd-失败;状态应为OK(已存在)
    var status2 = tryAddSession.RMW(ref key, ref input2);

    // 读取,结果应为input1(第一个TryAdd)
    var status3 = session.Read(ref key, ref output);

    if (!status.Found && status2.Found && status3.Found && output == input1)
    {
        Console.WriteLine("(5) Success!"); 
    }
    else
    {
        Console.WriteLine("(5) Error!");
    }
}
posted @ 2023-07-10 11:00  SpringCore  阅读(297)  评论(0编辑  收藏  举报