一天时间把redis吃透!
https://mp.weixin.qq.com/s/aOiadiWG2nNaZowmoDQPMQ -----建议参考博客
1.小伙子为什么选择用redis
- 因为传统的关系型数据库已经不适用所有的场景,比如双十一的秒杀,或者是APP的流量访问高峰;这些都会把数据打穿,所有我们引入了消息中间件—redis。
2.讲讲redis的基本数据类型吧
-
string [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lfGovrW2-1630285002020)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210829100047445.png)]
-
hash–类似hashmap
-
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pBFTzABi-1630285002024)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20210829101139149.png)]
-
list:Redis列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)—arrylist
LPUSH student ding---插入一个(左边) LINDEX student 0---取出下标0 RPUSH student zheng --插入右边 LRANGE students 0 10----取出下标0-10
-
set:散列表—hashset
-
redis 127.0.0.1:6379> SADD runoobkey redis---插一个或者多个都是这个 (integer) 1 redis 127.0.0.1:6379> SADD runoobkey mongodb (integer) 1 redis 127.0.0.1:6379> SADD runoobkey mysql (integer) 1 redis 127.0.0.1:6379> SADD runoobkey mysql (integer) 0 redis 127.0.0.1:6379> SMEMBERS runoobkey 1) "mysql" 2) "mongodb" 3) "redis"
-
sorted set–带下标一个链表—crud的速度都是O(1)
-
redis 127.0.0.1:6379> ZADD runoobkey 1 redis (integer) 1 redis 127.0.0.1:6379> ZADD runoobkey 2 mongodb (integer) 1 redis 127.0.0.1:6379> ZADD runoobkey 3 mysql (integer) 1 redis 127.0.0.1:6379> ZADD runoobkey 3 mysql (integer) 0 redis 127.0.0.1:6379> ZADD runoobkey 4 mysql (integer) 0 redis 127.0.0.1:6379> ZRANGE runoobkey 0 10 WITHSCORES 1) "redis" 2) "1" 3) "mongodb" 4) "2" 5) "mysql" 6) "4"
-
Bloomfilter
-
布隆过滤器实际上是由一个超长的二进制位数组和一系列的哈希函数组成。二进制位数组初始全部为0,当给定一个待查询的元素时,这个元素会被一系列哈希函数计算映射出一系列的值,所有的值在位数组的偏移量处置为1。如下图所示:
-
布隆过滤器的原理是,当一个元素被加入集合时,通过K个散列函数将这个元素映射成一个位数组中的K个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。这就是布隆过滤器的基本思想。
3. 理解一些hash函数的计算
知识铺垫:
-
- 与运算(&)全1为1,有0未0-----类似且(&&)
- 或运算(|)有1为1,全0为0-----类似或(||)
- 异或运算(^)相同为0,不同为1
hashcode
- 而hashcode用的是与运算
(length-1) & key.hashCode() => 1111 & 10001011000001111110001000
位数不够,高位补0,即
0000 0000 0000 0000 0000 0000 1111
&
0010 0010 1100 0001 1111 1000 1000------随机的一个hashcode
&运算规则是第一个操作数的的第n位于第二个操作数的第n位都为1才为1,否则为0
所以结果为0000 0000 0000 0000 0000 0000 1000,即 8
length-1&key.hashCode-------公式
-
hashmap中的key的下标是怎么算出来的
-
(length-1)&hash
-
hash函数的计算如下-----i.hashCode()^(i.hashCode()>>>16)
-
public static void main(String[] args) { String i="郭德纲"; System.out.println(i.hashCode());//10001011000001111110001000 System.out.println(i.hashCode()>>>16);//1000101100 System.out.println(i.hashCode()^(i.hashCode()>>>16));//10001011000001110110100100 }
4.缓存击穿
缓存击穿,就是某个热点数据失效时,大量针对这个数据的请求会穿透到数据源。
解决这个问题有如下办法。
- 可以使用互斥锁更新,保证同一个进程中针对同一个数据不会并发请求到 DB,减小 DB 压力。
- 使用随机退避方式,失效时随机 sleep 一个很短的时间,再次查询,如果失败再执行更新。
- 针对多个热点 key 同时失效的问题,可以在缓存时使用固定时间加上一个小的随机数,避免大量热点 key 同一时刻失效。
5.重点说一下这个List类型吧
- list类型可以做一个左进右出消息队列
- LPUSH从左边(也就是头部)插入数据,BRpop从尾部取数据
6. 讲一下redis的高可用吧
-
Redis 支持主从同步,提供 Cluster 集群部署模式,通过 Sentine l哨兵来监控 Redis 主服务器的状态。当主挂掉时,在从节点中根据一定策略选出新主,并调整其他从 slaveof 到新主。
-
选主的策略简单来说有三个:
- slave 的 priority 设置的越低,优先级越高;
- 同等情况下,slave 复制的数据越多优先级越高;
- 相同的条件下 runid 越小越容易被选中。
在 Redis 集群中,sentinel 也会进行多实例部署,sentinel 之间通过 Raft 协议来保证自身的高可用。
7. 说一下哨兵模式吧
背景介绍:
- 主从切换技术的方法是:当主服务器宕机后,需要手动把一台从服务器切换为主服务器,这就需要人工干预,费事费力,还会造成一段时间内服务不可用。这不是一种推荐的方式,更多时候,我们优先考虑哨兵模式。
简介:
- redis内部提供了哨兵命令,哨兵是作为一个进程独立运行的,原理:哨兵发送命令,等待redis服务器响应,从而监控redis实例。
作用:
- 哨兵通过发送命令来检测redis服务器的状态
- 如果redis主服务挂了,哨兵负责选举出来新的master,并且通过发布者订阅模式通知其他服务器,修改配置文件。
8. 客户端连接哨兵服务器的原因
- 哨兵服务器相当于注册中心。先从注册中心获取redis master 服务地址,然后再发起链接。当master宕机 哨兵会进行投票决定master是否真正死亡,然后选举最健康的slave作为新的master,然后客户端再次发起新的链接
9. http和https的区别
- HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全。
为什么安全捏?—https的流程
- 使用https的url请求服务器建立SSL连接
- 服务器会返回一个证书信息(包含公钥)返回给客户端
- 客户端拿着公钥对自己会话产生的密钥进行加密,发送给服务器
- 服务器收到后利用自己的私钥解析出会话的密钥
10. 如何保证你的redis里面全是热点数据
-
给key一个过期时间
-
定期删除+惰性删除
定期删除:隔一段时间就随机拿出一些key,如果过期就给他删除
惰性删除:使用key的时候,就检查一下设置的定期时间是否过期,如果过期就给它删除
-
如果定期遗漏了很多key,且也没走查询,也就没走惰性,这时就走淘汰机制
-
redis的淘汰策略:默认是 noeviction
noeviction:当内存使用达到阀值的时候,所有引起申请内存的命令会报错;
allkeys-lru:尝试回收,最近未使用或者使用比较少的键。(范围是:所有的键)
volatile-lru:尝试回收,最近未使用或者使用比较少的键。(范围是:设置了过期时间的键)
allkeys-random:随机移除某个key。(范围是:所有的键)
volatile-random:随机移除某个key。(范围是:设置了过期时间的键)
volatile-ttl:回收过期时间较短的key。(范围是:设置了过期时间的键)
概述(背!)
1. Redis是什么?简述它的优缺点?
Redis本质上是一个Key-Value类型的内存数据库,很像Memcached,整个数据库加载在内存当中操作,定期通过异步操作把数据库中的数据flush到硬盘上进行保存。
因为是纯内存操作,Redis的性能非常出色,每秒可以处理超过 10万次读写操作,是已知性能最快的Key-Value 数据库。
优点:
- 读写性能极高, Redis能读的速度是110000次/s,写的速度是81000次/s。
- 支持数据持久化,支持AOF和RDB两种持久化方式。
- 支持事务, Redis的所有操作都是原子性的,意思就是要么成功执行要么失败完全不执行。单个操作是原子性的。多个操作也支持事务,即原子性,通过MULTI和EXEC指令包起来。
- 数据结构丰富,除了支持string类型的value外,还支持hash、set、zset、list等数据结构。
- 支持主从复制,主机会自动将数据同步到从机,可以进行读写分离。
- 丰富的特性 – Redis还支持 publish/subscribe, 通知, key 过期等特性。
缺点:
- 数据库容量受到物理内存的限制,不能用作海量数据的高性能读写,因此Redis适合的场景主要局限在较小数据量的高性能操作和运算上。
- 主机宕机,宕机前有部分数据未能及时同步到从机,切换IP后还会引入数据不一致的问题,降低了系统的可用性。
2. Redis为什么这么快?
-
内存存储:Redis是使用内存(in-memeroy)存储,没有磁盘IO上的开销。数据存在内存中,类似于 HashMap,HashMap 的优势就是查找和操作的时间复杂度都是O(1)。
-
单线程实现( Redis 6.0以前):Redis使用单个线程处理请求,避免了多个线程之间线程切换和锁资源争用的开销。注意:单线程是指的是在核心网络模型中,网络请求模块使用一个线程来处理,即一个线程处理所有网络请求。
-
非阻塞IO:Redis使用多路复用IO技术,将epoll作为I/O多路复用技术的实现,再加上Redis自身的事件处理模型将epoll中的连接、读写、关闭都转换为事件,不在网络I/O上浪费过多的时间。
-
优化的数据结构:Redis有诸多可以直接应用的优化数据结构的实现,应用层可以直接使用原生的数据结构提升性能。
-
使用底层模型不同:Redis直接自己构建了 VM (虚拟内存)机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
Redis的VM(虚拟内存)机制就是暂时把不经常访问的数据(冷数据)从内存交换到磁盘中,从而腾出宝贵的内存空间用于其它需要访问的数据(热数据)。通过VM功能可以实现冷热数据分离,使热数据仍在内存中、冷数据保存到磁盘。这样就可以避免因为内存不足而造成访问速度下降的问题。
Redis提高数据库容量的办法有两种:一种是可以将数据分割到多个RedisServer上;另一种是使用虚拟内存把那些不经常访问的数据交换到磁盘上。需要特别注意的是Redis并没有使用OS提供的Swap,而是自己实现。
3. Redis相比Memcached有哪些优势?
-
数据类型:Memcached所有的值均是简单的字符串,Redis支持更为丰富的数据类型,支持string(字符串),list(列表),Set(集合)、Sorted Set(有序集合)、Hash(哈希)等。
-
持久化:Redis支持数据落地持久化存储,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 memcache不支持数据持久存储 。
-
集群模式:Redis提供主从同步机制,以及 Cluster集群部署能力,能够提供高可用服务。Memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据
-
性能对比:Redis的速度比Memcached快很多。
-
网络IO模型:Redis使用单线程的多路 IO 复用模型,Memcached使用多线程的非阻塞IO模式。
-
Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。
这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。
4. 为什么要用 Redis 做缓存?
从高并发上来说:
- 直接操作缓存能够承受的请求是远远大于直接访问数据库的,所以我们可以考虑把数据