1. Linux中有pagecache和direct io两种
    2. direct io其实和pagecache没什么区别,只是不再是内核管理,而是交给应用进程自己管理了,实际上还要使用到pagecache—->数据库DB一般会使用direct io—->mysql中的数据页是16kb❓
    3. 设置网卡的子端口的ip地址,这样就可以在一台机器上使用65535*2乃至更多个socket了

    image.png
    150.11和160.11各拿到6000多个端口号,可以同时申请—->只要保证四元组唯一即可(tcp的语义,socket的本质)
    image.png
    ip地址不能改的话,这个事不可以完成

    1. eth0是一个接口,是什么接口???
    2. 打开tcp监控:开启监听抓取数据包!!!

    image.png

    1. 协议

    image.png

    1. 四层负载均衡—->七层负载均衡
    2. 为什么一台机器上可以有很多个ip地址?网卡怎么设置
    3. 为什么要在linux上配置路由—->这是那个bug吗?
    4. 0.0.0.0:9090是什么意思
    5. ulimit -a
    6. 为什么最大句柄数是1024,为什么能打开4000多个句柄——>权限问题,普通用户受其限制,但是root用户不受其限制
    7. 内核级别可以起多少句柄的设置—->一般1g代表100000各句柄

    image.png

    1. ulimit控制的是用户进程级别的文件描述符的上限
    2. 网络编程之多路复用器与epoll编程章节中zookeeper中对多路复用器的使用
    3. 在rpc中的最初版本中加一个before就能先运行服务端???servlet中的before???
    4. 在java中的输出sout是系统调用!
    5. 动态DNS—->负载均衡的负载均衡—->DHCP劫持
    6. 软路由
    7. 负载均衡技术不是bind绑定技术:不会达到让一个人综合使用带宽的效果
    8. 负载均衡静态的轮询算法和操作系统中进程调度时的调度算法(马老师讲的课)
    9. image.png
    10. PAXIOS选举算法???
    11. zookeeper选举算法(有主模型和无主模型)
    12. 200和302;302表示跳转,跳转过去的时候表示是好的???
    13. 在同一个局域网中占用同一个ip会怎么样;不在同一局域网占用同一ip会怎么样(在实验中特殊在mac地址是相同的,mac地址不同时会出问题)
    14. redis和hbase都是二进制安全的
    15. redis的value的类型其实在key中,value中其实是字节数组来存储的
    16. 将软件安装成服务service,init.d文件夹,有些软件有自己的安装服务脚本(要先配置环境变量/etc/profile)
    17. chkconfig开机自启动—->chkconfig list
    18. ant编译工具
    19. make不是只面向一类语言的
    20. 老式的httpd是fork出来的进程,而nginx使用的是异步非阻塞???

    image.png

    1. 零拷贝—->系统调用sendfile
    2. kafka基于jvm
    3. kafka=sendfile(0拷贝)+mmap(内存映射 )
    4. redis是单线程的,所以内部是有顺序的,因此多个客户端不必加锁,但是要保证事务的话还是要保证在同一个客户端上发出请求;和kafka中的很像,kafka可以向不同主题下的不同分区发送数据,但是对同一资源的操作只能发往同一分区(是因为kafka并行吗???)

    image.png

    1. nginx多少颗cpu启动多少个worker进程,一个worker进程可以把数据压到一二三级缓存中去了,每个nginx进程使用多路复用epoll

    image.png

    1. tomcat8以后也是用的nio
    2. epoll的事件驱动并不是真正的时间驱动???(微内核、宏内核设计有区别!!!)
    3. 二进制安全(redis和hbase都是二进制安全的)
    4. redis中多线程的数据一致性要在客户端保证
    5. redis中需要转义符吗?可以直接设置ascii吗?
    6. redis中存储空格的时候要加引号

    image.png

    1. 二进制安全是将编解码交给客户端去做???—->不同语言对整型的宽度理解是不一样的,可能发生截断溢出这样的错误
    2. 使用json和xml来交互,而不使用序列化,因为json和xml和字符型的数据,使用序列化需要添加编码器和解码器(一遍认为int是4byte,一边认为int是2byte就会出现问题:一边写入4byte,一边读出的时候只能读2byte,这时就会溢出导致不够,会导致数据显示不对)
    3. redis是一个很重要的中间者,他有一个二进制安全,他只取字节流
    4. redis虽然知道某一个value是数值类型,但是他并不会按照某一种数据类型定义来存储
    5. redis的客户端也是一个字节一个字节的向里面去写
    6. INCR这样的计算会将字节拿出来先转换为数值,有时候还会更新encoding,下次计算就可以直接拿出来往上加了
    7. 如果不是int类型可以进行规避报错(加速)
    8. 更新编码的过程
    9. 编码并没有影响数值(数据)的存储
    10. 中文的“中”字为什么是3byte?—-> 因为客户端与redis通信的时候,xshell的编码(字符集)是utf-8的,在utf-8下,他占3byte;在gbk中占2byte
    11. 真正走的是字节流,编码要自己控制
    12. —raw会进行格式化(下图中xshell的编码为gbk),不带—raw,redis只会识别ascii,超过ascii直接按十六进制显示;加上—raw会自动按照客户端的编码进行显示(自动在编码集中找到那个字符)image.png
    13. 长度是不会发生变化的,还是3byte和2byte

    image.png

    1. 客户端上层、外围是什么编码,redis是不知道的;给redis的一定是客户端中变为的字节数组
    2. redis中的encoding可以作为预判断,但是可以忽略他,这个encoding只是为了方便运算操作
    3. 假如encoding就是int,那么在INCR的时候就可以直接计算了,就不需要做排错、转换类型的操作了,相当于提升了效率(把判断和转型的操作忽略掉了)
    4. redis底层就是按字节去存的,只不过在上面的key上做了一些优化,key上没有encoding的话,每次计算都要做一次判断看他能不能进行本次操作;比如上一次做数值运算成功了(之前是raw类型的encoding),就会把encoding标成int,那么下一次直接做累加就行了,不必再进行类型判断、校错了;假如对embstr进行数值计算的时候就直接报错,不会再去尝试了—->适当的加速过程,通过该方法让速度变快
    5. 使用redis的时候,一定要在用户端沟通好数据的编码和解码,redis中是没有数据类型的;这是为了客户端但是也是给客户端带来的问题:大家一定要约定俗成—->数据一定要以什么编码来存储
    6. getset命令不是原子性问题,而是从io请求、通信上来考虑的(作者的细腻之处)
    7. mset—->more set
    8. msetnx是原子性操作,只要其中有一个失败了,那么设置的多组值就会都失败!!!(只有不存在key才能设置进去)

    image.png

    1. redis设置一个kv必然是原子的,因为是单线程;只有在mset的时候才可能出现原子(msetnx出现原子操作)
    2. redis不走网卡150000,走网卡会讲到100000以下,60000或者70000左右
    3. mysql倾向于使用BIO,因为即使用NIO可以让他们很快进来,但是依然会受到磁盘IO带宽的限制,依然会等很久,所以还不如使用BIO
    4. mysql的缓存效果不好
    5. nginx有多少个物理核心就要开启几个进程,亲密度:四个核心,redis亲密到第三个核心上,其他的在别的核心上跑,这样(redis?)缓存就不会清来清去,这样才能达到最快的十万、八万的秒级速度;一直跑在这个核心上,不去别的核心去溜达—->docker的时候讲
    6. STRLEN求的是字节数,并且在redis中是以字节来显示和存储的
    7. ascii是标准字符集,其他的字符集都是拓展字符集,不会去重写ascii所定义的字符;并且ascii一定是以0开头的1byte,只要拿到字节发现是以0开头就用ascii字符集;假如在utf-8中以3个1和一个0开头,那么就表示这个字符用3byte来表示,这时要读出之后的2byte,来共同表示这个字符;把标识码(校验码)踢掉之后,把剩余的二进制位拼起来,去客户端字符集中取出字符并显示出来
    8. 不同场景下要做不同的技术选型—->不太重要的东西可以用redis存储,但是像银行的账户之类的还是要用数据库存储,要使用事务
    9. String型的数值计算可以用在抢购、秒杀、详情页等信息,详情一般是静态的东西,后端一定会用一个异步查询去请求商品所有的购买数、库存等信息;如果不用redis的话,就要去数据库,就会出现很高并行度情境下多个人同时去对商品加减,这会触发数据库的事务,redis可以规避并发下对数据库的事务操作,完全由redis内存操作代替—->计算向数据移动
    10. 微博中的点赞、评论(数)、好友数这些不太重要的数据,不必必须精准的数据可以用redis

    image.png

    1. 银行中的钱不适合用redis,那些必须持久化存储并且结合事务,数据可靠性必须保证(redis的事务是另一回事)
    2. 在不同情况下的技术选型必须要保证
    3. 在并发、多线程的情况下,使用关系型数据库必须使用事务(尤其是对同一数据进行操作)操作失败的情形就是并发下的操作失败
    4. redis并发执行的话必须前面成立,后面才能成立,对多种应用会组成一个事 务(各搞各的?)
    5. 世界上不只有关系型数据库这种模型(最好把每种模型有空都了解一下

    image.png

    1. 并发情况下jedis用得不是特别多了;大数据中还在用,因为一个任务中很少再向外抛出线程

    image.png

    1. 需求image.png
    2. P与NP问题(密码学)
    3. redis的list支持阻塞的单播队列
    4. redis的hash类型中age和18就固定下来了,不能再改变了,不能再像document那样分岔了
    5. 技术选型:redis和mongoDB,其实redis中就是一个document,只不过不能再分岔了!????什么叫分岔???
    6. document的分岔
    7. 🌟虽然redis给出了很多功能但是要知道哪些功能会影响性能,比如set中的SMEMBERS这个命令会降低服务器的吞吐量—->解决方案:专门拿出这样的一个服务器来放这样的集合,来满足需求就行了;这是在有这种需求并且不能用数据库来操作时的情形下;把SMEMBERS这个命令单独切出来,不要和别的k-v混在一起使用
    8. redis的set中的抽奖应用:SRANDMEMBER key count
      1. 这里的count可以是正数也可以是负数:正数不会重复,负数会出现重复
      2. 当count是正数的时候,要比集合中的元素个数小吗???假如比元素个数大会怎么样???会只输出全部,还是会重复输出,还是会报错,还是不会输出
    9. SPOP每次抽奖抽一个并且将抽出的元素从集合中取出来不参与下一次的抽奖了
    10. redis的set的三个特点:
      1. 无序性
      2. 随机性
      3. 去重
    11. 正是因为set的随机性才可以将redis用来进行抽奖与调节家庭矛盾
    12. 抽奖的真正公平是真正的随机而没有人为干预,不存在什么每个人抽奖均衡或者领导抽到的面值大一些这种额外条件
    13. 排序:字典序和数值序
    14. 按数据的什么属性去排序(名称、含糖量(很重要但是不要显示出来,可能看不到含糖量但是要排出来))
    15. sorted_set要有一个分值维度,不然不知道按什么规则去排序,既要给元素又要给出分值
    16. 当给出的分值都为1的时候,这时候按名称的字典序排的
    17. 顺序、倒序;从小到大、从大到小—->rank排名—->索引,正负项索引
    18. zset的三个要素:score分值、元素、索引
    19. 因为sorted_set和set的首字母重复了,所以用z来作为sorted_set的代表(z是字母表的最后一个字母)
    20. zset中不想用分值的时候,全给1就行了
    21. 物理内存左小右大(按score分值),不会随命令发生变化
    22. 跳表会随机造层(需不需要给其他元素插入时提供参照呢)—->放在哪几层,有个初始值,不超过几层
    23. 跳表牺牲存储空间来换取查询速度,一部分空间牺牲一下,而不是成倍的去翻倍
    24. 跳表的最下面一层不是单纯的链表,而是经过调整的有指向的表

    image.pngimage.png

    1. 数据量小的时候不需要跳表,数据量达到一定规模之后才会升级成跳表
    2. 跳表是类平衡树的—->左旋右旋,让高度相对一致,查找任何元素的复杂度比较均匀
    3. 跳表到底是快还是慢?
      1. 一定量的数据情况下(数据量多),增删改查操作比较多的情况下,平均下来快了,平均值相对最优
      2. 元素比开始第一个元素大的话要走好多次,转了一个圈才能回来,还不如直接线性遍历
      3. 综合评价,看增删改查,都看,平均下来
    4. 相较于平衡树和红黑树,跳表面对各种各样的数据他的性能测试结果相对比较稳定!!!
    5. 多数据源问题—->mybatis
    6. redis中有事务,但是不支持回滚,因为redis看重的是速度,他看人不看redis(注重人的错误)
    7. redis和nginx都是模块化的,redis除了自己的功能外,还可以向其中加入一些拓展库来增加他的功能
    8. 布隆过滤器bloom,counting bloom可以计算的布隆过滤器,cukcoo过滤器(布谷鸟过滤器)
    9. bf.add是布隆过滤器,cf.add是布谷鸟过滤器
    10. 布谷鸟过滤器!!!
    11. 双写问题:既要写数据库又要写布隆redis
    12. redis使用的最大内存最好在1g-10g范围之间;不要太大,太大用数据做持久化的时候成本是很大的,数据迁移的时候成本也比较高
    13. 发生写set会直接剔除过期时间,即过期时间没有延续的概念
    14. 倒计时和定时,并且redis不能延长倒计时的时间
    15. 过期原理:两种方式:被动和主动—->官网

    image.png

    1. 缓存的四个问题:
      1. 击穿???
      2. 穿透(布隆过滤器或者布谷鸟过滤器!!!
      3. 雪崩
      4. 缓存一致性(双写问题—>缓存作为数据库时发生的双写???)—->双写一致性
      5. 高并发下对……—->主动复制问题等
    2. 技术是易于人的使用,理论是极其复杂的
    3. redis+mysql的时候,不能保证强一致性(追平),可以采用异步的方式去向mysql中写,加一个消息队列,异步地向mysql中去写
    4. 缓存挂了之后的数据恢复过程,要不要进行数据恢复,要不要冷启动或者热启动
    5. redis作为数据库的时候要考虑速度和持久化,内存掉电易失
    6. 单机持久化和集群持久化(主从复制)
    7. 数据可靠性、数据持久化—->2类东西(无关redis—->存储层)
      1. 快照/副本
      2. 日志
    8. linux中管道会在执行的时候创建新的子进程
    9. 管道:
      1. 前一个命令的输出会作为后一个命令的输入
      2. 管道会触发创建子进程
    10. $$和$BASHPID
      1. 为什么不一样???
        1. 因为$$的优先级高于管道
        2. 执行echo $$ | more时是先将$$替换为当前bash的进程号—->io精讲中也有,然后再开辟一个进程进行处理
        3. $取一个普通变量时的优先级是低于管道的

    image.png

    1. 管道会开辟两个子进程???左边一个子进程,右边一个子进程?
    2. linux中用&表示程序后台运行,此时程序依然可以在前台进行输出但是再按一次回车之后就可以回到父进程了
    3. linux系统中父子进程的变量是隔离的,但是父进程可以通过export命令让某一变量对子进程可见,但是这时子进程的修改不会影响到父进程中变量的值,父进程的修改也不会影响子进程(进程隔离!)

    image.png

    1. 进程之间可以导出而并非共享—->可以达到这样的效果!—->联想到redis持久化时的时点性
    2. 脚本的第一行要写#!,后面加的东西表示执行该脚本要用的程序!!!一般是/bin/bash
    3. 在Linux命令行下执行/bin/bash命令可以进入一个新的bash窗口,这时的$$和¥BASHPID是不一样的
    4. 存的是数据的副本—->谁改另一个都看不到
    5. redis持久化—->你改你的,我落我的(落数据—->持久化数据)—->有两个问题:
      1. 速度(10g数据在内存中创建副本的话可能也是比较慢的)
      2. 内存大小(内存中是否还有足够的空间存放10g的副本数据)
    6. linux中的fork系统调用—->实际上玩的就是指针的一个引用
      1. 创建速度快
      2. 空间要求不多—->子进程占用很少的空间
    7. fork如何实现?

    image.png

    1. redis配置中save的意义

    image.png

    1. pagecache是哪个层次的?是硬盘和内存,还是内存和虚拟内存(应用程序的内存!!!???)
    2. 每隔5s但是每次要10s,这样的话并不是每次都创建一个进程—->有点和事务类似,要等这次持久化结束之后才会开始下一次的持久化???,也不符合事实,时间间隔太短的话IO成本太大!!!—->开始一个任务之后就必须等待这个任务(子进程持久化任务?)做完!!!!
    3. 一秒一次RDB不如用AOF
    4. AOF是实时的
    5. redis是内存的,用AOF反而和磁盘打交道了,降级成半IO这种行为了—->看值不值得
    6. 加了AOF会降低速度
    7. RDB不支持拉链,永远只有一个dump.rdb文件—->拉链指的是一个定时有时间的一系列的记录,因为RDB没有拉链所以需要运维设置定时任务每天将最后一个rdb设置成拉链保存起来
    8. 有拉链—->不覆盖、不更新!而是追加
    9. rdb不消耗太大硬盘,因为只有一份数据,但是数据不那么可靠了,因为之前的几个版本的数据会丢失!!!
    10. 有时候最简单的就是最好的、速度最快的
    11. 程序代码越多,潜在风险和bug越多
    12. redis一般只让他占10g以内的内存空间,因为持久化的时候太大了会占用很长的持久化时间,这样会造成效率的下降,一般一两个G、两三个G,不会允许往一个redis中疯狂的怼数据
    13. IO是最大瓶颈
    14. 持久化或者全量数据备份的情形下永远有间隔之间丢失的问题
    15. 序列化、反序列化,二进制时速度是最快的,因为可以直接放到内存中去,而不是要经过很多步骤才能称为符合的变量(json会慢一点,需要解析)
    16. mysql中的三种log
    17. hdfs的log和文件备份
    18. 如果开启了AOF,只会用AOF做恢复,因为AOF恢复的完整性相对会好一些(即使RDB也可以用来恢复)
    19. redis4.0以后AOF可以包含RDB的全量,也可以做AOF新数据的增量(增加记录新的写操作)
      1. 先将rdb二进制的先恢复到内存,再恢复一些新增加的操作
      2. 新增的会少一些,速度会快一些
    20. pagecache和内核中的buffer,与向磁盘中刷写的时机???
    21. pagecache的脏页!!!dirty page
    22. rocketmq中的AKF是哪三个层次?
      1. 主备(单点故障)->主从(读写分离)
      2. 不同的主题
      3. 不同主题下的不同分片?
    23. 有一个冗余的概念是什么?操作系统中的,还是IO中的,还是LVS中的,还是rocketmq中的?????????❓
    24. 多个机器监控redis,是哨兵吗—->涉及到分区容忍性
    25. 哨兵可以改自己的配置文件—->redis也行,极大的安全隐患
    26. 16384个槽位—->redis的cluster模式
    27. nginx在哪里
    28. 代理层中要加入逻辑代码实现nginx反向代理
    29. 逻辑实现—->无状态的代理
    30. 满足了无状态之后才可以一变多
    31. 命令安装软件要先大概扫一眼所有的安装步骤看有没有什么注意点,在操作中要注意注意点,否则可能会报错
    32. git clone报错的话可能是因为操作系统的版本太低了,yum update nss就行了
    33. redis手工起的话就拿当前所在目录作为持久化目录!(没有默认配置文件?)
    34. jedis线程不安全,在高并发场景下不适合,但是在大数据场景下可能使用,因为大数据场景下很少有高并发的需求
    35. redis的压力不会大,顶多在那排队(单线程)
    36. 某一台机器可能会挂——>1.让他活(高可用);2.避免挂掉造成的影响(避免死锁:设置锁的过期时间)
    37. 布隆过滤器不支持删除,布隆过滤器+或者布谷鸟过滤器支持删除
    38. 解决布隆过滤器不能删除的问题,要么在redis层面置空,要么换一个过滤器
    39. 雪崩的解决方案:业务端进行延时
    40. 架构师做决策:数据一致性……
    41. redis可以做分布式锁redisson,但是不常用—->不然zookeeper就不会出现了
    42. zookeeper做分布式最容易
    43. 分布式锁不要求效率,但是要求一致性和准确度
    44. zookeeper没有redis快,但是会最大程度上做到数据的可靠性,并且开发会比较简单
    45. 金融—->蚂蚁金服相护宝,写sql
    46. 民生银行—->平安;民生的技术比较前沿,从民生出来去平安,从平安出来去民生
    47. redis是二进制安全的,只存字节数组,只要双方约定好各种数据类型该如何存放即可(约定编码、解码)
    48. Redis Reactor模式
    49. Reactor是异步的吗
      1. 软件层面的异步而不是IO层面的异步
      2. 逻辑代码中异步的概念—->回调函数
    50. 现在互联网的开发进入了Reactor的编程模式!!!
    51. redis实现聊天室
    52. redis的高级API
    53. zookeeper也是基于内存?kafka是磁盘?
    54. kafka可以重复消费数据?
    55. kafka是可靠的
    56. 完成分布式协调很难,需要分布式锁
    57. zookeeper用于分布式应用的分布式协调服务
    58. zookeeper基于内存,数据存放在内存之中
    59. zookeeper中每一个节点可以存数据,但是每个节点中存的数据不是很多—->1m(做出了限制)
    60. 不要把zookeeper当数据库用,理论上可以但是不建议用;
    61. zookeeper的主旨是快,这就要求数据量小,这就与数据库的使用不符合
    62. spark消费kafka中数据的时候,每消费一下就将偏移量offset记录到zookeeper中去,其他节点可以拿到这个offset—->这种用法是不正确的—->写和读没有达到一个很大的优势,不是读多写少,比例不对
    63. linux网卡配置

    image.png

    1. 关闭防火墙并设置成开机不启动

    image.png

    1. 更新系统环境变量之后要将其加载到内存中去

      1. . /etc/profile
      2. 或者
      3. source /etc/profile
    2. zookeeper中的ephemeralOwner表示临时所有者,是临时节点的owner!!!

    3. mysql中redolog和binlog的两阶段提交
    4. zookeeper的两阶段提交:第一阶段是日志,第二阶段是内存持久化???由follower转给leader—->leader转给follower记录日志—->提交—->过半通过—->最终客户端拿回ok结果
    5. redis由强一致性到弱一致性到最终一致性
    6. 要么剩过半,要么整个集群直接不可用;不存在剩下的节点少于一半的情况
    7. 没过半直接不可用了,因为这样连主都选不出来了
    8. zookeeper中最开始永远是先给自己投票的
    9. zookeeper的可靠性redis比不上但是redis的速度一定比zookeeper快!!!
    10. redis中也是有事务的,不过这个事务没有mysql中的完善,只保证了一致性和隔离性,不满足原子性和持久性。
    11. 原子性,redis会将事务中的所有命令执行一遍,哪怕是中间有执行失败也不会回滚。kill信号、宿主机宕机等导致事务执行失败,redis也不会进行重试或者回滚。
    12. 持久性,redis事务的持久性依赖于redis所使用的持久化模式,遗憾的是各种持久化模式也都不是持久化的。
    13. 隔离性,redis是单进程,开启事务之后,会执行完当前连接的所有命令直到遇到exec命令,才处理其他连接的命令。
    14. 一致性,看了文档,觉得挺扯的,但是貌似说的没有问题。
    15. 对于一个分布式系统来说,考虑并发的时候要对读和写分别进行考虑!!!
      1. 读的并发量是多少
      2. 写的并发量是多少
      3. 一般读比写更快
    16. watch的回调是基于注册的,没有注册是不会给你发送消息的
    17. zookeeper纯广播就会有点像消息的发布订阅了!!!在集群太大的情况下,节点之间的通信会消耗掉大多的资源,反而不划算
    18. netty、nio、reactor非常重要(不光面试中)
    19. 用不用netty或者reactor模型是服务器能发挥多大能力的关键因素50%—->80%
    20. redis—->jedis、lettce(netty高性能spring默认)、redsson
    21. spark、dubbo底层都是netty
    22. zookeeper的api导包的时候,服务端用的哪个版本客户端就必须用哪个版本
    23. zookeeper中没有连接池的概念,因为每一个连接都会得到一个独立的session,在zookeeper中session有专门的作用
    24. ACL访问控制列表—->Ids
    25. API中写的时候产生事件而读的时候注册事件
    26. 会话中的watch和path中的watch,path中的watch是一次性的
    27. 内部类(局部类)要用外部类的成员变量时要将外部类的成员变量设置成final
    28. 在之后的getData注册watch的时候参数给的是true的话,默认是default watch被注册到这个path上—->是new zookeeper的时候注册的会话的watch;要注册path的watch的话要传this
    29. zookeeper简单快速,但是watch有点烧脑true和this
    30. 将日志配置文件放到项目的resource资源目录下,在连接的时候会将详细日志打印出来
    31. zookeeper客户端有fail-over可以切换到别的地方去,并且因为统一视图的原因sessionId是不会变的!
    32. 不用回调的时候,线程是严格按照程序员规定的顺序去执行的,这样会进入一种阻塞状态,一定程度上会降低效率(cpu因为等待会在那里空转);异步:程序员是方法内容的缔造者,而不是逻辑执行顺序的缔造者;逻辑执行顺序是由框架来决定的,只要实现方法,放到那里,到时事件发生了会自动去调用这个方法—->什么事情发生了就及时处理这些事件,避免cpu空转,浪费效率
    33. sessionId的过期时间是服务端去记录的,不是客户端去记录的;将连接的服务端停掉,这个sessionId会在其他节点上停留3s钟,假如在这3s之内连接转移到另一个节点去了,这个session不会被断开、销毁,还是同一个session(统一视图);假如超过3s这个session就会断开!
    34. 用zookeeper主要是为了zookeeper的回调机制,使用zookeeper的人不需要去轮询,别人修改了zookeeper,而你watch了他,那么你就会第一时间获取到变化
    35. zookeeper案例:
      1. 分布式配置(配置中心,dubbo也是使用了zookeeper的回调方式)
        1. 配置中心
        2. 注册发现
      2. 分布式锁—->面试,实际价值小但是可以通过这个题目可以带出很多知识点
    36. 并没有每种场景都线性写一个方法堆砌起来,而是将这些方法都堆砌好,用回调和watch事件来粘连的他们
    37. 没有用具体的方法将这些场景都罗列起来
    38. 做上帝将事件都写出来,看事件自己什么时候发生—->面向事件编程(响应式编程)——>Reactive模型
    39. 阻塞式更简单
    40. 封装完之后真正的业务代码就只剩几行了
    41. 因为只有一个返回值,所以可以采用引用传参的方式来获取别的参数
    42. 可以将引用传递给一个类作为那个类的成员属性,然后在这个新的类里面就依然可以使用这个之前的对象了
    43. 改过配置之后要记得重启
    44. 写客户端zookeeper的监视器watcher的时候要进行自包含—->zookeeper对象作为成员属性
    45. 有时候每一个线程中都是new的一个新的对象,是单独的对象,不是共享的对象(共享资源!!!)所以不需要同步
    46. zookeeper的api进行删除的时候要给出版本号,此时给-1就表示忽略版本号,直接删除—->给出pathName就可以删除
    47. 响应式编程模型——>异步的编程模型!!!
    48. 要避免事件发生在监控注册之前!!!发生的太快了会出问题—->要保证监控被注册上去之后再发生事件
    49. 之前的线程在同一台机器上,使用的是同一内存jvm中的锁;而在分布式情况下,线程分散在不同的机器上,无法使用相同的内存,这时锁放在远程的zookeeper上
    50. 不依赖jvm,而依赖一个外部状态