Redis
Redis是什么
随着数据量增大,读写数据压力不断增大,数据库不断增大,分页等操作,会减慢读取数据的时间。
数据可以分为冷热,热数据即经常访问到的数据,可以的一种逻辑是每次先从redis读,没有的话就再从mysql读,写的话直接往mysql写,redis监听binding修改redis。Redis缓存在内存里,比在磁盘里读取要快很多,且数据会同步到硬盘上防止重启数据丢失,保证数据持久化。
Redis应用案例
-
连续签到
每天有一次签到机会,每天的23:59:59之前,如果断签计数归零。
Key : cc_uid_xxxxx
value : 252
expireAt : 后天的0点
[知识点]自增和过期
-
消息通知
文章更新时,将更新后的文章推送到ES(搜索引擎),用list作为消息队列。
-
计数
一个用户有多项计数需求,可以通过hash结构存储。例如关注功能等,需要每一个关注就加一条记录,当关注的数量到达一定的数量级,count函数的性能就会很不好,这个时候就需要使用redis来完成计数。redis中一个key的value可以是一个hash结构,减少了key的数量。
也可以使用自增命令HIncrBy
[知识点] rehash 渐进式rehash(访问时rehash)
-
排行榜
积分变化时,排名要实时变更。
榜单的数据可能是千万级的,按照积分进行排序,对千万数据排序是不太能接受的。
redis数据结构有zset ,用跳跃表加hash实现
-
限流
要求1秒内放行的请求为N,超过N则禁止访问。(key的值insr,超出限制,comment_freq_limit_[时间戳])
-
分布式锁
并发下只能由一个协程执行。用setnx实现,redis是单线程的。
Redis使用注意事项
-
大Key,热Key
大key : value的字节数大于10KB或复杂结构的数量多于5k -> 拆分/压缩
热key :QPS超过500
-
慢查询场景
一次性传入过多数据、zset很大、大key
-
缓存穿透,缓存雪崩
缓存穿透:查询一个一定不存在的数据,请求一定会直接到db/缓存过期
在Ubuntu上安装redis
在 Ubuntu 上安装 Redis 非常简单直接。
Redis 5.0 被包含在默认的 Ubuntu 20.04 软件源中。想要安装它,以 root 或者其他 sudo 身份运行下面的命令:
sudo apt update
sudo apt install redis-server
一旦安装完成,Redis 服务将会自动启动。想要检查服务的状态,输入下面的命令:
sudo systemctl status redis-server
测试连接
在 Ubuntu 上安装 Redis 非常简单直接。
Redis 5.0 被包含在默认的 Ubuntu 20.04 软件源中。想要安装它,以 root 或者其他 sudo 身份运行下面的命令:
sudo apt update
sudo apt install redis-server
一旦安装完成,Redis 服务将会自动启动。想要检查服务的状态,输入下面的命令:
sudo systemctl status redis-server
想要验证所有设置都设置好了,可以尝试使用redis-cli从你的远程机器上 ping 一下 Redis 服务器。
redis-cli -h <REDIS_IP_ADDRESS> ping
返回响应PONG
Go语言 Redis
使用以下命令下安装 go-redis 库。
go get github.com/go-redis/redis/v8
连接redis服务器
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // 密码
DB: 0, // 数据库
PoolSize: 20, // 连接池大小
})
基本使用方法
// doCommand go-redis基本使用示例
func doCommand() {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
// 执行命令获取结果
val, err := rdb.Get(ctx, "key").Result()
fmt.Println(val, err)
// 先获取到命令对象
cmder := rdb.Get(ctx, "key")
fmt.Println(cmder.Val()) // 获取值
fmt.Println(cmder.Err()) // 获取错误
// 直接执行命令获取错误
err = rdb.Set(ctx, "key", 10, time.Hour).Err()
// 直接执行命令获取值
value := rdb.Get(ctx, "key").Val()
fmt.Println(value)
}
不存在错误
if errors.Is(err, redis.Nil) {
return defaultValue, nil
}
遍历key
vals, err := rdb.Keys(ctx, "prefix*").Result()
Redis Pipeline 允许通过使用单个 client-server-client 往返执行多个命令来提高性能。区别于一个接一个地执行100个命令,你可以将这些命令放入 pipeline 中,然后使用1次读写操作像执行单个命令一样执行它们。这样做的好处是节省了执行命令的网络往返时间(RTT)。