一文读懂Redis

Redis单线程,为什么这样设计?

问:是因为安全才这样设计吗?
答:一方面是安全,另一方面是避免多线程的锁机制,影响设计的复杂度,还有减少多线程上下文切换的时间。
问:单线程设计不是会影响速度吗?但是Redis的速度达到十万级别,这是为什么?
答:虽然单线程理论上没有多线程快,但是速度的根本原因是什么?内存是一部分原因,更主要的是IO。Redis技术选型上选择了IO多路复用技术,在读取内存的时候是异步操作的,不是IO阻塞的,无形中加快了数据的交互。
问:IO多路复用技术是用的什么技术实现的?
答:epoll,属于系统内核的一种优化技术,在我们设计其它工具时,可以参考Redis时采用的 。
问:Redis里的所有操作都是单线程的吗?
答:不是,涉及到Redis内部操作的时候,譬如,Redis在进行持久化数据的时候,会采用RDB或者AOF的时候,Redis会同时开辟一个线程去运行。可以说是对外是单线程,对外是多线程。

Redis接受什么样的数据类型?内部的存储采用什么数据结构?为什么这样设计?

问:什么样的数据类型可以存在Redis里面?
答:String,Hash类型数据,list,Set,有序Set
问:能存这些类型的数据,Redis是用什么样的数据类型来接收的呢?
答:SDS,字典,链表,跳跃表
问:SDS和String有什么区别?
答:SDS是动态字符串,关键的区别是SDS有一个len的设计,表示当前还有多少字符是可存的,这样设计就不需要频繁地进行内存的分配了;获取字符串长度的时候,一般会遍历字符串获取长度,但是SDS直接读取len就行了;修改字符串的时候,一般会需要重新分配字符串的内存空间,但是SDS不会去立马修改内存,假如是对字符串进行截取的话,多出来的内存空间一般会回收,但是SDS不会立马这样做,而是会将多出来的内存放在那里,是为了防止下次再对这个字符串进行操作,分配空间,但是如果一直没操作,SDS也是会回收这些内存的;假如是新增一个字符串的话,如果有10个字节,那么SDS会对其分配20个字节的空间,这样做的目的就是尽量避免重复分配空间,也就是,修改字符串长度N次最多要执行N次内存重分配。
问:Redis中的字典和HashMap是一样的东西吗?
答:不是,但是类型,HashMap是由一个链表和一个数组组成的+Hash算法获取的Hash值,但是字典是由两个数组组成的,且没有Hash值,只带了一个定值;
定值原因就是不需要进行Hash运算,又是一个优化速度的地方。
两个数组其实是为了扩容用的,而且扩容的机制和HashMap的也有很大的区别,HashMap是一次性创建出一个大的数组,把小的数组里面的值分配到大的数组里面,重新计算Hash值;
但是Redis是渐进式,一点点扩到第二个数组,完了之后再释放第一个数组。
问:扩容对应的是收缩,满足什么条件会收缩?
答:哈希表的负载因子小于0.1,负载因子是什么?
问:有序集合是用什么数据结构实现的?
答:跳表
问:Redis的通讯协议是什么?
答:RESF:REdis Serialization Protocal,redis序列化协议

Redis一般用于什么场景?这些场景是因为什么优点而选择Redis?

问:Redis的优点有很多,用于什么场景?
答:(1)缓存,因为内存操作;
	(2)分布式锁,因为是单线程;
	(3)登陆失效功能,Redis知名特性失效过期;
	(4)控制数据库的访问频次,限制 IP 在一段时间的最大访问量;
	(5)计数器(点赞数,收藏数),因为原子递增可以进行计数;
	(6)记录某些动作(记录该用户是否点过赞);
	(7)消息队列,list的特性:利用 LPUSH 命令将数据添加到链表头部,通过 BRPOP 命令将元素从链表尾部取出。

既然Redis是存储数据的,那么它的持久化机制是什么?

答:RDB和AOF,RDB是快照,AOF是命令;redis会优先AOF来备份数据。

分布式以及集群的情况下,Redis需要注意哪些?

Redis怎么部署需要根据具体的场景来设计
(1)单机版,只需部署一个Reids就行了
(2)哨兵,监控 redis 主从服务器,并在主服务器下线时自动进行故障转移
(3)集群

Redis的常见的命令对应的应用场景是什么?

1.1 存String的命令:set get
redis> SET key "value"
OK
redis> GET key
"value"
1.2 设置失效时间
redis> SET key-with-expire-time "hello" EX 10086
OK

redis> GET key-with-expire-time
"hello"

redis> TTL key-with-expire-time
(integer) 10069
1.3 计数
redis> SET page_view 20
OK

redis> INCR page_view
(integer) 21

redis> GET page_view    # 数字值在 Redis 中以字符串的形式保存
"21"
1.4 倒计时

对储存数字值的键 key 执行 DECR 命令:

redis> SET failure_times 10
OK

redis> DECR failure_times
(integer) 9

