Day 10 Go | 青训营笔记

97 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第10天

起源

数据日益增加,数据存储,读取的需求越来越大,从单表,演进出了分库分表,MySQL从单机演进出了集群。数据量增长导致读写数据压力的不断增加。产生了把数据存储到内存的数据库redis。
一般来说,都是经常访问的热数据才会放到redis中去。

持久化机制

有两个文件,RDB\AOF保证redis的数据的持久化,把数据放到硬盘中去,防止数据丢失。

  • 增量数据保存到AOF文件
  • 全量数据保存到RDB文件 在redis启动中,会先读取RDB文件,然后加载AOF文件,会检查会否有未执行的命令,把未执行的命令加载进去。这样就保证了,redis和上次启动的数据保持一致。

RDB是个二进制文件。 image.png

处理机制

redis是个单线程处理机制,采用非阻塞IO多路复用技术,会把收到的命令按先后顺序进行处理。该特性对于分布式锁有重要意义。

案例

连续签到

把用户id作为key,连续签到天数为value。然后在后天的0点设置为key的过期时间

使用到的数据结构String redis使用的string是二进制存储,【节省空间,更快速的读写数据】 image.png 数据存到buf中,预先设置的有足够的空间。空间不够也会扩容。寻址的时候指针sds指针会指到buf前,然后向左移动,获取到数据的类型(flags),获取buf的长度(alloc),存储数据的长度(len)。

消息通知

用list作为消息队列 例如当文章更新时,将更新后的文章推送到ES,用户就能搜索到最新的文章数据 使用到的数据结构list

QuickList是一个双向链表和listpack实现 image.png

image.png

用户数据

一个用户有多项计数需求,可通过hash结构存储,例如账号下的:文件数、点赞数、阅读数等统一存放到hash中,通过一条命令去读取多条数据。

一次性取多个数据,也可对每个数据项单独变更。 hash使用开链法解决冲突,当某一条链过长,就会rhash,但是数据过多的话,服务压力过大,所以会选择渐进式rhash。每一个访问,都慢慢挪动数据。

榜单

用户查看榜单使用redis命令,比如zreverang 倒排序然后返回数据 使用zset结构,底层使用zskipset(跳表)

image.png 结合使用hash,node节点的对象存放更多数据和更多类型

限流

使用inc命令进行限流,比如一分钟最多访问几次key

分布式锁

并发场景,要求一次只能有一个协程执行执行完成后,其它等待中的协程才能执行 可以使用redis的setnx实现
利用了两个特性:1. Redis是单线程执行命令2. setnx只有未设置过才能执行成功 image.png 存在的问题
但是setnx不是高可用的。假如一个协程获得锁,但发生异常,锁未释放就会阻塞所有的协程,可以设置时长,时间一到就释放。
主从分库,读写分离,如果主库获得锁,但是那一瞬间没同步到从库,导致从库可以上锁,就出现了并发问题。

未完。。。。。