利用下班时间,我两星期完成了redis入门与进阶

.NET
252
0
0
2022-03-27

过去的两周,小松陆陆续续看完了一门长达十几个小时的课程 redis入门与精通。

当然,仅仅课程是不足以精通redis的,不过用来入门和窥见redis的全貌大有帮助,今天,小松就记录一下过去两周在redis上的学习心得。

基础

五大基本类型

key 这是最基础的,Redis是典型的键值对数据库,key可以通过runoobkey设置,如果设置成功就会返回OK,删除返回1。

redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> DEL runoobkey
(integer) 1

String 这是最基础的类型,相比起来,mysql的类型是真的多,光一个int都要好几种。 而redis由于是key-value结构,他的key基本都是使用的String,而value也大量使用,所以String使用非常频繁。 最简单的时候方式是set,get,当然,也支持各种对string的操作。

redis 127.0.0.1:6379> SET runoobkey redis
OK
redis 127.0.0.1:6379> GET runoobkey
"redis"

list list大家都不陌生,和数据结构一样,使用LPush命令在左边插入数据,RPush在右边插入数据。 类似的,有LPop,LTrim(截取),LRem(删除),LRANGE(查看)等操作,redis中字母不区分大小写。 这是在菜鸟教程中截取的例子。

127.0.0.1:6379>LPUSH list1 "foo"
(integer) 1
127.0.0.1:6379> LPUSH list1 "bar"
(integer) 2
127.0.0.1:6379> LRANGE list1 0 -1
1) "bar"
2) "foo"

set set也很简单,命令包括SAdd,SCard(查看元素个数),SRem,SUion(取并集),SInter(取交集)等。 比如b站里面的共同关注就是通过SInter获取。 一个账号的粉丝存储在一个Set中,两个账号就有两个Set,只要将两个Set进行SInter,就可以知道同时关注这两个账号的人了。

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"

hash 这就是java中的map或者python中的dict,在redis中,叫做hash,案例和上面类似,就不贴了,无外乎hset,hget,hmset(批量设置),hlen等。

进阶

持久化

持久化分为两种,持久化简单说就是要长期保存数据库,对于长期保存一样东西,思路就是要么保存过程,继而推导出结果,要么直接保存结果,所以这就是RDB和AOF。

RDB RDB的原理是,从父进程fork一个子进程,写入临时RDB,然后替换原来的快照,成为正式的RDB,在此期间,父进程,也就是原有的运行进程,正常运行

利用下班时间,我两星期完成了redis入门与进阶

所以他就是做了一个对结果的备份,放在一个后缀为rdb格式的文件中而已

当需要恢复的时候,将rdb放在redis的启动目录,这样,启动redis时,rdb同步写入redis,就完成了恢复,他有以下特点

优点: 1. 适合大规模数据恢复。 2. 适合备份数据库,作为后备兜底用途。 缺点: 1. 需要一定时间间隔进行操作,因为不能每时每刻都备份,比如每隔1小时备份,那么一旦宕机,就会损失一小时的数据。 2. fork进程消耗资源。

AOF AOF相比起RDB,是更加常用的方式。


利用下班时间,我两星期完成了redis入门与进阶

原理是将所有的命令记录下来,写入一个叫做appendonly.aof的文件中,当手动开启后,重启redis就会出现,很简单,而且由于保存的是步骤,而不是数据库本身,所以安全性高,他有三种同步方式,每一次修改都同步,每秒同步,从不同步,有以下特点:

优点: 1. 如果设置每一次修改都同步,很方便,不会有损失。 2. 如果设置每秒同步,最多丢失一秒数据。 3. 每次重启redis,优先载入aof恢复数据。

缺点: aof的体积大于Rdb文件,而且恢复也比较慢,这个好理解,记录了那些步骤都要重新执行一遍,自然比rdb直接备份的要慢一些。