对不存在的键执行 DECR 命令:

redis> EXISTS count
(integer) 0

redis> DECR count
(integer) -1
2.1 设置一个Hash
当 HSET 命令在哈希表中新创建 field 域并成功为它设置值时, 命令返回 1 ; 如果域 field 已经存在于哈希表, 并且 HSET 命令成功使用新值覆盖了它的旧值, 那么命令返回 0 。

设置一个新的Hash:

redis> HSET website google "www.g.cn"
(integer) 1

redis> HGET website google
"www.g.cn"

修改一个已存在的Hash:

redis> HSET website google "www.google.com"
(integer) 0

redis> HGET website google
"www.google.com"

一个key可以有多个值-域:

redis> HMSET website google www.google.com yahoo www.yahoo.com
OK

redis> HGET website google
"www.google.com"

redis> HGET website yahoo
"www.yahoo.com"
3.1 将多个元素插入到list中(LPUSH和RPUSH一个是存在表头一个表尾)

加入单个元素

redis> LPUSH languages python
(integer) 1

加入重复元素

redis> LPUSH languages python
(integer) 2

redis> LRANGE languages 0 -1     # 列表允许重复元素
1) "python"
2) "python"

加入多个元素

redis> LPUSH mylist a b c
(integer) 3

redis> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"
4.1 记录网站每天访问的独立IP数量
基数就是指一个集合中不同值的数目,比如[a,b,c,d]的基数就是4,[a,b,c,d,a]的基数还是4,因为a重复了一个,不算。基数也可以称之为Distinct Value,简称DV。下文中可能有时候称呼为基数,有时候称之为DV,但都是同一个意思。HyperLogLog算法就是用来计算基数的。

将元素添加至 HyperLogLog:
返回给定 HyperLogLog 的基数估算值:

redis> PFADD  databases  "Redis"  "MongoDB"  "MySQL"
(integer) 1

返回给定 HyperLogLog 的基数估算值:

redis> PFCOUNT  databases
(integer) 3
5.1 查找附近的人;摇一摇:一个数组, 数组中的每个项表示一个范围之内的位置元素。
redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1

redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2

redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"

Redis与Mysql双写一致性方案解析

https://zhuanlan.zhihu.com/p/59167071
https://zhuanlan.zhihu.com/p/58360254a

Redis数据失效的回收策略

redis如何存数据到字典

问:键值对K0和V0添加到字典里面?
答:计算k0的哈希值
hash=dict->type->hashFuncion(k0),假如哈希值是8,下一步是计算索引:index=hash&dict->ht[].sizemask=8&3=0,索引值是0
将k0和v0放到哈希表数组的索引值为0的位置上
问:如果算出的索引值已经有东西了怎么办?(hash冲突)
答:用next指针作为单向链表,最新存的放在最前面

redis对数据的回收机制(内存回收)

问:类似于JVM的回收机制,redis使用什么技术实现的?
答:引用计数法,并且此方法还用于redis内部的内存共享上,一个值可以对应两个键,这个对象是k1k2v1,存共享只对整数值的字符串对象进行共享,因为,共享的话需要比较两者对象一样,整数值的字符串对象最简单,如果共享比较复杂的字符串或者一些复杂对象,单单去比较久很化CPU的时间,适得其反。redis只会共享0-9999整数值的字符串对象。
redis中的对象被访问会被记录下访问的时间,回收内存的时候,这也是判断依据,这叫空转时间。

reids在接受到命令的时候是怎么判断该条命令是否合法的?

服务器在执行某些命令之前,会先检查给定键的类型能否执行指定命令,而检查一个键的类型就是检查键的值对象的类型

redis如何实现分布式锁机制的?

答:先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:嗯,这小子还不错。

reids默认有几个数据库?什么时候用到切库的功能

答:默认有10个数据库,切库?todo

reids的过期删除策略

答:一共有3个,定时,惰性,定期删除
问:redis一把选择哪个策略?
答:一般是惰性+定期,反正各有优缺点,所以采用惰性+定期是最合理的。这边要结合雪崩的来理解,雪崩就是同一时间数据很多到期。

redis的命令请求内部逻辑是什么?

问:服务器从启动到开始能处理客户端的请求需要执行一些怎么样的初始化操作?
答:1,初始化服务器状态 2,载入服务器配置 3,初始化服务器数据结构 4,还原数据库状态 5,执行事件循环
问:redis一次请求,客户端和服务端整个过程?
答:1,客户端将命令发给服务端 2,服务器读取命令请求,并分析出命令参数 3,命令执行器根据参数查找命令的实现函数,然后执行实现函数并得出命令回复 4,服务器将命令回复返回给客户端。

redis中的文件事件和时间事件是什么?

redis的慢查询是什么意思?

答:慢查询日志用于记录执行时间超过指定时长的命令,其实一样也很单一?!

猜你喜欢

转载自blog.csdn.net/qq_34707991/article/details/88770221