Redis笔记 | 青训营

68 阅读3分钟

Redis - 大厂程序员是怎么用的

大数据量下mysql读写数据压力增加,希望从内存读取数据

  • 写数据时,增量数据保存到磁盘上的AOF文件
  • 全量数据RDB文件:包含所有数据

先读取RDB,看之后有没有没执行的命令,如果有,则加载AOF文件

redis的操作是单线程的,需要排队,先进先出

go导入redis包

 go get github.com/go-redis/redis
 ​
 import "github.com/go-redis/redis"

redis案例

1.连续签到

 Key: cc_uid_1165894833417101
 value: 252
 expireAt:后天的O点

RedisClient.Incr()使原有值+1

2.消息通知 list队列

消息队列list:向队列中放入文章,只要里面有文章就会pop出来通知给ES数据库。

list的数据结构是Quicklist,是一个双向链表,每个节点的entry是一个listpack结构,包含许多元素、每个元素的长度

3.计数 哈希

一个用户的多项计数需求可使用hash结构存储,读很快。map[user_id]=struct{属性1,属性2...}。

读:hgetall命令。

写:使用流水线pipeline将多条数据一次性写redis

数值加一:RedisClient.HIncrBy()

hash的数据结构是dict,是一个单项链表,每个节点下面又有一个单向链表,相当于一个桶。桶0空间不够时需要扩容,使用rehash操作将其中数据全部迁移到另一个桶1中,也可使用渐进式rehash将部分数据迁移,性能更好

4.排行榜 zset

对大量数据(千万级别)进行排序,数据变化后排序,使用zset有序集

zset使用数据结构跳表(zskiplist)+哈希,跳表每个元素是哈希表的一个桶

  • zadd:添加元素到集合
  • zrange:返回正序的集合
  • zrevrange:返回倒序的集合
  • zrank:返回有序集合中指定成员的排名
  • zscore:返回有序集中指定成员的分数值

5.限流

要求一秒内放行n个请求,超过n的无法访问

构建map[时间戳]=cnt,cnt>n禁止访问

6.分布式锁 SetNX

并发场景,要求一次只能有一个协程执行。执行完成后,其它等待中的协程才能执行。

redis的SetNX实现加锁、完成业务、释放锁,但不是高可用分布式锁

redis注意事项

1.大key和热key

(1)大key:value>10KB,读取成本高,容易导致慢查询(过期、删除),主从复制异常,服务阻塞。

处理:

  • 大key拆分成小key
  • 压缩:将value压缩后写入redis
  • 冷热数据分离:热门的放在zset,其他放在db

(2)热key:QPS超过500

处理:

  • 在redis cache前面再加一层LocalCache
  • 拆分key,代价是更新时需要更新多个key,存在数据短暂不一致的风险
  • 使用redis代理

2.慢查询

  • pipeline一次不要传超过100个key
  • zset不要大小超过5KB
  • 对大key的删除和过期操作

3.缓存穿透:热点数据没查缓存,直接查了db。 原因:查询缓存中一定不存在的数据、缓存过期。 解决:缓存空值;布隆过滤器压缩key值,快速判断key是否存在

缓存雪崩:大量缓存同时过期 解决:将缓存失效时间分散开;使用缓存集群