所以,根据他们的原理和优缺点,我们很容易判断他们的使用范围。 如果是数据比较重要,但是可以承受损失,比如微博评论啥的,就用rdb吧。 如果需要更加安全,不能有损失,就用aof。 当然,两个都用于ok,aof用作平时的恢复,rdb用于紧急的兜底备份。

发布订阅

类似于微信公众号,信息消费者(subscriber)和信息生产者(Publisher )通过中间的channel进行连接,需要subscriber先订阅,然后Publisher 将信息推入到channel中,这里的channel本质上是一个键。 redis会维护一个字典,每个channel都是键,对应的值是一个链表,包含了所有的subscriber,所以当信息被推入channel中,信息就知道了他要去的地方,是那个链表,然后逐一分发下去。


利用下班时间,我两星期完成了redis入门与进阶

主从复制

鸡蛋不能放在一个篮子里面,凡是涉及到数据库的,都需要进行备份,只不过各家的方式不一样。 redis使用主从复制,一个最简单的模型是一主二从,使用三台电脑。

利用下班时间,我两星期完成了redis入门与进阶

先思考一下,我们需要解决哪些问题? 基础功能:

  1. 数据不能乱,读写要和一台机器一样。

方案:主机才有权力写,而从机只能从主机复制内容。

  1. 如果主机挂了,就能够及时变成主机。

方案:哨兵模式。

哨兵模式

我第一次接触哨兵模式,是在学习计算机系统的时候,所谓哨兵,相当于中世纪的教皇,而主机,是国王。 国王需要接受教皇的册封,才能成为真正的国王。

当主机挂掉的时候,哨兵将选择一个从机,让他成为主机,而且,即使原来的主机回来了,他也只能变成从机。 选择的方式,是投票。 哨兵不只一个,是奇数个,对于三个服务器,一主二从,这里三个哨兵比较合适,定时向主机发送消息监控,如果三个哨兵都无法收到主机的回包,大概率主机就挂掉了,此时哨兵进行投票,得票多的从机成为主机,如下图 sentinel为哨兵,slave为从机。

利用下班时间,我两星期完成了redis入门与进阶


投票是一种算法,这里不再深入。 而如何防止哨兵挂掉呢?这就是为什么哨兵不只一个的原因,多个哨兵也相互监督。

这样,这个模型如果不断扩大,除非大面积断电,不然即使有一些哨兵或者服务器挂掉了,也可以正常运行。

缓存雪崩

黑天鹅还是来了,大面积断电了! 此时,就是缓存雪崩,因为断电,Redis作为内存数据库,作为访问与数据库之间的中间缓存,将会彻底失效,此时 缓存称为雪崩。 方案在思路上没啥神奇的办法,只能异地容灾,或者提前预热,比如在11月10号模拟几亿订单量冲击淘宝系统,看看能不能抗住。

穿透

雪崩毕竟是天灾,我们无法改变,但是缓存穿透我们可以有所作为 穿透,就是缓存没起到作用,为什么没起到作用? 因为在缓存中没找到数据,比如说,用户找一个商品信息,但是缓存中找不到,所以会跳转到数据库中去找,而如果大量用户都来发起访问没找到的数据,数据库将会直接暴露,容易受到攻击,比如下图,如果一直是否,就会一直查询DB

利用下班时间,我两星期完成了redis入门与进阶

主流解决方法是使用过滤器,比如著名的布隆过滤器,筛选出容易造成穿透的访问信息,剔除掉即可,相当于给缓存打了一个补丁,除了过滤,还可以分流,降级等等,这些东西,和几千年前的大禹治水的思路一样,只是搬到了计算机上,毕竟,智慧,从古到今,都不会变,变的是使用场景。

击穿

穿透是找不到,击穿是受不了,假设缓存中有这个商品信息,但是由于访问过于频繁,使得缓存也受不了,就会崩掉,比如微博某明星谈恋爱就崩了,这应该是属于缓存击穿案例。 方案也不难,可以使用临界区,只要一部分在在访问,其他的就无法访问,这是一种互斥锁的方案,虽然并发少了,但是至少不会崩。