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") } }
一些业务中无效key数量比较多,需要脚本批量删除,利用MULTI批量删除
批量删除
conn, err := redis.Dial("tcp", "127.0.0.1:6379") if err != nil { panic(err) } defer conn.Close() conn.Do("SET", "app1", "test1") conn.Do("SET", "app2", "test2") val, err := redis.Strings(conn.Do("KEYS", "app*")) fmt.Println(val, err) conn.Send("MULTI") for i, _ := range val { conn.Send("DEL", val[i]) } fmt.Println(conn.Do("EXEC"))
封装成函数
func DeleteRedis(arr []string) (res string, err error) { rcc := RedisClient.Get() rcc.Send("MULTI") for _, v := range arr { if len(v) == 0 { continue } arr := strings.Fields(v) rcc.Send("DEL", arr[1]) res += arr[1] + " " } _, err = rcc .Do("EXEC") rcc.Close() return }
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,用户可以通过执行不同的操作增加或减少计数器的值,比如在游戏中的记分器就可能用到这些命令。
- PHP学习笔记之三:数据库基本操作
- Redis数据库及其基本操作
- 【VC++ 中使用ADO操作数据库学习笔记】_ConnectionPtr指针的基本用法
- Django 学习笔记(七)数据库基本操作(增查改删)
- MySQL 5.6学习笔记(数据库基本操作,查看和修改表的存储引擎)
- 【Laravel5.3 笔记整理九】Laravel数据库的基本操作
- MYSQL 学习笔记 之 数据库基本操作2
- MYSQL数据库 - 学习笔记1 - 数据库基本操作
- Django 学习笔记(七)数据库基本操作(增查改删)
- MySQL 学习基础笔记-MySQL基本数据库的操作
- MySql笔记-数据库基本操作
- android开发笔记之db数据库基本操作
- java 操作redis 数据库一:基本操作
- mybatis笔记-1-数据库的基本操作
- Django 学习笔记(七)数据库基本操作(增查改删)
- (二)Redis 笔记——发布&订阅、事务、数据库操作
- PHP学习笔记之三 数据库基本操作
- Django 学习笔记(七)数据库基本操作(增查改删)
- 学习笔记_JDBC_1_Demo1_连接数据库的基本操作和步骤