青训营笔记4:Redis| 青训营

45 阅读4分钟

Redis

Redis是什么

随着数据量增大,读写数据压力不断增大,数据库不断增大,分页等操作,会减慢读取数据的时间。

数据可以分为冷热,热数据即经常访问到的数据,可以的一种逻辑是每次先从redis读,没有的话就再从mysql读,写的话直接往mysql写,redis监听binding修改redis。Redis缓存在内存里,比在磁盘里读取要快很多,且数据会同步到硬盘上防止重启数据丢失,保证数据持久化。

Redis应用案例

  1. 连续签到

    每天有一次签到机会,每天的23:59:59之前,如果断签计数归零。

    Key : cc_uid_xxxxx

    value : 252

    expireAt : 后天的0点

    [知识点]自增和过期

  2. 消息通知

    文章更新时,将更新后的文章推送到ES(搜索引擎),用list作为消息队列。

  3. 计数

    一个用户有多项计数需求,可以通过hash结构存储。例如关注功能等,需要每一个关注就加一条记录,当关注的数量到达一定的数量级,count函数的性能就会很不好,这个时候就需要使用redis来完成计数。redis中一个key的value可以是一个hash结构,减少了key的数量。

    也可以使用自增命令HIncrBy

    [知识点] rehash 渐进式rehash(访问时rehash)

  4. 排行榜

    积分变化时,排名要实时变更。

    榜单的数据可能是千万级的,按照积分进行排序,对千万数据排序是不太能接受的。

    redis数据结构有zset ,用跳跃表加hash实现

  5. 限流

    要求1秒内放行的请求为N,超过N则禁止访问。(key的值insr,超出限制,comment_freq_limit_[时间戳])

  6. 分布式锁

    并发下只能由一个协程执行。用setnx实现,redis是单线程的。

Redis使用注意事项

  1. 大Key,热Key

    大key : value的字节数大于10KB或复杂结构的数量多于5k -> 拆分/压缩

    热key :QPS超过500

  2. 慢查询场景

    一次性传入过多数据、zset很大、大key

  3. 缓存穿透,缓存雪崩

    缓存穿透:查询一个一定不存在的数据,请求一定会直接到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)。