”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 实现具有 TTL 和磁盘持久性的高性能缓存

实现具有 TTL 和磁盘持久性的高性能缓存

发布于2024-08-15
浏览:851

Go High-Performance Cache with TTL and Disk Persistence

一、简介

加速您的 Golang 项目,无需每次开始新项目时设置数据库的麻烦。厌倦了从头开始配置数据库?只是为了面对新的问题吗?不用再看了 在这篇博客中,我们将研究 Golang 缓存库,支持 TTL磁盘持久性哈希数据类型

GoSwift.

2.前提条件

  • Golang基础知识
  • 了解典型缓存的工作原理

三、特点

  1. 设置和获取命令
  2. 更新命令
  3. 删除命令
  4. 存在命令
  5. 支持 TTL
  6. 支持磁盘保存(快照)
  7. 支持哈希数据类型(Hset、Hget、HgetAll、HMset)
  8. 安全锁定

设置和获取命令

import (
    "fmt"
    "github.com/leoantony72/goswift"
)

func main(){
    cache := goswift.NewCache()

    // Value 0 indicates no expiry
    cache.Set("key", "value", 0)

    val, err := cache.Get("key")
    if err !=nil{
        fmt.Println(err)
        return
    }
    fmt.Println("key", val)
}

更新命令

// Update value
// @Update(key string, val interface{}) error
err = cache.Update("key","value2")
if err != nil{
    fmt.Println(err)
    return
}

Del 命令 && 存在命令

// Delete command
// @Del(key string)
cache.Del("key")

// Exist command
// @Exists(key string) bool
value = cache.Exists("key")
fmt.Println(value) // returns false

支持TTL

// Set Value with Expiry
// @Set(key string, val interface{}, exp int)
// Here expiry is set to 1sec
cache.Set("key","value",1000)

// Hset command
// @Hset(key, field string, value interface{}, exp int)
// in this case the "key" expires in 1sec
cache.Hset("key","name","value",1000)
cache.Hset("key","age",18,1000)

支持Hash数据类型(Hset、Hget、HgetAll、HMset)

// Hset command
// @Hset(key, field string, value interface{}, exp int)
// in this case the "key" expires in 1sec
cache.Hset("key","name","value",1000)
cache.Hset("key","age",18,1000)


// HMset command
// @HMset(key string, d interface{}, exp int) error
// Set a Hash by passing a Struct/Map
// ---by passing a struct---
type Person struct{
    Name  string
    Age   int
    Place string
}

person1 := &Person{Name:"bob",Age:18,Place:"NYC"}
err = cache.HMset("key",person1)
if err != nil{
    fmt.Println(err)
    return
}

// ---by passing a map---
person2 := map[string]interface{Name:"john",Age:18,Place:"NYC"}
err = cache.HMset("key",person2)
if err != nil{
    fmt.Println(err)
    return
}


// Hget command
// @HGet(key, field string) (interface{}, error)
// get individual fields in Hash
data,err := cache.HGet("key","field")
if err != nil{
    fmt.Println(err)
    return
}
fmt.Println(data)

// HgetAll command
// @HGetAll(key string) (map[string]interface{}, error)
// gets all the fields with value in a hash key
// retuns a map[string]interface{}
data,err = cache.HGetAll("key")
if err != nil{
    fmt.Println(err)
    return
}

快照

opt := goswift.CacheOptions{
        EnableSnapshots:  true,
        SnapshotInterval: time.Second*5,
    }
c := goswift.NewCache(opt)

这将每 5 秒拍摄一次数据快照并将其保存到 Snapshot.data 文件中。默认情况下,快照被禁用,如果未提供 SnapshotInterval,则默认值为 5 秒。

注意:如果 EnableSnapshot 为 false,则不会导入文件中保存的数据

错误处理

const (
    ErrKeyNotFound   = "key does not Exists"
    ErrFieldNotFound = "field does not Exists"
    ErrNotHashvalue  = "not a Hash value/table"
    ErrHmsetDataType = "invalid data type, Expected Struct/Map"
)

这些是编写代码时可能出现的常见错误。这些变量为您提供了一种清晰、简单的错误比较方法来确定错误。

data,err := cache.Get("key")
if err != nil {
    if err.Error() == goswift.ErrKeyNotFound {
        //do something
}
}    

缓存过期的内部工作原理

每 3 秒就会调用 **sweaper ** 函数来清除哈希表中的过期值。我们维护一个指向哈希图的最小堆。顶部元素将是具有最小 TTL 的键。我们遍历树直到 TTL 大于当前时间。

概括

我不会建议您在生产中使用它!!,但请随意在您的小型副项目中使用它。请尝试一下,如果遇到错误,请在 GitHub 存储库上提出问题。

电子邮件:[email protected]
Github:https://github.com/leoantony72
仓库:https://github.com/leoantony72/goswift

