价值与场景
Redis 这么火,它都解决了哪些问题?
问题场景:接口慢
方案1:消费者端缓存(cache-control:max-age)——旧数据,依然有大量新请求
方案2:基于本机内存的1分钟缓存——旧数据,单机内存不够
方案3:Redis单机服务器——挂了就缓存丢失、造成重启和恢复中的雪崩
方案4:Redis持久化——缓解重启时的大量重新请求
方案5:Sentinel和Replication——缓解Redis挂了的问题
- Sentinel可以管理多个Redis服务器,它提供了监控,提醒以及自动的故障转移的功能;是对Redis的发布和订阅功能的一个利用。
- Replication则是负责让一个Redis服务器可以配备多个备份的服务器。Redis也是利用这两个功能来保证Redis的高可用的。
方案6:集群——解决单机资源有限问题
- Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
- Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
常用数据结构
String,Hash,List,Set,Sorted Set
https://my.oschina.net/xsh1208/blog/2218494
- String
可变的字节数组
会多分配空间字符串长度小于1M时,扩容都是加倍现有的空间,如果超过1M,扩容时一次只会多扩1M的空间
# get set strlen
# getrange 获取子串
# setrange 设置子串
# append 追加
# 没有删除子串,和插入子串
# 计数器
> set ireader 42
OK
> get ireader
"42"
> incrby ireader 100
(integer) 142
> get ireader
"142"
> decrby ireader 100
(integer) 42
> get ireader
"42"
> incr ireader # 等价于incrby ireader 1
(integer) 143
> decr ireader # 等价于decrby ireader 1
(integer) 142
> expire ireader 60
(integer) 1 # 1表示设置成功,0表示变量ireader不存在
> ttl ireader
(integer) 50 # 还有50秒的寿命,返回-2表示变量不存在,-1表示没有设置过期时间
> del ireader
(integer) 1 # 删除成功返回1
> get ireader
(nil) # 变量ireader没有了
- list
双向链表实现(数据量少是ziplist,数据量大是quicklist(把连续的内存空间(ziplist)连起来而非对每个元素都用指针连,后者太费空间))。可用作队列、堆栈
rpush
rpop
lpush
lpop
llen
lset
lrange
linsert xxx before a b# linsert指令并不是通过指定位置来插入,而是通过指定具体的值
lrem l_name n object# 删除
blpop # 阻塞pop
lindex # 随机读
- hash
和Java的HashMap数据结构一致
# 增加元素
> hset ireader go fast
> hmset ireader java fast python slow # 添加多个
# 获取元素
> hmset ireader go fast java fast python slow
OK
> hget ireader go
"fast"
> hmget ireader go python
1) "fast"
2) "slow"
> hgetall ireader
1) "go"
2) "fast"
3) "java"
4) "fast"
5) "python"
6) "slow"
> hkeys ireader
1) "go"
2) "java"
3) "python"
> hvals ireader
1) "fast"
2) "fast"
3) "slow"
#删除元素
> hmset ireader go fast java fast python slow
OK
> hdel ireader go
(integer) 1
> hdel ireader java python
(integer) 2
# 是否存在
> hexists ireader go
(integer) 1
hash也可做计数器
- Set
Java的HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构
> sadd ireader go java python # 插入
(integer) 3
# 读取
> smembers ireader
1) "java"
2) "python"
3) "go"
> scard ireader
(integer) 3
> srandmember ireader
"java"
# 删除
> sadd ireader go java python rust erlang
(integer) 5
> srem ireader go java
(integer) 2
> spop ireader
"erlang"
# 元素是否存在
> sismember ireader rust
(integer) 1
> sismember ireader javascript
(integer) 0
- ZSet(SortedSet)
SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。
zset底层实现使用了两个数据结构,第一个是hash,第二个是跳跃列表,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。跳跃列表的目的在于给元素value排序,根据score的范围获取元素列表。
# 增加1-N个value/score对
> zadd ireader 4.0 python
(integer) 1
> zadd ireader 4.0 java 1.0 go
(integer) 2
# 获取排名
> zscore ireader python
"5"
> zrank ireader go # 分数低的排名考前,rank值小
(integer) 0
> zrank ireader java
(integer) 1
> zrank ireader python
(integer) 2
> zrevrank ireader python
(integer) 0
# 操作很多,不一一列举
跳表很重要!
高级数据结构
https://blog.csdn.net/wufaliang003/article/details/82016385
- Bitmaps
127.0.0.1:6380> setbit dupcheck 10 1
(integer) 0
127.0.0.1:6380> getbit dupcheck 10
(integer) 1
- Hyperloglogs
涉及数学,不太理解 - GEO
地理位置信息,经纬度
- Pub/Sub主题订阅者模式
实现1对N的消息订阅
缺点:消费者下线的情况下,生产的消息会丢失,要用专业的消息队列如rabbitmq等。
底层数据结构
-
跳表 SkipList/JumpLink
http://www.cnblogs.com/seniusen/p/9870398.html
https://www.cnblogs.com/a8457013/p/8251967.html
https://redisbook.readthedocs.io/en/latest/internal-datastruct/skiplist.html
为什么用跳表而不是平衡树 -
ziplist+quicklist
进阶
Redis Module
1.BloomFilter
2.RedisSearch
3.Redis-ML
分布式锁
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
- 如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
这个锁就永远得不到释放了。set指令有非常复杂的参数,是可以同时把setnx和expire合成一条指令来用.
核心原理与源码分析
http://zhangtielei.com/posts/blog-redis-how-to-start.html
- Redis的事件循环(Event Loop)的机制,关系到:
为什么Redis是单线程执行却能同时处理多个请求?(当然严格来说Redis运行起来并非只有一个线程,但除了主线程之外,Redis的其它线程只是起辅助作用,它们是一些在后台运行做异步耗时任务的线程)
Redis的main函数开始执行后的逻辑可以分为两个阶段:
1.各种初始化(包括事件循环的初始化);
2.执行事件循环。
这几个部分也很重要,有时间再细细了解
- 持久化
- PipeLine
- 同步机制
网友评论