文章目录
1 Redis基础介绍
1.1 redis 是一个高性能的 key-value 缓存数据库,
1、支持数据持久化
2、丰富的数据类型
3、原子性操作
1.2 redis 的作用
1、提供缓存服务
2、用于分布式锁
3、用于做消息队列(不是redis的优势)
1.3 为什么要用Redis
传统的关系型数据库Mysql基于磁盘读写的应用不足以支撑更大的访问量,
我们可以借助redis这种基于内存操作的缓存中间件,将不需要实时的数
据可以放到redis中,这样轻松的就可以支撑更大的访问量
- 工作中
例如:
1、对课程信息的缓存,大量的客户端请求直接命中缓存,不需要查询数据库了
2、做分布式锁,进行资源的竞争控制
1.3.1 性能高
1、纯内存访问
2、使用io多路复用模型
- 1 通过io多路复用模型,监听socket时间
- 2 进行处理,放到事件队列中
- 3 事件分派器处理,处理
- 连接应答处理器(处理socket连接)
- 命令处理器(读取socket的请求数据)
- 命令回复器(返回处理结果)
3、单线程避免了线程切换和锁产生的消耗
4、Redis支持强大的数据结构,提供更加快速的访问
1.4 为什么用redis,不用mencached?
因为redis支持更多的数据结构,支持持久化储存,可进行灾难恢复时,通过RDB和AOF来恢复数据
memcache的value最多1M大小,失效时间中最多设置30秒,不支持持久化。目前很多场景转向redis了
(不能持久化,失效时间最多设置30,value值只能1M)
1.5、Redis有那些数据结构
1.5.1 String
实现机制:
- SDS简单动态字符串,保存了长度字段和预分配空间和惰性回收
struct SDS{
T capacity 容量
T len 数组长度
byte flags 标志位
char[] content 数组内容
}
使用场景:
- 缓存: 经典使用场景,把常用信息,字符串,图片或者视频等信息放到redis中,redis作为缓存层,mysql做持久化层,降低mysql的读写压力。
- 计数器:redis是单线程模型,一个命令执行完才会执行下一个,同时数据可以一步落地到其他的数据源。
- session:常见方案spring session + redis实现session共享,
1.5.2 list
实现机制:
- 当元素比较小的时候采用ZipList(压缩列表),将所有元素彼此紧挨着,分配的是一个连续的空间,
struct ziplist{
int zlbytes //整个压缩列表占用字节数
int zltail_offset //最后一个元素距离压缩列表其实位置的偏移量
int zllength //元素个数
T[] entries //元素内容
int zlend //标准压缩列表的结束 值恒为 0XFF
}
struct entry{
int prevlen //前一个entry的字节长度
int encoding //元素类型编码
byte[] content //元素内容
}
- 当数据比较多的是时候变成QucikList(快速列表) 将多个ZipList用指针连接起来。
struct quicklist{
quicklistNode* head
quicklistNode* tail
long count //元素总和
int nodes //ziplist 节点的个数
int compressDepth //LZF算法压缩深度
}
struct quicklistNode{
quicklistNode* prev
quicklistNode* next
ziplist* zl //如果当前节点的数据没有压缩,那么它指向一个ziplist结构;否则,它指向一个quicklistLZF结构。
int32 size //ziplist的字节总数
int16 count //ziplist中的元素数量
int2 encoding//存储类型 是元素字节数组话说LZF压缩存储
}
使用场景:
- 微博TimeLine: 有人发布微博,用lpush加入时间轴,展示新的列表信息。
- 消息队列
- 列表数据
1.5.3 Hash
实现机制:
- 数据量小时使用压缩列表zipList
- 数据量大一些时使用字典dict
redisDb{
dict
expires
blocking_keys
ready_keys
watched_keys
id
avg_ttl
expires_cursor
defray_later
}
dict{
type
privdata
dictht ht[2] //包含两个hashtable,一个存放值,一个用于字典扩容缩容
rehashidx
iterators
}
dictht{
dictEntry table //链表
size //第一维数组的长度
sizemask //
userd //hash表中元素个数
}
dictEntry{
key
union{
val
u64
s64
}
dictEntry* next //链表下一个节点
}
使用场景:
缓存: 能直观,相比string更节省空间,的维护缓存信息,如用户信息,视频信息等。
1.5.4 set
实现机制:
两个条件任务满足时set将。1.元素个数小于set-max-intset-entries,2.元素无法用整形表示
- 满足时,用dict存储数据
- 不满足时,用intset存储数据
struct intset{
int32 encoding //决定整数位宽
int32 lenght //元素个数
int<T> contents //整数数组
}
使用场景:
- 点赞,或点踩,收藏等,可以放到set中实现
- 一些去重场景
1.5.5 ZSet
实现机制:
- 数据量小的时候用压缩链表ziplist
- 数据量大就用跳跃表skiplist
struct zslnode{
string value //key
double score //分数
zslnode*[] forwards //多层连接指针
zslnode* backward //回溯指针
}
struct zsl{
zslnode* header //跳跃列表头指针
int maxLevel //跳跃列表当前的最高层
map<String,zslnode*> ht //hash结构的所有键值对
}
使用场景:
排行榜:有序集合经典使用场景。例如小说视频等网站需要对用户上传的小说视频做排行榜,榜单可以按照用户关注数,更新时间,字数等打分,做排行。