zoukankan      html  css  js  c++  java
  • 2----------原理篇

    Redis事单个线程程序

    Nginx也是单线程,但是他们都是服务器高性能的典范

    redis为什么这么快?

    所有数据都在内存中,所有的运算都是内存级别的运算

    Redis既然是单线程,如何能处理那么多的并发客户连接?

    多路复用

    非阻塞IO

    当我们调用套接字(socket网络编程)默认是阻塞的;

    阻塞:非要读到数据才返回,非要写完才返回

    非阻塞IO:在套接字对象上提供一个选项Non_Blocking,当这个选项打开时,读写方法不会阻塞,而是能读多少度多少,能写多少写多少。

    1. 能读多少:取决于内核为套接字分配的读缓冲区内部的数据字节数
    2. 能写多少:取决于内核为套接字分配写缓冲区的空闲空间字节数
    3. 返回值高数程序实际读写了多少字节

    事件轮询(多路复用)

    简单的轮询API是select函数,操作系统提供给用户程序的API。来一个处理一个,来了事件就立即返回,死循环。-----不是很懂,大概跟底层相关吧。

    指令队列

    Redis会将每个客户端套接字都关联一个指令队列。客户端的指令通过队列来排队进行顺序处理,先到先服务。

    相应队列

    Redis为每一个客户端套接字关联一个响应队列。rRedis服务器通过响应队列来讲指令的返回结果回复给客户端。

    定时任务

    假如线程阻塞在select系统调用上,定时任务无法准时调度怎么办

    定时任务记录在一个最小堆的数据结构中。快执行的任务放在堆的最上方。

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    通信协议

    RESP

    Redis序列化协议------文本协议

    就是将客户端发送给服务器的指令按照一定的规则转换为文档;服务器将返回结果经过编码发送回来。说白了就是序列化协议。

    持久化

    Redis的数据全部在内存里,突然宕机,数据就会全部丢失,因此需要一种机制来保证Redis的数据不会因为故障而丢失,这个叫作Redis的持久化。

    持久化方式:

    1. 快照
    2. AOF日志

    快照原理

    原理:将内存数据的二进制序列化,然后复制一份到文件中

    简单的:fork一个子进程,将此时的内存数据复制一份在内存中,然后进行快照。

    那么产生的问题就是:在复制完成的过程中,内存发生的数据改变是无法感知的。跟CopyOnWriteList一摸一样

    AOF日志

    记录指令,恢复Redis时需要进行重放这些指令,很慢。

    Redis每次执行指令结束之后,执行完的指令再放入日志存盘。

    所以:这个日志会越来越长,而且恢复会很耗时,导致Redis长时间无法对外提供服务,所以需要AOF定期瘦身

    ------Redis提供了bgrewriteaof指令用来给AOF文件日志瘦身

    fsync

    保证机器宕机的时候,也保证指令的不丢失

    运维

    通常Redis的主节点不会进行持久化操作,持久化操作主要在从节点进行,从节点是备份节点,没有来自客户端请求的压力,它的操作系统资源往往比较充沛。

    混合持久化

    前半段用快照,后半段用最新的AOF文件

    管道

    就是将连续的几个任务请求一起发送过去,然后结果一起发送过来。是客户端提供的功能,其实没东西的

    事务

    Redis对应的事务指令为:multi、exec、discard。

    multi
    
    incr books
    
    incr books
    
    exec

    所有指令在exec之前不执行,而是缓存在服务器的一个事务队列中,服务器一旦收到exec指令,才开始执行整个事务队列,执行完毕后一次性返回所有指令的运行结果。

    注意:假如事务的中间有一条指令出错,那么后续的还是能执行的。所以说redis并不能保证原子性。

    discard 丢弃

    跟exec是对立的

    优化

    Redis事务在发送每个指令到事务缓存队列时都要经历一次网络读写,当一个事务内部的指令较多时,需要的网络IO就会变长,所以通常Redis的客户端在执行事务时都会结合管道一起使用。

    watch

    乐观锁

    watch books
    
    incr books
    
    multi
    
    incr books
    
    incr books
    
    exec

    上述代码执行失败,因为books在事务之前改变了。

    PubSub消息队列

    上一篇讲了Redis消息队列的使用方法,但是没有提到Redis消息队列的不足,不保证准确性和多播机制

    消息多播允许生产者只生产一次信息,由中间件负责将信息复制到多个消息队列,每个消息队列由相应的消费组进行消费。

    为了解决多播问题:Redis提供了PubSub(PublisherSubscriber)发布者/订阅者模式。

    消费者

    订阅了name这个主题

    import redis
    import time
    
    client = redis.StrictRedis()
    p = client.pubsub()
    p.subscribe("name")
    while true:
        msg = p.get_message()
        if  not msg:
            time.sleep(1)
            continue;
        print msg

    生产者

    import redis
    
    client = redis.StrictRedis()
    client.publish("name", "java")
    client.publish("name", "python")
    client.publish("name", "go")

    所有的消费者都会收到相同的信息

    但是休眠也不是个事,用监听来代替休眠

    import redis
    import time
    
    client = redis.StrictRedis()
    p = client.pubsub()
    p.subscribe("name")
    for msg in p.listen():
        print msg

    当信息来了,就知道了

    模式订阅

    一次订阅多个主题

    缺点

    无法确认消费者是否收到

    并且不会持久化

    小对象的压缩

    Redis是一个非常耗费内存的数据库,它的所有数据都放在内存里

    zipList

    内部管理的集合数据结构很小,他会使用紧凑存储形式压缩存储

    本来时Hashmap存储的,改用一维数组存储下。

    如果hash结构,那么key和value会作为两个entry被相邻存储

    object encoding key:查看是用什么格式存储的

    intset

    当set元素少的时候且都是整数的时候,紧凑的整数数组存储

    总结:小对象超过一定的数量之后就必须使用标准的存储结构

    内存回收机制

    页回收,只要页上还有一个key,就不会回收,但是会重新使用那些尚未回收的空闲内存

    内存分配算法

    内存分配是一个非常复杂的课题,需要适当的算法划分内存页,需要考虑内存碎片,需要平衡性能和效率。

    redis不管内存的,但是有第三方库管理:

    1. jemalloc(facebook)
    2. tcmalloc(google)

    jemalloc的性能好一些,所以redis默认使用了jemalloc

  • 相关阅读:
    CDH 2、Cloudera Manager的安装
    204 01 Android 零基础入门 03 Java常用工具类 04 Java集合 04 Map集合 01 Map概述
    203 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 07 删除宠物猫信息数据(引入泛型知识点)
    202 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 06 查找宠物猫信息数据
    201 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 05 添加重复的宠物猫信息数据
    200 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 04 添加和显式宠物猫信息
    199 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 03 宠物猫信息管理概述
    198 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 02 案例:在集合中插入字符串
    197 01 Android 零基础入门 03 Java常用工具类 04 Java集合 03 Set集合 01 Set概述
    196 01 Android 零基础入门 03 Java常用工具类 04 Java集合 02 List集合 05 案例:公告的删除和修改
  • 原文地址:https://www.cnblogs.com/sicheng-li/p/13298086.html
Copyright © 2011-2022 走看看