版本声明 本文转载于:https://dev.to/leoantony72/go-high-performance-cache-with-ttl-and-disk-persistence-4a4m?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何避免Go语言切片时的内存泄漏?
    如何避免Go语言切片时的内存泄漏?
    ,a [j:] ...虽然通常有效,但如果使用指针,可能会导致内存泄漏。这是因为原始的备份阵列保持完整,这意味着新切片外部指针引用的任何对象仍然可能占据内存。 copy(a [i:] 对于k,n:= len(a)-j i,len(a); k
    编程 发布于2025-07-24
  • Java字符串非空且非null的有效检查方法
    Java字符串非空且非null的有效检查方法
    检查字符串是否不是null而不是空的 if(str!= null && str.isementy())二手: if(str!= null && str.length()== 0) option 3:trim()。isement(Isement() trim whitespace whitesp...
    编程 发布于2025-07-24
  • 如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求和假用户代理绕过网站块?
    如何使用Python的请求模拟浏览器行为,以及伪造的用户代理提供了一个用户 - 代理标头一个有效方法是提供有效的用户式header,以提供有效的用户 - 设置,该标题可以通过browser和Acterner Systems the equestersystermery和操作系统。通过模仿像Chro...
    编程 发布于2025-07-24
  • C++20 Consteval函数中模板参数能否依赖于函数参数?
    C++20 Consteval函数中模板参数能否依赖于函数参数?
    [ consteval函数和模板参数依赖于函数参数在C 17中,模板参数不能依赖一个函数参数,因为编译器仍然需要对非contexexpr futcoriations contim at contexpr function进行评估。 compile time。 C 20引入恒定函数,必须在编译时进行...
    编程 发布于2025-07-24
  • 如何使用PHP将斑点(图像)正确插入MySQL?
    如何使用PHP将斑点(图像)正确插入MySQL?
    essue VALUES('$this->image_id','file_get_contents($tmp_image)')";This code builds a string in PHP, but the function call ...
    编程 发布于2025-07-24
  • 如何在Chrome中居中选择框文本?
    如何在Chrome中居中选择框文本?
    选择框的文本对齐:局部chrome-inly-ly-ly-lyly solument 您可能希望将文本中心集中在选择框中,以获取优化的原因或提高可访问性。但是,在CSS中的选择元素中手动添加一个文本 - 对属性可能无法正常工作。初始尝试 state)</option> < op...
    编程 发布于2025-07-24
  • CSS可以根据任何属性值来定位HTML元素吗?
    CSS可以根据任何属性值来定位HTML元素吗?
    靶向html元素,在CSS 中使用任何属性值,在CSS中,可以基于特定属性(如下所示)基于特定属性的基于特定属性的emants目标元素: 字体家庭:康斯拉斯(Consolas); } 但是,出现一个常见的问题:元素可以根据任何属性值而定位吗?本文探讨了此主题。的目标元素有任何任何属性值,属...
    编程 发布于2025-07-24
  • 左连接为何在右表WHERE子句过滤时像内连接?
    左连接为何在右表WHERE子句过滤时像内连接?
    左JOIN CONUNDRUM:WITCHING小时在数据库Wizard的领域中变成内在的加入很有趣,当将c.foobar条件放置在上面的Where子句中时,据说左联接似乎会转换为内部连接。仅当满足A.Foo和C.Foobar标准时,才会返回结果。为什么要变形?关键在于其中的子句。当左联接的右侧值...
    编程 发布于2025-07-24
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-07-24
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-07-24
  • 在GO中构造SQL查询时,如何安全地加入文本和值?
    在GO中构造SQL查询时,如何安全地加入文本和值?
    在go中构造文本sql查询时,在go sql queries 中,在使用conting and contement和contement consem per时,尤其是在使用integer per当per当per时,per per per当per. 在GO中实现这一目标的惯用方法是使用fmt.spr...
    编程 发布于2025-07-24
  • 在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在程序退出之前,我需要在C ++中明确删除堆的堆分配吗?
    在C中的显式删除 在C中的动态内存分配时,开发人员通常会想知道是否需要手动调用“ delete”操作员在heap-exprogal exit exit上。本文深入研究了这个主题。 在C主函数中,使用了动态分配变量(HEAP内存)的指针。当应用程序退出时,此内存是否会自动发布?通常,是。但是,即使在这...
    编程 发布于2025-07-24
  • C++中如何将独占指针作为函数或构造函数参数传递?
    C++中如何将独占指针作为函数或构造函数参数传递?
    在构造函数和函数中将唯一的指数管理为参数 unique pointers( unique_ptr [2启示。通过值: base(std :: simelor_ptr n) :next(std :: move(n)){} 此方法将唯一指针的所有权转移到函数/对象。指针的内容被移至功能中,在操作...
    编程 发布于2025-07-24
  • 如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    如何修复\“常规错误:2006 MySQL Server在插入数据时已经消失\”?
    How to Resolve "General error: 2006 MySQL server has gone away" While Inserting RecordsIntroduction:Inserting data into a MySQL database can...
    编程 发布于2025-07-24

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3