redis深度理论

1.关系型数据库

建表:必须给出schema
类型:字节宽度
存:倾向于行级存储

2.数据库表很大,性能下降怎么办

如果表有索引:

增删改查变慢;

查询速度

1.1个或者少量的查询依然很快
2.并发大的时候会受到硬盘带宽影响速度

3.memcached和redis 的不同

相同:都是key---value的形式
不同:memcached没有类型的概念,redis有类型的区分

4.为什么 Redis 中要使用 I/O 多路复用这种技术

首先,Redis 是跑在单线程中的,所有的操作都是按照顺序线性执行的,但是由于读写操作等待用户输入或输出都是阻塞的,所以 I/O 操作在一般情况下往往不能直接返回,这会导致某一文件的 I/O 阻塞导致整个进程无法对其它客户提供服务,而 I/O 多路复用就是为了解决这个问题而出现的

5. redis的io模型

1.epoll(默认主要)

2.select/poll

3.kqueue

6. epoll有诸多优点

  1. epoll 没有最大并发连接的限制,上限是最大可以打开文件的数目,这个数字一般远大于 2048,
    一般来说这个数目和系统内存关系很大
    ,具体数目可以 cat /proc/sys/fs/file-max 察看。

  2. 效率提升, Epoll 最大的优点就在于它
    只管你“活跃”的连接
    ,而跟连接总数无关,因此在实际的网络环境中, Epoll 的效率就会远远高于 select 和 poll 。

  3. 内存拷贝, Epoll 在这点上使用了“
    共享内存
    ”,这个内存拷贝也省略了。

7.多路复用I/O(Multiplexing I/O)

  1. select:能打开的文件描述符个数有限(最多1024个),如果有1k请求,用户进程每次要把1k个文件描述符发送给内核,内核在内部轮询后将可读描述符返回,用户进程再依次读取。因为文件描述符(fd)相关数据需要在用户态和内核态之间拷来拷去,所以性能还是比较低;
  2. poll:可打开的文件描述符数量提高,因为用链表存储,但性能仍然不够,和select一样数据需要在用户态和内核态拷来拷去;
    3. epoll(Linux下多为技术):用户态和内核态之间不用文件描述符(fd)的拷贝,而是通过mmap技术实现开辟共享空间,所有fd用红黑树存储,有返回结果的fd放在链接中,用户进程通过链表读取返回结果,伪异步I/O,性能较高。epoll分为水平触发和边缘触发这两种模式,ET是边缘触发,LT是水平触发,一个表示只有在变化的边际触发,一个表示在某个阶段都会触发;

8.epoll给我们提供了3个api

1: int epoll_create(int size);

生成一个 epoll 专用的文件描述符,其实是申请一个内核空间,用来存放你想关注的 socket fd 上是否发生以及发生了什么事件。 size 就是你在这个 epoll fd 上能关注的最大 socket fd 数,大小自定,只要内存足够。

2: int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event );

控制某个 epoll 文件描述符上的事件:注册、修改、删除。参数说明:

epfd 是 epoll_create() 创建 epoll 专用的文件描述符。相对于 select 模型中的 FD_SET 和 FD_CLR 宏;

op就是你要把当前这个套接口fd如何设置到epfd上边去,一般由epoll提供的三个宏指定:EPOLL_CTL_ADD,EPOLL_CTL_DEL,EPOLL_CTL_MOD。

fd: 当事件发生时操作的目标套接口。

event指针就是你要给这个套接口fd绑定什么事件。

3: int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);

等待 I/O 事件的发生;参数说明:

epfd: 由 epoll_create() 生成的 Epoll 专用的文件描述符;

epoll_event: 用于回传代处理事件的数组;

maxevents: 返回的最大事件数;

timeout: 等待 I/O 事件发生的超时值(毫秒);

epoll_wait返回触发的事件数。

9.epoll的LT和ET模式的区别

LT模式:epoll就是一个快速版poll,可读可写就绪条件和传统poll一致
ET模式:为了避免Starvation,建议
1)文件描述符设置为非阻塞
2)只在read或write返回EAGAIN后,才能调用下一次epoll_wait
3)应用层维护一个就绪链表,进行轮询,可以防止大量IO时在一个描述符上长期read或write(因为只有等到read
或 write返回EAGAIN后才表示该描述符处理完毕)而令其它描述符starve

  理解ET的含义后,上面那些操作其实都是显然的。以wirte为例说明,LT时只要有一定范围的空闲写缓存区,每次epoll_wait都是可写条件就 绪,但是ET时从第一次可写就绪后,epoll_wait不再得到该描述符可写就绪通知直到程序使描述符变为非可写就绪(比如write收到 EAGAIN)后,epoll_wait才可能继续收到可写就绪通知(比如有空闲可写缓存)
  其实ET相对于LT来说,把文件描述符状态跟踪的部分责任由内核空间推到用户空间,内核只关心状态切换即从未就绪到就绪切换时才通知用户,至于保持就绪 状态的,内核不再通知用户,这样在实现非阻塞模型时更方便,不需要每次操作都先查看文件描述符状态。上述多数内容取自man epoll

10.redis 持久化 RDB

RDB使用的是:fork(系统调用)和copy on write(内核机制)

RDB会要是用fork()创建一个子进程,子进程记录的是创建时间节点的数据。

copy on write: 写时复制

在fork子进程的时候,只拷贝指针,并不发生内存的复制。
只有当其中的某一个进程试图对该区域进行写操作时,内核就会在物理存储器中为子进程开辟一个新的物理页面,将需要写的区域将父进程的内容复制一份给子进程,然后对新的物理页面进行写操作。
这时就是实现了对不同进程的操作而不会产生影响其他的进程,同时也节省了很多的物理存储器。
并且根据经验来看,不可能父子进程将所有数据都改一遍。下图redis也用了这个机制,而且redis的子进程不会去修改数据:

11.快照(RDB)保存过程:

  1. redis调用fork,现在有了子进程和父进程。
  2. 父进程继续处理client请求,子进程负责将内存内容写入到临时文件。由于os的写时复制机制(copy on write)父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的页面创建副本,而不是写共享的页面。所以子进程的地址空间内的数据是fork时刻整个数据库的一个快照。
  3. 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出(fork一个进程入内在也被复制了,即内存会是原来的两倍)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值