掘金-Redis

83 阅读4分钟

是什么

为什么要:

一开始是web/server/mysql结构, 随着数据量增加,业务场景不断扩充。

数据表从单表演化为分库分表。

【数据量增长、读写数据压力不断增加】(一台MySQL速度跟不上),【mysql从单机到集群】(出现集群)

一主MySQL多从MySQL

主负责写,从负责读。

秒杀、高qps情况下MySQL作实时查询支撑不住。

考虑从内存读取数据,把数据存到内存,redis应运而生。

image.png

数据分冷热数据,(经常访问的)热数据存到内存中。

读场景:浏览器发起的请求,来到服务器端,服务器判断数据在redis(内存)中是否在,存在返回一个用户。不存在,去MySQL中读取数据,再回写到redis中

【回写到redis中】

写场景:一般有两种方式,此处为一种。

go/Java服务端先写入MySQL数据,MySQL会产生监听binlog,记录MySQL中数据变更。

很多开源框架可以反解binlong,解析到数据变更后,再把数据变更写到redis里。

image.png

基本原理

内存中数据,服务器重启后数据会丢失。

redis数据的特征:一定程度的持久化。重启不会丢失。

如何保证数据不会丢失

redis基本结构:

客户端/Java/go程序读写redis数据时,走的是RESP协议。

协议传到redis服务端,服务端收到请求就把数据读写到内存中。

其实在读写到内存之前,会产生一条日志【叫(appendonly.aof)AOF文件】,写到磁盘文件上

AOF:append of field 把新数据追加到文件末尾。

如果服务器宕机,redis重启的时候会读取aof文件,重放完aof中的命令后才会拉起redis服务。数据不会丢失。

RDB文件(是二进制的文件):保存了当前redis实例的所有的[key信息/文件]。

整个启动过程,先读取RDB文件,再去对比RDB之后有没有未执行的命令 如果有就会把AOF没有执行的命令加载进去

image.png

redis是单线程处理所有操作命令

多命令进入,排队处理

image.png

案例

连续签到

如何归零:用到redis的过期。 设置过期时间。

image.png

数据结构

为什么要学数据结构:实际开发中,重视基础。 比如用到key/value存储的功能时,设计时为什么用这个数据结构?为什么用这个数据结构会提升性能,压缩存储

go的string比较特殊:

是二进制安全的数据,实际存储二进制数据。

  • 存储时足够节省空间
  • 很快读数据
  • 字符变更时很快把数据写进去

image.png

注意事项

sds

实际分四段。

len:字符串的容量长度 alloc:存储的长度 flags: buffer:实际存储位置

寻址的时候get一个key,key指针会指到这,先左移得到flags知道当前存的是什么数据类型。就知道指针向左移几位是元信息。左移一个是字符串长度“向右移动指针移几位”。

Redis基本操作

2.3.1 熟悉以下命令的操作

  • GET/SET/DEL/INCR/SETNX
  • HSET/HGET/HINCRBY
  • LPUSH/RPOP/LRANGE
  • ZADD/ZRANGEBYSCORE/ZREVRANGE/ZINCRBY/ZSCORE

消息通知

redis的list其实是quicklist

双向链表+listpack。

listpack的结构:第一个字节记录,整个内存空间大小,右移一个字节得知存了几个元素,

image.png

image.png

哈希数据结构

速度参考:

一个qps,在mysql中count的10000行,需要十多ms。百万级别没法count

如果存到redis里查询,2ms就可以。

pipelining

redis中一次设置或者get多个key时,如果用多个redis链接,很磨叽,用pipelining。减少网络上的来回传输。

初始化pipelining,把三条命令打包set到pipelining。之后go客户端会把三条命令一次性发到服务器

Hmget

HGetAll

改数据/增加

redis有increase命令。

哈希也有增加哈希表中一个元素的值,调用incr__byfield.

redisclient.HIncrBy()方法。

哈希结构

为什么rehash?

在扩容的同时,又要保证redis正常响应,不能阻塞redis的访问。数据迁移,先扩容,再拷贝。

渐进式:把拷贝过程,平摊到每次用户访问过程中,迁移一部分数据。

原H0,新H1.

用户访问H0的元素时,顺带迁移到H1中。

最后H0指针指向H1,H1指针置空。

image.png

image.png

ZSET

用例:天梯榜单。【高qps下更新数据,且排序】

添加榜单 ZADD

ZRANGEBYSCORE 查看积分

ZREVRANGE 倒排序

ZINCRBY

ZSCORE get命令对应方法

zset数据结构

zskiplist跳表.

找7找3

head--3--7

head--3--1

image.png

redis的zset用的是哈希+跳表。

可以由排名跳表指针查元素的哈希kv 也可由key反哈希差跳表排名

跳表一般不会超过4层。

构成的是双向链表

image.png

限流

用key字段,后面带有时间戳(数字部分)。

时间戳最小单位为1s,规定1s内的请求数n

多次用到increase命令,通过一个请求就+1,请求数小于n,放行。超过n时,限流

image.png

redis做分布式锁