Redis_1

Redis(Remote Dictionary Server)

视频教程:全面透析redis底层原理+redis分布式锁+企业解决方案+redis实战

redis是基于内存的,速度快;IO多路复用;有丰富的数据类型,合适的选择可以提高运行效率。

String

setnx加ex超时,配合lua,分布式锁。

有自增自减操作(INCR -1),SETNX,将对象序列化为JSON字符串后存储

缓存击穿中热点key加互斥锁的时候可以用SETNX来实现()

分布式中全局唯一ID,每天一个key(方便统计)、ID构造是 时间戳 + 计数器(自增实现)

Hash

可重入锁,field是threadid,value是次数,配合lua。

无序字典,里面会有对应域和值,可对单个字段做独立的CRUD

List

异步队列,生产者消费者,下的单进行消费,但是单一消费者。

双向链表,插入和删除快

可用BLPOP和RPUSH,或者BRPOP和LPUSH,实现阻塞队列,缺点:

Set

与hashset,可看作value为null的hashmap,无序、不重复,查找快,交集、并集、差集等

比如看自己跟别人的共同关注列表

SortedSet

每一条博客下面,按照用户点赞时间排序给用户排序。

底层实现是skiplist跳表+hash表

根据score排序,不重复,查询快

用来做排行榜等

GEO和BitMap

==geo==获取附近商铺信息

==bitmap==比如每日签到,签到统计

注意

GEO是sortedset的实现

bitmap其实是==string数据类型==实现

新的数据类型Stream,消息队列

缓存穿透

客户端请求的,在缓存中和数据库中都不存在

  1. 缓存空对象(+TTL)
  2. 布隆过滤(BitMap实现)(多一层前置过滤,存在误判)

缓存雪崩

同一时间大量缓存的key同时失效 或 Redis服务宕机,大量的请求到达服务器

针对不同的有不同的方法,给不同的key的TTL添加波动的随机值;Redis主从集群哨兵(能解决高并发读,高可用),分片集群(高并发写,海量数据存储)。

但是如果真的出现了,也要考虑。给缓存业务添加降级限流策略(消息队列固定请求大小,削峰填谷。判失败,拒绝服务器),给业务添加多级缓存。

缓存击穿

热点key都会首先缓存到redis中的。

热点key问题,被高并发访问并且缓存重建业务复杂(重建的时间内大量的访问)的key失效了。

解决:互斥锁(SETNX(),需要TTL防止程序异常。一致性)(加锁是查询数据库的时候加锁,而且这个key最好是加适当的时间呀,如果说他是在1天内秒杀,然后提前一天上架,那么久TTL设置成2天呗?);逻辑过期(不用TTl自己维护一个expire,也要获锁新开线程。可用性,无需等待,但是期间拿到的是旧数据)

HyperLogLog做UV统计

pipeline批量导入数据,pipeline的多个命令之间不具备原子性,mset和pipeline这样的批处理,如果是在集群中,那么批处理命令的多个key必须落在一个插槽中。

持久化

RDB和AOF

主从和哨兵(高可用、高并发读)

IMG_0301A08F2931-1.jpg

IMG_5AD953718C41-1.jpg

IMG_F7B6AAA32E9D-1.jpg

IMG_2015.jpg

分片(海量数据存储、高并发写)

散列插槽,数据key与插槽绑定(16384个插槽分配到不同的实例,根据有小部分计算哈希值,取余)

多级缓存

OpenResty
Redis缓存预热

缓存同步

数据库的主从同步原理

IMG_09705D2FEE35-1.jpg

设置有效期外失效,同步双写强一致性(修改完数据库修改缓存形成事务),异步通知

异步通知,第一种是基于==MQ==的异步通知,需要手写发布监听,然后更新;第二种是canal,把自己伪装成一个MYSQL的slave节点,从而坚挺binary log的变化,再把得到的变化信息通知给canal的客户端,进而完成对其他数据库的同步。所以要用canal,要先实现mysql的主从。

IMG_33E435DAFCBC-1.jpg

AOP:事务、动态代理

SDS动态字符串

redis没有直接使用c的字符串(获取长度需要遍历,非二进制安全,不可修改)

SDS中有buf[],一保存字符串长度,申请总字节数,不同头类型大小,可以动态扩容

IntSet

唯一、长度可变、有序、二分查找来查询

Dict

dict由三部分组成:哈希表、哈希节点、字典。一个dict中有两个哈希表bictht,一个用于存储,一个用于扩容再哈希使用。哈希表中是数组结合单向链表实现解决hash冲突,类似java的hashtable,当个数到达一定的时候,会扩容收缩(伴随再hash)。

非连续,碎片多

ZipList

一个特殊的“双端链表”,由一系列特殊编码的连续内存组成,用1字节或者5字节保存前一节点的长度而不是用指针记录前后节点。

QuickList

一个双端链表,链表中的每一个节点都是一个ziplist。(LinkedList+ZipList)使用的ziplist,解决了传统链表的内存占用问题(碎片),控制每一个zipilst大小,解决了连续内存空间申请的效率问题,中间节点可以压缩进一步节省内存。

SkipList跳表

链表,升序排序,节点包含多个后指针,跨度不同,前驱指针只有一个

RedisObject

Redis的任意数据类型的键和值都会被封装为一个RedisObject,也叫Redis对象。

五种数据结构是如何的

IMG_2026.jpg

网络模型

IMG_2047.jpg

为什么redis单线程

IMG_2056.jpg

内存回收

IMG_2060.jpg

Author: Jcwang

Permalink: http://example.com/2022/05/13/redis-1/