Golang中如何实现一个高效的键值存储服务

Golang中如何实现一个高效的键值存储服务 我正在寻找一个基础的键值对(KEY/VALUE)HTTP前端代码。 如果能看看现有的HTTP服务代码,会对我有很大帮助。

我成功使用过boltdb和leveldb,但我确信还有其他人写过类似的基础软件。 请给我展示一些代码。

3 回复

你是否在考虑像Redis缓存这样的服务?但是用Go语言编写的?

更多关于Golang中如何实现一个高效的键值存储服务的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


我想看一些为键值库提供 HTTP API 的代码。 我之前用 Go 写过一个名为 SquidBlocker 的数据库,它使用了 BoltDB 或 LevelDB。 在我着手开发 V2 版本之前,我正在寻找其他思路。

我自己还没有找到一个为 LevelDB 提供键值 HTTP API 的服务,而这正是我真正想开始着手的方向。

以下是一个基于Go标准库和BoltDB的高效键值存储HTTP服务实现:

package main

import (
    "encoding/json"
    "io"
    "log"
    "net/http"
    "sync"
    "time"

    "github.com/boltdb/bolt"
)

type KeyValueStore struct {
    db *bolt.DB
    mu sync.RWMutex
}

func NewKeyValueStore(path string) (*KeyValueStore, error) {
    db, err := bolt.Open(path, 0600, &bolt.Options{Timeout: 1 * time.Second})
    if err != nil {
        return nil, err
    }
    
    err = db.Update(func(tx *bolt.Tx) error {
        _, err := tx.CreateBucketIfNotExists([]byte("kvstore"))
        return err
    })
    
    return &KeyValueStore{db: db}, err
}

func (kvs *KeyValueStore) Close() error {
    return kvs.db.Close()
}

func (kvs *KeyValueStore) Put(key, value string) error {
    kvs.mu.Lock()
    defer kvs.mu.Unlock()
    
    return kvs.db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("kvstore"))
        return b.Put([]byte(key), []byte(value))
    })
}

func (kvs *KeyValueStore) Get(key string) (string, error) {
    kvs.mu.RLock()
    defer kvs.mu.RUnlock()
    
    var value []byte
    err := kvs.db.View(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("kvstore"))
        v := b.Get([]byte(key))
        if v != nil {
            value = make([]byte, len(v))
            copy(value, v)
        }
        return nil
    })
    
    if err != nil {
        return "", err
    }
    if value == nil {
        return "", nil
    }
    return string(value), nil
}

func (kvs *KeyValueStore) Delete(key string) error {
    kvs.mu.Lock()
    defer kvs.mu.Unlock()
    
    return kvs.db.Update(func(tx *bolt.Tx) error {
        b := tx.Bucket([]byte("kvstore"))
        return b.Delete([]byte(key))
    })
}

type Request struct {
    Key   string `json:"key"`
    Value string `json:"value"`
}

type Response struct {
    Success bool   `json:"success"`
    Value   string `json:"value,omitempty"`
    Error   string `json:"error,omitempty"`
}

func main() {
    kvs, err := NewKeyValueStore("mykvstore.db")
    if err != nil {
        log.Fatal(err)
    }
    defer kvs.Close()

    http.HandleFunc("/get", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var req Request
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        value, err := kvs.Get(req.Key)
        resp := Response{Success: err == nil}
        if err != nil {
            resp.Error = err.Error()
        } else {
            resp.Value = value
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })

    http.HandleFunc("/put", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var req Request
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        err := kvs.Put(req.Key, req.Value)
        resp := Response{Success: err == nil}
        if err != nil {
            resp.Error = err.Error()
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })

    http.HandleFunc("/delete", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var req Request
        if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        err := kvs.Delete(req.Key)
        resp := Response{Success: err == nil}
        if err != nil {
            resp.Error = err.Error()
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(resp)
    })

    http.HandleFunc("/batch", func(w http.ResponseWriter, r *http.Request) {
        if r.Method != http.MethodPost {
            http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
            return
        }

        var requests []Request
        if err := json.NewDecoder(r.Body).Decode(&requests); err != nil {
            http.Error(w, err.Error(), http.StatusBadRequest)
            return
        }

        results := make([]Response, len(requests))
        for i, req := range requests {
            err := kvs.Put(req.Key, req.Value)
            results[i] = Response{
                Success: err == nil,
                Error:   func() string { if err != nil { return err.Error() }; return "" }(),
            }
        }

        w.Header().Set("Content-Type", "application/json")
        json.NewEncoder(w).Encode(results)
    })

    log.Println("Starting key-value store server on :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

这个实现包含以下特性:

  1. BoltDB集成:使用BoltDB作为底层存储引擎,提供ACID事务支持

  2. 线程安全:使用读写锁(sync.RWMutex)确保并发安全

  3. RESTful API

    • POST /get - 获取键值
    • POST /put - 设置键值
    • POST /delete - 删除键值
    • POST /batch - 批量操作
  4. JSON接口:所有请求和响应都使用JSON格式

使用示例:

# 设置键值
curl -X POST http://localhost:8080/put \
  -H "Content-Type: application/json" \
  -d '{"key":"user:1","value":"{\"name\":\"John\",\"age\":30}"}'

# 获取键值
curl -X POST http://localhost:8080/get \
  -H "Content-Type: application/json" \
  -d '{"key":"user:1"}'

# 批量操作
curl -X POST http://localhost:8080/batch \
  -H "Content-Type: application/json" \
  -d '[{"key":"key1","value":"value1"},{"key":"key2","value":"value2"}]'

这个实现提供了基础的键值存储HTTP服务,可以根据需要扩展更多功能,如TTL支持、数据压缩或集群功能。

回到顶部