Browse Source

finished the first instroduction

master
jingxun 2 years ago
parent
commit
d7a81c83cc
  1. 357
      cp1/introduction.md

357
cp1/introduction.md

@ -0,0 +1,357 @@
# `Redis`基本介绍
哈喽,我们这节课开始介绍一下关于`redis`的内容,为啥要学这个呢,咱也不说虚的,那些很多说为了让自己技术更全面,为了让自己更优秀,为了让自己效率更高,都是狗屁,我学习一门技术的理由很简单,只是为了找工作时或者在职场上能少一个被直接淘汰的理由。
## 概述
那么既然我们学习`redis`,又到了最开始那个千篇一律的问题了,`redis`是个什么东西?说实话我已经不喜欢回答这种问题了,他爱是什么东西是什么东西,他是什么东西你真的感兴趣吗?你真的关心吗?你真的在乎吗?不,你在乎的只有你自己。
所以说我也懒得说这个是什么东西,反正就是一种技术产物。而这种技术我们称之为`NoSQL`。
可能又有人要问,`NoSQL`又是什么呀?这是为了解决性能问题而产生的一种技术。现在告诉你了,你学会了吗?知道怎么用吗?你说你闲得那么好奇干什么啊?知道这个玩意儿是什么有什么用啊?以后这些类似的事少打听。
## 背景
行了,那么我们看看为什么会有这种技术吧。
在最初的时候,也就是所谓的`web 1.0`时代,一个简单的`web`项目架构也是很简单。
$$
PC\ 端\ \Leftrightarrow\ web\ 服务器\ \Leftrightarrow\ 数据库服务器
$$
那个时候吧车马很慢,网速比车马还要慢,但是渐渐到了所谓的`web 2.0`时代,随着网络技术的发展,智能手机的普及,`3G`,`4G`的到来,网速也提升了,渐渐的`web`服务器的吞吐量也就大了起来。那么如果还是用之前的架构会怎么样呢?
$$
\boxed{\begin{matrix}
PC\ 端\\\\
移动端
\end{matrix}}\
\Leftrightarrow\ web\ 服务器\ \Leftrightarrow\ 数据库服务器 \\\\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \Downarrow\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \Downarrow \\\\
\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ CPU\ 压力\ \ \ \ \ \ \ \ \ \ \ \ \ \ IO\ 压力
$$
如果在大量访问量的情况下,依然使用旧的架构就会对`web`服务器造成`CUP`压力,对数据库服务器也会造成很严重的`IO`压力。
## 解决`CUP`压力
面对老旧架构逐渐无法满足市场需求,就好像火车站排队买票,如果说只有一个售票口的话,那么售票压力就会很大,可能会存在很多人还没来得及买到票,他想买的那个班次就已经开走了。但是活人还能让尿憋死?首先我们来解决一下`CPU`压力,现在市面上最主流的方式便是服务器集群。简单的来说就是用反向代理服务器配上负载均衡:
$$
\boxed{\begin{matrix}
PC\ 端\\\\
移动端
\end{matrix}}\
\Leftrightarrow\
\overset{负载均衡分发请求}{\boxed{\begin{matrix}
代理服务器\\\\
\ \ 负载均衡\ \
\end{matrix}}}\
\Leftrightarrow\
\overset{服务器集群}{\boxed{\begin{matrix}
服务器\ 1\\\\
服务器\ 2\\\\
\ \ \vdots\\\\
服务器\ n
\end{matrix}}}\
\Leftrightarrow\ 数据库服务器
$$
像上面这种架构的话当我们利用负载均衡将所有的请求都分发给服务器集群中的各个服务器,这就好比还是火车站排队买票,我们这次开放 10 个售票口,那么售票压力就会减小很多。
但是虽然解决了服务器`CUP`压力,又出了新的问题。学习过前端的都知道,就是`session`问题,因为`session`是存储在服务器上的。那么就会出现什么情况呢,第一次用户登录时,请求被分发到了服务器 1,那么`session`就会存储在服务器 1 上面的。那么第二次再访问这个网站的时候,负载均衡不一定可以将这请求依旧分发给服务器 1。那么这下就没法在服务器上面获取到`session`。
就好比大学城里有 5 个健身房,大学城的学生太多了,因为第一个健身房人少,所以你去了第一个健身房,然后办了卡。第二天你再去健身房,发现只有第二个健身房人少,那么你去第二个健身房肯定是没有办法查询到你的会员记录的。
可是这个问题又应该怎么解决呢?
## 解决`session`问题
其实解决`session`问题是有很多方法的。
比如我们可以将`session`存储在`cookies`中,每次发送请求的话,可以直接通过`cookies`携带用户信息去请求服务器。但`cookies`是存储在浏览器中的。所以说安全性就会比较低了,如果有其他人在电脑上获取到了用户信息,那么这将是一件很危险的事。
就好像有人拿到了你的银行卡,密码和身份证一样,那问题可就严重了诶,这样别人就会知道你居然这么穷,多可怕。
那么我们可以不存在`cookies`中,我们依然将`session`存储在服务器端,那么我们把`session`复制下来在每个服务器都存一份,就好像你在每个健身房都办一张卡,那么不管你去哪个健身房都有会员。
但是这样的话又有一个新的问题`session`数据冗余,造成了大量空间资源浪费。好比你办了那么多健身房的会员卡,那么你指什么吃啊?钱都拿去办卡了,你吃什么?你办了卡又不一定会去健身房,只能慢慢等卡过期,那么你的钱是不是都被你给浪费了?
当然了,我们可以选择将`session`存储在数据库中,或者存储在文件服务器中。那这样的话就不会造成数据冗余了啊。这就有点类似于连锁店,你办了卡,所有分店都能用。
但是呢这个方案是要操作`IO`的,所以会出现`IO`效率问题。这个在我们现实生活中的连锁店中可是没有出现过。
那么我们最终还是来到了这一步。那就是存储在`NoSQL`数据库中。
$$
\boxed{\begin{matrix}
PC\ 端\\\\
移动端
\end{matrix}}\
\Leftrightarrow\
\overset{负载均衡分发请求}{\boxed{\begin{matrix}
代理服务器\\\\
\ \ 负载均衡\ \
\end{matrix}}}\
\Leftrightarrow\
\overset{服务器集群}{\boxed{\begin{matrix}
服务器\ 1\\\\
服务器\ 2\\\\
\ \ \vdots\\\\
服务器\ n
\end{matrix}}}\
\left.\begin{matrix}
\Leftrightarrow\ \boxed{NoSQL数据库}\\\\
\Leftrightarrow\ \boxed{\ \ 数据库服务器\ \ }
\end{matrix}\right.
$$
这种架构看着没有什么问题,但是为什么用`NoSQL`数据库就不会出现`IO`效率问题呢?因为`NoSQL`数据库是将数据存储在内存中的,数据查询并不需要交互`IO`,这样的话速度快,而且数据结构简单,就可以解决掉性能问题,而没有什么明显的弊端。
## 解决数据库`IO`问题
通常我们日常开发中用的数据库基本上都是关系型数据库居多,比如`MySQL`,`Oracle`,`db2`等,但是这些数据库是将数据存储在磁盘中的,在进行操作的时候都要进行`IO`的交互,当数据量小的时候我们进行`IO`交互是没有问题的,效率也很高。
但是随着项目的发展,用户的增多,数据量也会越来越大,那么在这个时候我们再操作数据库与`IO`进行交互的话就会很明显地感觉到效率降低了。那么我们该怎么做呢,通常来说我们会选择将库还有表来进行拆分,这样的话是可以解决`IO`压力的,但是这个方法也是有弊端的,拆分库和表,注定就会要牺牲掉一部分的业务逻辑。
当然除了这个方法我们也可以将表根据具体业务逻辑选择行存储或者列存储。那么是什么意思呢?比如说:
| `id` | `name` | `age` | `gender` | `phone` |
| :--: | :----: | :---: | :------: | :---------: |
| 1 | 张三 | 20 | 男 | 15900000000 |
| 2 | 李四 | 21 | 男 | 15811111111 |
| 3 | 王五 | 22 | 男 | 15722222222 |
想这样一张表,这是一个很常见的关系型数据库的表。所谓的行存储就我们以每一行的数据作为一个存储单元,像传统的关系型数据库,例如`MySQL`,`Oracle`等等基本都是行存储
$$
\boxed{\begin{matrix}
\boxed{1\ |\ 张三\ |\ 20\ |\ 男\ |\ 15900000000} \\\\
\boxed{2\ |\ 李四\ |\ 21\ |\ 男\ |\ 15811111111} \\\\
\boxed{3\ |\ 王五\ |\ 22\ |\ 男\ |\ 15722222222}
\end{matrix}}
$$
就好像是这种架构,一张表里,每一行是一个单位,这样做的优势就是在查询的时候可以随机查询。我可以快速通过`id`字段来查询到`id`为 2 的数据。但是这个架构的弊端就是当数据量很大的时候,比如表里有 100 万条数据,那么我们想要计算这 100 万条数据的平均年龄,那么我们再来查询,效率就很很低。
随着大数据时代的到来,`Hbase`,`EMC Greenplum`等数据库渐渐兴起,这些都是列存储的数据库,这些就是将上面的表中每一列作为一个存储单元。
$$
\boxed{\begin{matrix}
\boxed{\begin{matrix}
1 \\\\ 2 \\\\ 3
\end{matrix}} &
\boxed{\begin{matrix}
张三 \\\\ 李四 \\\\ 王五
\end{matrix}} &
\boxed{\begin{matrix}
20 \\\\ 21 \\\\ 22
\end{matrix}} &
\boxed{\begin{matrix}
男 \\\\ 男 \\\\ 男
\end{matrix}} &
\boxed{\begin{matrix}
15900000000 \\\\ 15811111111 \\\\ 15722222222
\end{matrix}}
\end{matrix}}
$$
就是上面这种架构,这种架构的好处就是我们可以快速取出一列数据,这样我们想查询平均年龄,职级将这一列取出进行计算就好了,这样的优点在于可以快速取出一列数据来进行计算,但是我们如果想要通过`id`来查询出`id`为 2 的这一行数据,效率就会很低。
所以说行存储和列存储,可以根据具体的业务逻辑来具体选择,从而来减轻`IO`的压力。
但是行存储和列存储终究还是太麻烦了,有没有其他的方案了呢?当然还是有的,我们可以用`NoSQL`做缓存数据库
$$
\boxed{\begin{matrix}
PC\ 端\\\\
移动端
\end{matrix}}\
=\Rightarrow\
\overset{负载均衡分发请求}{\boxed{\begin{matrix}
代理服务器\\\\
\ \ 负载均衡\ \
\end{matrix}}}\
=\Rightarrow\
\overset{服务器集群}{\boxed{\begin{matrix}
服务器\ 1\\\\
服务器\ 2\\\\
服务器\ 3\\\\
\ \vdots\\\\
服务器\ n
\end{matrix}}}\
\left.\begin{matrix}
\Leftrightarrow\ \boxed{\ \ \ \ NoSQL数据库\ \ \ \ }\\\\\\\\
\Leftrightarrow\ \boxed{\ \ \ \ \ 数据库服务器\ \ \ \ \ } \\\\
\ \ \ \ \ \ \ \ \ \Updownarrow \\\\
\Leftrightarrow\ \boxed{NoSQL缓存数据库}
\end{matrix}\right.
$$
我们这样,将一些高频查询的数据存储在`NoSQL`中,用`NoSQL`数据库来作为网站的缓存,这样的话即便有大量的用户,大量的数据,大量的请求,我们也可以通过缓存数据库来降低数据库服务器的`IO`压力。
## `NoSQL`
那么说了这么多了,我们好像并不怎么了解`NoSQL`,因为我让你们少打听。但是我会在合适的时候告诉你应该告诉你的对象。比如我现在会告诉你,`NoSQL`是一种非关系型数据库,不依赖业务逻辑,以简单的`key-value`的模式存储,大大提高了数据库的扩展能力。
那么什么是所谓的`key-value`存储模式呢?举个例子,大家在公司都有自己的工号,在公司的信息系统中,只要输入你的工号,就会查询出你的员工信息,而这个工号就是`key`,而员工信息就是`value`,每个人的工号和其员工信息是一一对应的。`key-value`模式也是这样,一个`key`只对应一个`value`,我们可以通过`key`来得到与之对应的`value`。
那么`NoSQL`还有什么特点呢?
首先`NoSQL`不遵循`SQL`的标准,我们用`SQL`来操作数据库的话要用复杂的`SQL`语句来完成一系列操作。但是`NoSQL`不用,`NoSQL`只需要用相应的命令就可以了。仿佛似面向过程与面向对象的区别。
另外`NoSQL`不支持事务的原子性,一致性,持久性和隔离性,这个暂时不做过多介绍,在后续的学习中大家慢慢去体会。至于对这四个特性不了解的朋友,大家可以去认真查阅关系型数据库的的事务相关的资料。
最后一个特点也是我们最重要的,就是`NoSQL`的性能远超`SQL`,不然的话我们引入`NoSQL`就没有意义了。但是为什么呢?因为`NoSQL`的数据是存储在内存中的。计算机对内存的读写操作可是远超对硬盘的读写操作的。所以说`NoSQL`的性能要远超`SQL`的
## `NoSQL`的适用性
那么我们介绍了`NoSQL`了。知道这个对象是用来解决性能问题的,那么我们还要用关系型数据库干什么?直接都用`NoSQL`不就得了嘛,其实并不是我们想当然的这样。`NoSQL`也是有自己的适用场景的。
就好像我们要进行数据高并发的读写的话,比如电商秒杀啊,12306 春运抢票啊,再比如大数据海量数据的读写啊,或咋要求数据库有高扩展性啊,这种都可以使用`NoSQL`。
但是如果我们想要利用数据库的事务,以及即席查询的话,那么`NoSQL`就不太适用了,倒不是说`NoSQL`不支持事务,`NoSQL`是不支持事务的四大特性。当我们需要事务支持的话通常还是会选用关系型数据库的。至于什么是即席查询。简单来说就是自定义性和灵活性都很强的查询就叫即席查询。
所以说我们是要根据相应的业务场景来定是否使用`NoSQL`。
## `redis`简介与安装
首先来说`redis`是`NoSQL`数据库的一种,目前来说在市面上其实是非常活的,最常用的`NoSQL`数据库中`redis`算是排在前几名的。在`redis`之前,大家用一个叫做`MemCache`的`NoSQL`数据库,但这个数据库有一个缺点,就是不支持把数据持久化到硬盘中去,只能存在内存里,那么万一服务器一关机,那么数据就都丢了啊。
后来`redis`出现了,`redis`几乎涵盖了`memcache`所有功能,最关键的一点,`redis`支持将数据持久化到硬盘中去。
那么`redis`都有什么特点呢?
首先和所有`NoSQL`数据库一样,数据存储在内存中,而且是`key-value`模式。而且`redis`的数据都是原子性的,而且都支持`push/pop`、`add/remove`以及取交集并集等丰富的操作,另外`redis`还支持不同方式的排序,支持将数据持久化到硬盘中,而且`redis`还会周期性地自动将数据写入硬盘,`redis`还有一个特点就是实现了主从同步,至于这个是什么,后期的学习中会慢慢介绍。
除此之外,`redis`采用的是单线程 + 多路`IO`复用的技术从而来实现类似于多线程的操作。什么意思呢?
比如你去买周杰伦演唱会门票,但是你觉得你肯定买不到啊,那么火哪是那么容易买的啊,那么你就去找黄牛买票。你就去找了一个黄牛帮你买票,因为你只找了一个黄牛,那么这个就是所谓的单线程,但是这个黄牛并不是只接了你一个人的单子啊,也许他还接了张三买德云社演出票的单子,又接了李四买脱口秀大会演出票的单子。但是你们让黄牛帮忙买票了,黄牛就一定能买到吗?是不是不一定啊?但是在他买到票之前,你们总不至于一直陪着黄牛在哪等吧,你们肯定还是该干嘛干嘛去,等黄牛买到票了,再来通知你们。这就是所谓的多路`IO`复用,单线程做多件事,但是事情完成之前有不影响其他的事情,从而实现类似于多线程的效果。
## 安装`redis`
我们介绍完了`redis`的特点之后,那么我们准备学习吧,在学习这个数据库之前,我们要做的就是先安装这个数据库,通常来说`redis`我们都在`Linux`系统上安装的比较多,所以我们也就只介绍`Linux`环境下安装`redis`。
其实很简单,直接用包管理工具也就可以了,拿`CentOS`系统为例,首先执行命令添加`EPEL`仓库
```shell
sudo yum install epel-release
sudo yum update
```
添加完仓库之后更新源,然后执行命令
```shell
sudo yum install redis
```
然后就等待安装完成就可以了。
## 启动`redis`与简单使用
`Linux`系统启动`redis`也是很简单的,我们通常都以服务的方式来启动`redis`
```shell
sudo systemctl start redis
```
我们可以方便快捷地使用`systemctl`工具来进行服务的管理。
启动了`redis`服务之后,我们通过`redis-cli`命令来进入`redis`交互界面。
![image-20220422114132707](https://file.lynchow.com/2022-04-22-034135.png)
我们看当我输入了`redis-cli`然后敲下回车就会进入一个新的交互界面,在这个界面就可以通过`redis`的命令来对`redis`进行操作
比如我们先来测试一下连通性,执行命令`ping`
![image-20220422131120747](https://file.lynchow.com/2022-04-22-051122.png)
我们执行了`ping`命令之后,如果像图中那样输出了`PONG`,那么说明我们已经连接成功了。可能有人要问了,还会有进入交互界面但是连接不成功的情况吗?当然有:
![image-20220422131900609](https://file.lynchow.com/2022-04-22-051905.png)
我们来看上面这张图,我们第一次`ping`的时候就报错了,说明没连接成功,然后我们执行了`auth`命令之后再`ping`就成功了,这是为什么呢?因为我本地的`redis`设置了密码,`auth`后面我打了马赛克的那一段就是密码,只有我验证了密码之后才能成功连接上数据库。至于怎么给`redis`设置密码,我们后面会介绍。
那么我们现在安装好了`redis`,也学会了启动`redis`,也知道怎么在命令行里面连接`redis`了,那么我们来说几个基础知识点:
第一,`redis`的默认端口号是 6379,没有为什么,记住就行了,知道为什么也没有意义。而且我们后续会介绍如何修改`redis`占用的端口号,只需要知道默认端口号是 6379 就行了
第二,`redis`默认提供 16 个数据库,和数组的索引类似,这 16 个库的编号从 0 开始,当我们连接上`redis`时默认使用的是 0 号数据库。
第三,我们可以通过`select`命令加数据库编号来切换数据库,命令不需要区分大小写
![image-20220422134007633](https://file.lynchow.com/2022-04-22-054009.png)
我们从图上可以看到,一旦我们切换了数据库就会显示数据库的编号,但是切换回默认数据库的话则会省略数据库编号。
这两个知识点就作为一个常识来了解就好,并不用去深究,`redis`是`NoSQL`数据库,`NoSQL`的存储方式是`key-value`,而我们都是通过`key`来关联到`value`,那么直白地来看,`NoSQL`就是对`key`来玩一些花样啊。没错,那么我们来看看`key`都有哪些基础的花样可以玩:
首先,`keys *`命令,这个命令是用来查看当前库都有哪些`key`:
![image-20220422134316997](https://file.lynchow.com/2022-04-22-054318.png)
这个是我的一个`web`项目存进来的缓存,我先把这些给清掉
![image-20220422134441230](https://file.lynchow.com/2022-04-22-054443.png)
清掉之后我们看见当前库里面是空的,一个`key`都没有。那么我们就可以引出新的命令了:
`set`命令,这个命令是向库里添加一个`key`:
![image-20220422134659226](https://file.lynchow.com/2022-04-22-054701.png)
我们来看上面这张图,我们`set`命令有两个必须传入的参数,用空格隔开,第一个参数就是`key`的名称,随便取,另一个是`value`的值,这个值可以是`redis`所支持的数据类型的任何一种。至于数据类型我们后续的学习中会介绍。那么我们执行的命令`set key1 value1`做了什么呢?其实就是想当前库里添加一个叫做`key1`的`key`,而这个`key`对应的`value`值是`value1`。现在我们再执行`keys *`,就会看见库里现在有一个叫`key1`的`key`。
既然我们能添加`key`,自然少不了删改这个`key`,众所周知,对数据库的操作无非就是增删改查这四个字,我们可以用`set`增,那么改呢?其实改也是`set`:
![image-20220422135334557](https://file.lynchow.com/2022-04-22-055336.png)
就如同图中一样,直接用`set`命令重新新增`key1`,这个时候并不会在库里新增一个新的`key1`,而是用这次`set`的`value`覆盖掉库里原有的`key1`所对应的值,那么我们怎么验证呢?这就要提到对数据库的查询操作了,怎么查呢?
与`set`对应的就是`get`,没错,我们可以用`get`命令加上`key`的名称来查看指定的`key`对应的`value`:
![image-20220422135723880](https://file.lynchow.com/2022-04-22-055725.png)
我们从图中可以看见第一次我们`get key1`获取到的`value`的值是`value1`,然后我们重新`set`了`key1`,再来执行`get key1`得到的就是第二是重新`set`时候的`value`的值
那么到这一步`redis`的增改查都介绍完了,那么怎么删呢?这样我们就引出了`del`命令和`unlink`命令,这两个命令都可以删除一个`key`,比如我们先用`del`:
![image-20220422140058959](https://file.lynchow.com/2022-04-22-060100.png)
我们看见执行完`del`命令之后,库里已经没有任何`key`了,但是执行`del`命令的时候输出了一个数字 1 是什么意思呢?我们都知道计算机是二进制的,只有 0 和 1,那么 0 和 1 所能表示的东西就多了,但是其中最常见的之一就是用 1 表示成功,用 0 表示失败。我们现在已经清空了当前库了,库里也没有`key`了,那么我这个时候再执行`del`命令,按照我们刚才的逻辑是不是应该输出 0 才对?因为没有`key`了,那么不可能删除成功的,所以按照逻辑上来说应该输出 0,那么我们来验证一下:
![image-20220422140549919](https://file.lynchow.com/2022-04-22-060551.png)
果然如我们预期一样,我们输出的是 0。所以说执行`del`命令输出的数字代表着这个`key`是否成功删除。那么我们再来看看`unlink`命令:
![image-20220422140740959](https://file.lynchow.com/2022-04-22-060742.png)
我们先是新增一个`key`,然后用`unlink`命令删除,我们看见,执行`unlink`命令输出的也是数字 1,和`del`命令一样,这个数字也代表是否成功删除了。
但是`del`命令和`unlink`命令有什么区别呢?其中`del`命令是直接删除,而`unlink`命令只是将`key`从`keyspace`里面 删除,但是数据实际上并没有删除,而`unlink`真正删除数据的步骤实在后续的异步任务中操作的。当然这个问题我们后续会详细介绍,这里就不再赘述了。
当然了,我们说完了增删改查,还有其他的命令要说,比如`exists`命令,这个命令可以用来判断某个`key`是不是存在于当前的库:
![image-20220422141449018](https://file.lynchow.com/2022-04-22-061450.png)
我们`set`一个新的`key`,我们看见,当前的库里面只有这一个`key`,那么我们执行`exists`命令,输出的也是数字来表示是否存在。
另外还有`type`命令,从命令字面意思上就可以看出,这是个查询类型的命令`type`命令后面跟`key`的名称,这里不在赘述了。
另外还有两个命令`expire`和`ttl`命令这两个命令一个是给`key`设定过期时间,另一个是查询`key`还有多长时间过期,时间以秒为单位。
![image-20220422145022672](https://file.lynchow.com/2022-04-22-065024.png)
我们`set`两个`key`,其中`key1`我们设置 20 秒的过期时间,`key2`不设置过期时间,也就代表`key2`永不过期。我们看,`expire`输出也是数字,代表设置是否成功。然后用`ttl`命令查询`key1`还剩多少时间过去,输出了 15,说明还剩 15 秒就会过期。然后我们又用`ttl`命令查了一下`key`到底过期时间,输出是 -1,但是大家想也知道在我们这个宇宙和维度中,时间是不可能有负数的,那么这里的 -1 肯定有别的意思,没错,这里的 -1 代表的是永不过期。等时间差不多了,`key1`应该已经过期了,再用`ttl`命令来查一下`key1`的过期时间,输出了 -2,那么这里的 -2 又代表什么呢?这里的 -2 就代表已经过期了。
## 总结
以上便是这节课的内容,我们来简单做一个总结:
- `NoSQL`是一种为了解决性能问题而诞生的技术
- `NoSQL`可以解决服务器集群的`session`问题
- `NoSQL`可以做缓存数据库来缓解数据库服务器的`IO`压力
- `NoSQL`采用的是`key-value`的存储模式,不遵循`SQL`标准,不支持事务四大特性,数据存储在内存中,性能远超`SQL`
- `redis`采用单线程 + 多路`IO`复用实现类似多线程的效果
- `redis`实现了主从同步
Loading…
Cancel
Save