Go Redis
Go RedisGo语言连接Redis库,常用的库 redisgo 和 go-redishttps://github.com/gomodule/redigohttps://github.com/go-redis/redis新项目更建议直接使用go-redis,它对集群和哨兵模式支持更好gormhttp://gorm.book.jasperxu.com/crud.html#credigo 基本使用#
Go Redis
Go语言连接Redis库,常用的库 redisgo
和 go-redis
https://github.com/gomodule/redigo
https://github.com/go-redis/redis
新项目更建议直接使用go-redis,它对集群和哨兵模式支持更好
gorm
http://gorm.book.jasperxu.com/crud.html#c
redigo 基本使用
# 安装redigo
go get github.com/gomodule/redigo/redis
连接redis
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
conn,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil{
fmt.Println("connect redis error:",err.Error())
return
}
fmt.Println("connect redis success ...")
defer conn.Close()
}
redigo 操作
conn.Do(redis命令),它的命令与redis命令行一致,只要知道redis如何操作,填入Do中即可。
比如
redis> SET name “sun”
go> conn.Do(“SET”, “name”, “sun”)
获取到的值,使用redis.String()
转换一下,如果是其他类型,也使用redis.StringMap
redis.Int64
等
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
conn,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil{
fmt.Println("connect redis error:",err.Error())
return
}
fmt.Println("connect redis success ...")
defer conn.Close()
_, err = conn.Do("SET", "name", "sun")
if err != nil{
fmt.Println("redis set error",err.Error())
return
}
name,err := redis.String(conn.Do("GET", "name"))
if err != nil{
fmt.Println("redis get error",err.Error())
return
} else {
fmt.Println("redis get name",name)
}
}
pipeline
管道批量操作
conn.Send(command1)
conn.Send(command1)
conn.Send(command1)
conn.Flush()
res1,err := conn.Receive()
res2,err := conn.Receive()
res3,err := conn.Receive()
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
conn,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil{
fmt.Println("connect redis error:",err.Error())
return
}
fmt.Println("connect redis success ...")
defer conn.Close()
_, err = conn.Do("SET", "name", "sun")
if err != nil{
fmt.Println("redis set error",err.Error())
return
}
conn.Send("HSET","user","name","sun","age","30")
conn.Send("HSET","user","sex","female")
conn.Send("HGET","user",'age')
conn.Flush()
res1,err := conn.Receive()
fmt.Printf("Receive res:%v\n",res1)
res2,err := conn.Receive()
fmt.Printf("Receive res:%v\n",res2)
res3,err := conn.Receive()
fmt.Printf("Receive res:%v\n",res3)
}
如果检查命令没有问题,可能是redis版本过低,请升级版本。
ERR wrong number of arguments for 'hset' command
发布/订阅模式
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
"time"
)
// 订阅,接收消息
func Subscribe() {
// 连接redis
conn,err := redis.Dial("tcp","127.0.0.1:6379")
if err != nil{
fmt.Println("connect redis error:",err.Error())
return
}
defer conn.Close()
psc := redis.PubSubConn{conn}
psc.Subscribe("channel001") //订阅channel001频道
for {
switch v:=psc.Receive().(type) {
case redis.Message:
msg := string(v.Data)
fmt.Println("redis.message",v.Channel,msg)
case redis.Subscription:
fmt.Println("redis.Subscription",v.Channel,v.Kind,v.Count)
case error:
fmt.Println(v)
return
}
}
}
// 发布者,发送消息
func Push(message string){
conn,_ := redis.Dial("tcp","127.0.0.1:6379")
defer conn.Close()
_,err := conn.Do("PUBLISH","channel001",message)
if err != nil {
fmt.Println("push err",err.Error())
return
}
}
func main() {
go Subscribe()
time.Sleep(time.Second * 2) // 这里是防止订阅者启动比发布者慢,启动后已经没有push发布了。
go Push("this is a message,one .")
go Push("this is a message,two .")
time.Sleep(time.Second * 3 )
}
事务操作
MULTI 开启事务
EXEC 执行事务
DISCARD 取消事务
WATCH 监控事务中的变化,一旦有变化则取消事务
c.Send("MULTI") // 开启事务
c.Send("INCR", "foo")
c.Send("INCR", "bar")
r, err := c.Do("EXEC") // 执行事务
补充:
https://blog.csdn.net/sxj6977380/article/details/80794256
事务开启和提交,事务开始和取消,提交后的事务没有取消的操作。
事务提交后失败的情况有2种,语法检测没通过,则会直接取消
语法检测通过,但是中间过程报错,比如字符串的key,用hash的操作,那么后面的的还会正常执行
watch 监听某个值,在开启事务之前,提交/取消后,这个监听也消失了。
使用连接池
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
"time"
)
var Pool redis.Pool
func init() {
Pool = redis.Pool {
MaxIdle: 16,// 最大空闲连接数
MaxActive: 16,// 最大激活连接数
IdleTimeout: 120, //空间连接时间,超过就会断开
Dial: func() (redis.Conn, error) {//连接的函数
c,err := redis.Dial("tcp","127.0.0.1:6379",
redis.DialConnectTimeout(30 * time.Millisecond),
redis.DialReadTimeout(50 * time.Millisecond), // 5
redis.DialWriteTimeout(50 * time.Millisecond)) // 5
if err != nil{
fmt.Println(err)
return nil,err
}
return c,nil
},
}
}
func do_something(){
conn := Pool.Get()
defer conn.Close()
res,err := conn.Do("HSET","user","like","ball")
fmt.Println(res,err)
res1,err := redis.String(conn.Do("HGET","user","like"))
fmt.Println(res1,err)
}
func main() {
do_something()
}
数据库认真/切换/连接检测
c.Do("AUTH",password)
c.Do("SELECT",dbnum)
c.Do("PING")
go-redis
注意:哨兵和集群是go-redis的,不是上面的redigo
https://github.com/go-redis/redis
哨兵模式
https://blog.csdn.net/busai2/article/details/81449422
集群模式
16384个槽,为什么?
Redis 应用
ZSET : 榜单,排行榜,定时任务
INCR : 点赞
LIST : 管理后台发送通知邮件短信
SET :去重
缓存:缓存热点数据,缓存击穿/雪崩/穿透
更多应用场景,推荐书籍 <Redis开发与运维> <Redis实战>
缓存穿透:
查询的数据 redis没有,mysql也没有,导致每次请求都会达到mysql
查询为空也短暂缓存 + 布隆过滤器
缓存雪崩
同一时间,大量redis-key过期,导致请求到达mysql
key的过期时间随机波动性
缓存击穿
大量请求 正好访问一个恰巧过期的key
限流,二级缓存
优化技巧
- key 尽量都要有过期时间
- 一级key不要太多
- big key 尽量少
- key 分级 shop:userinfo:1000 shop:userinfo:2000
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)