golang redis数据库基本操作笔记

一、基础知识

Redis是一个开源的、使用C语言编写的、支持网络交互的、可基于内存也可持久化的Key-Value数据库。

Redis 优势

    性能极高 – Redis能读的速度是110000次/s,写的速度是81000次/s 。

    丰富的数据类型 – Redis支持二进制案例的 Strings, Lists, Hashes, Sets 及 Ordered Sets 数据类型操作。

    原子 – Redis的所有操作都是原子性的,同时Redis还支持对几个操作全并后的原子性执行。

    丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等等特性。

选用Redis场景:

    解决应用服务器的cpu和内存压力

    减少io的读操作,减轻io的压力

    关系型数据库的扩展性不强,难以改变表结构

    nosql数据库没有关联关系,数据结构简单,拓展表比较容易

    nosql读取速度快,对较大数据处理快

    数据高并发的读写

    海量数据的读写

    对扩展性要求高的数据

二、基本操作:

在开发过程中我们使用到了开源库redis如下

github地址

https://github.com/garyburd/redigo

文档地址:

http://godoc.org/github.com/garyburd/redigo/redis

1、数据库的连接

func connRedis() (c redis.Conn, err error) {

    db, err := redis.Dial("tcp", "127.0.0.1:6379")

    if err != nil {

        fmt.Println("Connect to redis fail!", err)

        return

    }

    return db, err

}

采用连接池的方式:

var RedisClient *redis.Pool

func ConnectRedis() {

    host := beego.AppConfig.DefaultString("redis.host", "127.0.0.1:6379")//通过beego配置文件获取

    pwd := beego.AppConfig.DefaultString("redis.psw", "")

    MaxIdle := beego.AppConfig.DefaultInt("redis.MaxIdle", 100)

    MaxActive := beego.AppConfig.DefaultInt("redis.MaxActive", 1024)

    RedisClient = &redis.Pool{

    // 从配置文件获取maxidle以及maxactive,取不到则用后面的默认值

        MaxIdle:    MaxIdle,

        MaxActive:  MaxActive,

        IdleTimeout: 180 * time.Second,

        Dial: func() (redis.Conn, error) {

            c, err := redis.Dial("tcp", host, redis.DialPassword(pwd))

            if err != nil {

                return nil, err

            }

        return c, nil

        },

    }

}

2、写入

func saveToRedis(c redis.Conn) {

_, err := c.Do("SET", "name", "TigerwolfC", "EX", "60")

if err != nil { 

       fmt.Println("redis set failed:", err) 

  } else {   

       fmt.Println("save success") 

  }

}

批量写入

_, err := c.Do("MSET", "name", "TigerwolfC", "SEX", "F", "EX", "60") 

if err != nil {   

    fmt.Println("redis set failed:", err) 

} else {   

    fmt.Println("save success") 

}

tips:EX是这个值的过期时间

连接池方式写入

type UserInfo struct {

Name        string        //邮箱号,如"455*****"

Displayname string  //用户名,如“张三”

Mail        string          //邮箱,如“455*****@qq.com.cn”

}

func saveToRedis(userInfos map[int]models.UserInfo) error {

    rcc := RedisClient.Get()

    _, err := rcc.Do("SELECT", 1)

    if err != nil {

        return err

    }

    for _, v := range userInfos {

        _, err = rcc.Do("HMSET", v.Name, "mail", v.Mail, "displayName", v.Displayname)

        if err != nil {

            return err

        }

    }

    return nil

}

3、读取

func readFromRedis(c redis.Conn) { 

    username, err := redis.String(c.Do("GET", "name")) 

    if err != nil {   

        fmt.Println("redis get failed:", err) 

    } else {   

        fmt.Printf("Get mykey: %v \n", username) 

    }

}

批量读取

func readFromRedis(c redis.Conn) { 

    username, err := redis.Strings(c.Do("MGET", "SEX", "name")) 

    if err != nil {   

        fmt.Println("redis get failed:", err) 

    } else {   

        fmt.Printf("Get mykey: %v \n", username) 

    }

}

4、删除

func delFromRedis(c redis.Conn) {

    _, err := c.Do("DEL", "name", "SEX") 

    if err != nil {   

        fmt.Println("redis delete failed:", err)

    } else {   

        fmt.Println("delete success") 

    }

}

5、设置keys 过期时间

在写入的时候如果设置了EX的时间,则当前的key过期时间为设置时间,不设置则当前的key永久有效

