• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
孙龙 程序员
少时总觉为人易,华年方知立业难
博客园    首页    新随笔    联系   管理    订阅  订阅
go知名第三方包ssdb

因为beego中cache模块中使用了ssdb,所以准备学习下ssdb
(1)ssdb简介
(2)ssdb的基本操作
(3)gossdb怎么使用?

1、ssdb简介
SSDB 是一个 C/C++ 语言开发的高性能 NoSQL 数据库, 支持 KV, list, map(hash), zset(sorted set),qlist(队列) 等数据结构, 用来替代或者与 Redis 配合存储十亿级别列表的数据.
SSDB 是稳定的, 生产环境使用的, 已经在许多互联网公司得到广泛使用, 如奇虎 360, TOPGAME.
特性
替代 Redis 数据库, Redis 的 100 倍容量
LevelDB 网络支持, 使用 C/C++ 开发
Redis API 兼容, 支持 Redis 客户端
适合存储集合数据, 如kv, list, hashtable, zset,hset,qlist...
客户端 API 支持的语言包括: C++, PHP, Python, Java, Go
持久化的队列服务
主从复制, 负载均衡

既然有redis这种NoSQL数据库,为什么需要ssdb?
我在网上得到的结论是Redis是内存型,内存成本太高,SSDB针对这个弱点,使用硬盘存储,使用Google高性能的存储引擎LevelDB。

2、ssdb的基本操作
命令
3、gossdb包怎么使用?
源码,打开源码文件,代码大概在190行左右,不是很多。这个包也不复杂。
1、结构体Client

 
type Client struct {
    sock     *net.TCPConn
    recv_buf bytes.Buffer
}

 相关方法:
1)创建Client
func Connect(ip string, port int) (*Client, error)

func Connect(ip string, port int) (*Client, error) {
    addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", ip, port))
    if err != nil {
        return nil, err
    }
    sock, err := net.DialTCP("tcp", nil, addr)
    if err != nil {
        return nil, err
    }
    var c Client
    c.sock = sock
    return &c, nil
}

2)发送命令到ssdb服务器
func (c *Client) Do(args ...interface{}) ([]string, error)

func (c *Client) Do(args ...interface{}) ([]string, error) {
    err := c.send(args)
    if err != nil {
        return nil, err
    }
    resp, err := c.recv()
    return resp, err
}


3)设置值
func (c *Client) Set(key string, val string) (interface{}, error)

func (c *Client) Set(key string, val string) (interface{}, error) {
    resp, err := c.Do("set", key, val)
    if err != nil {
        return nil, err
    }
    if len(resp) == 2 && resp[0] == "ok" {
        return true, nil
    }
    return nil, fmt.Errorf("bad response")
}

4)获取值

func (c *Client) Get(key string) (interface{}, error) {
    resp, err := c.Do("get", key)
    if err != nil {
        return nil, err
    }
    if len(resp) == 2 && resp[0] == "ok" {
        return resp[1], nil
    }
    if resp[0] == "not_found" {
        return nil, nil
    }
    return nil, fmt.Errorf("bad response")
}

5)func (c *Client) Del(key string) (interface{}, error)
删除值

func (c *Client) Del(key string) (interface{}, error) {
    resp, err := c.Do("del", key)
    if err != nil {
        return nil, err
    }

    //response looks like this: [ok 1]
    if len(resp) > 0 && resp[0] == "ok" {
        return true, nil
    }
    return nil, fmt.Errorf("bad response:resp:%v:", resp)
}

6)func (c *Client) Send(args ...interface{}) error
发送命令到ssdb服务器

func (c *Client) Send(args ...interface{}) error {
    return c.send(args);
}

func (c *Client) send(args []interface{}) error {
    var buf bytes.Buffer
    for _, arg := range args {
        var s string
        switch arg := arg.(type) {
        case string:
            s = arg
        case []byte:
            s = string(arg)
        case []string:
            for _, s := range arg {
                buf.WriteString(fmt.Sprintf("%d", len(s)))
                buf.WriteByte('\n')
                buf.WriteString(s)
                buf.WriteByte('\n')
            }
            continue
        case int:
            s = fmt.Sprintf("%d", arg)
        case int64:
            s = fmt.Sprintf("%d", arg)
        case float64:
            s = fmt.Sprintf("%f", arg)
        case bool:
            if arg {
                s = "1"
            } else {
                s = "0"
            }
        case nil:
            s = ""
        default:
            return fmt.Errorf("bad arguments")
        }
        buf.WriteString(fmt.Sprintf("%d", len(s)))
        buf.WriteByte('\n')
        buf.WriteString(s)
        buf.WriteByte('\n')
    }
    buf.WriteByte('\n')
    _, err := c.sock.Write(buf.Bytes())
    return err
}

 

7)func (c *Client) Recv() ([]string, error)
接收ssdb的信息

func (c *Client) Recv() ([]string, error) {
    return c.recv();
}

func (c *Client) recv() ([]string, error) {
    var tmp [8192]byte
    for {
        resp := c.parse()
        if resp == nil || len(resp) > 0 {
            return resp, nil
        }
        n, err := c.sock.Read(tmp[0:])
        if err != nil {
            return nil, err
        }
        c.recv_buf.Write(tmp[0:n])
    }
}

8)func (c *Client) Close() error
关闭连接

func (c *Client) Close() error {
    return c.sock.Close()
}

解析命令

func (c *Client) parse() []string {
    resp := []string{}
    buf := c.recv_buf.Bytes()
    var idx, offset int
    idx = 0
    offset = 0

    for {
        idx = bytes.IndexByte(buf[offset:], '\n')
        if idx == -1 {
            break
        }
        p := buf[offset : offset+idx]
        offset += idx + 1
        //fmt.Printf("> [%s]\n", p);
        if len(p) == 0 || (len(p) == 1 && p[0] == '\r') {
            if len(resp) == 0 {
                continue
            } else {
                var new_buf bytes.Buffer
                new_buf.Write(buf[offset:])
                c.recv_buf = new_buf
                return resp
            }
        }

        size, err := strconv.Atoi(string(p))
        if err != nil || size < 0 {
            return nil
        }
        if offset+size >= c.recv_buf.Len() {
            break
        }

        v := buf[offset : offset+size]
        resp = append(resp, string(v))
        offset += size + 1
    }

    //fmt.Printf("buf.size: %d packet not ready...\n", len(buf))
    return []string{}
}
参考链接:
1、ssdb学习:
https://www.w3cschool.cn/ssdb/
http://ssdb.io/docs/zh_cn/commands/index.html
2、gossdb源码:
https://github.com/ssdb/gossdb



 
 
 
 
 

 
 
 
 

本文来自博客园,作者:孙龙-程序员,转载请注明原文链接:https://www.cnblogs.com/sunlong88/p/17711370.html

posted on 2023-09-18 11:06  孙龙-程序员  阅读(201)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3