6、检查是否存在key值

exists, err := redis.Bool(conn.Do("EXISTS", "test-Key"))

if err != nil {

    fmt.Println("illegal exception")

}

fmt.Printf("exists or not: %v \n", exists)

7、读写json到redis

写json

func saveJsonDataToRedis(c redis.Conn) { 

    imap := map[string]string{"name": "TigerwolfC", "phone": "156**********"} 

    value, _ := json.Marshal(imap) 

    n, err := c.Do("SETNX", "chen_peggy", value)

    if err != nil {   

        fmt.Println(err) 

    }

    if n == int64(1) {   

        fmt.Println("success") 

  }

}

读json

func readJsonFromRedis(c redis.Conn) { 

    var imapGet map[string]string 

    valueGet, err := redis.Bytes(c.Do("GET", "chen_peggy")) 

    if err != nil {   

        fmt.Println(err) 

    } 

    errShal := json.Unmarshal(valueGet, &imapGet) 

    if errShal != nil {   

        fmt.Println(err) 

    } 

    fmt.Println(imapGet["name"]) 

    fmt.Println(imapGet["phone"])

}

8、列表操作,存入一组数据

存列表

func saveListToRedis(c redis.Conn) { 

    _, err := c.Do("lpush", "username", "chen_peggy") 

    if err != nil {   

        fmt.Println("redis set failed:", err) 

    } 

    _, err = c.Do("lpush", "username", "lisi") 

        if err != nil {   

        fmt.Println("redis set failed:", err) 

    }

    _, err = c.Do("lpush", "username", "TigerwolfC") 

    if err != nil {   

        fmt.Println("redis set failed:", err) 

    }

}

读列表

func readListFromRedis(c redis.Conn) { 

     values, _ := redis.Values(c.Do("lrange", "username", "0", "2")) 

    fmt.Printf("count%d", len(values)) 

    for _, v := range values { 

        fmt.Println(string(v.([]byte))) 

       }

  }

9、自增实现计数

redis中的INCR命令每次对key记录增加1,将 key 中储存的数字值增一。

如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。

如果值包含错误的类型,或字符串类型的值不能表示为数字,那么返回一个错误。

本操作的值限制在 64 位(bit)有符号数字表示之内

127.0.0.1:6379> incr  TigerwolfC

<internet> 1

127.0.0.1:6379> incr  TigerwolfC

<internet> 2

127.0.0.1:6379> incr  TigerwolfC

<internet> 3

127.0.0.1:6379>

例子

package main

import (

    "log"

    "github.com/garyburd/redigo/redis"

)

func main() {

    server := "127.0.0.1:6379"

    option := redis.DialPassword("******")

    c, err := redis.Dial("tcp", server, option)

    if err != nil {

        log.Println("connect server failed:", err)

        return

    }

    defer c.Close()

    v, err := redis.Int64(c.Do("INCR", "TigerwolfC"))

    if err != nil {

        log.Println("INCR failed:", err)

        return

    }

    log.Println("value:", v)

}

output:

2018/10/26 12:30:56 value:4

计数器是 Redis 的原子性自增操作可实现的最直观的模式了,它的想法相当简单:每当某个操作发生时,向 Redis 发送一个 INCR 命令。

比如在一个 web 应用程序中,如果想知道用户在一年中每天的点击量,那么只要将用户 ID 以及相关的日期信息作为键,并在每次用户点击页面时,执行一次自增操作即可。

比如用户名是 TigerwolfC,点击时间是 2018 年 10 月 22 日,那么执行命令 INCR TigerwolfC::2018.10.22 。

可以用以下几种方式扩展这个简单的模式:

    可以通过组合使用 INCR 和 EXPIRE ,来达到只在规定的生存时间内进行计数(counting)的目的。

    客户端可以通过使用 GETSET 命令原子性地获取计数器的当前值并将计数器清零,更多信息请参考 GETSET 命令。

    使用其他自增/自减操作,比如 DECR 和 INCRBY,用户可以通过执行不同的操作增加或减少计数器的值,比如在游戏中的记分器就可能用到这些命令。

持续更新中

如有不对欢迎指正,相互学习,共同进步。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,546评论 6 507
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,224评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,911评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,737评论 1 294
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,753评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,598评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,338评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,249评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,696评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,888评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,013评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,731评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,348评论 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,929评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,048评论 1 270
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,203评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,960评论 2 355

推荐阅读更多精彩内容