一、为什么你们项目里面要用缓存/或者问为什么要用Redis

这个问题问的是缓存的特性,缓存是干嘛用的呀?

  1. 为了加快响应时间,为了提升项目的读取性能,比如说:A 去 DB 里面取一个数据要 300ms 如果这个数据在 Redis 中呢?只需要 50ms
  2. 为了保护 DB:保护 DB 是什么意思呢?MySQL 它是个 BIO 模型的,BIO 模型有什么特征?你来一个请求我就开一个线程,来十个我开十个,来了一千个请求你顶得住,来呢一万个呢?十万个呢?请求我可以无限增长你线程能无限开不?开一个线程的开销是多少呢?你内存不够用了不就直接宕机了吗?将数据直接放到 Redis 中的话 DB 也就安全了,虽然你可以分库分表但是你单机性能只有这么高,tm 十台 MySQL 都比不上一台 Redis 属于是不是一个维度的选手了。

但是注意:Redis 只能保护 DB 读的请求,写请求是保护不了的。
比如说下单/秒杀:Redis 只能说做预减这种限流级别的减操作,不能拿去做真实库存的减。
总结:

  1. 为了加快响应时间,为了提升项目的读取性能
  2. 为了保护 DB 的读取

    二、Redis 和 Memcached 的区别

  3. 数据类型的区别:众所周知嗷,Redis 支持很丰富的数据结构,而 Memcached 只支持 K/V 这一种,但是这个重要吗?有一说一并不重要,json 这种数据类型我只能说太牛了,它可以代替所有的数据类型,懂不懂任你百路来,我只一路去的含金量啊,但是 Redis 给不同类型提供了很多方法。那这个有关系吗?那我只能说关系大了。例如:我存了一个 list 1,2,3,4,5,6,7 然后我要把 4 拿出来计,如果是 Memcached 需要返回一整个 json,然后我把 json 转成 list,然后拿 list 去 get 到 4那 Redis 呢?我直接就可以在 Redis 里面 get 了,这区别可见大了呀。

  4. 持久化问题:Redis 可以做持久化,而 Memcached 没有提供持久化方案。这个有所谓吗?讲道理,如果单纯的做缓存的话,由于我不可能是裸机跑的,我做了主从或者集群,你挂了恢复慢都无所谓,不可能主挂了从跟着一起马上挂掉吧?但是缓存真的需要持久化吗?做了主从之后,缓存挂了有所谓吗?无所谓的呀,反正有备机,充其量只是少了一小部分数据而已,但是 DB 里面还有啊重新缓存不就行了?但是 Redis 就不一样了除了 String 是正儿八经的缓存结构之外,其他的什么 List、Set、Hash、ZSet 更多都属于是功能性结构这些数据 DB 里面它不一定有所以才要持久化,说白了 Memcached 就是个纯粹的缓存。

总结:

  1. 数据类型的区别
  2. 持久化问题
  3. Redis 相对来说,并不是一个纯粹的做缓存用的,而 Memcached 它是个正儿八经做缓存的

    三、为什么 Redis 要用单线程多线程不是更快吗?或者问:为什么 Redis 的单线程比 Memcached 的多线程要快?

    这个问题就相当于是在问,缓存是什么东西,那缓存是什么东西呢?比如说我逛淘宝,由于它的页面都是做的页面静态化的,缓存的基本上就只有一些 SKU、商品名称之类的少量数据,加起来一个商品数据都不知道有没有 1K 大小,基本上缓存的东西大小都很小,这种情况我开多线程有必要吗?而且开多线程,你得保证原子性吧?得加锁吧?而且你网卡性能只有这么高,你开一万个线程,网卡吞吐上不去也是白扯
    总结:

  4. 对大批量小容量数据进行处理的时候,单线程并不是性能的制约,网络的 I/O 吞吐量才是影响性能的关键。

  5. 在处理大容量的数据时采用多线程的 Memcached 确实有着比 Redis 更加出色的性能表现,但是作为缓存数据库大批量小容量的数据才是更应该注意的。
  6. 单线程既可以保证原子性,而且在处理小容量数据的时候频繁的上下文切换线程会造成不必要的性能开销。

    四、为什么单线程的 Redis 支持高并发呢?

    这个问题就是在问 Redis 的 I/O 模型,也就是 epoll。BIO、NIO、AIO 这种东西大家应该都听说过吧,epoll 就是 NIO 的一种
    大体是这样子的:分为三个 epoll_create 、epoll_ctl 和 epoll_wait 。
    create 为创建、ctl 为注册监听事件、wait 是等待事件发生。

    讲个故事:
    我去淘宝买东西,我总得知道我要买什么是吧?那我要买的东西我管它叫 fd
    卖家要把东西发给我,那他起码得知道我在哪里吧?我的地址我管它叫 socket
    卖家不可能亲自送货吧?他得把发货这个任务外包给第三方比如说快递,我管它叫 epoll

    那个整体流程差不多就是这样了:

    1. 我现在给 fd 下了个单,我将 socket 发送给了卖家, 而卖家又将 fd 给了 epoll,然后填上了我的 socket 说要送到这里;
    2. epoll 收到了这个订单之后,就给我创建了订单(epoll_create),然后又注册了个监听事件(epoll_ctl)如果快递到了之后,就好通知我来取;
    3. 将 fd 送到了我的地址附近之后(fd 准备就绪之后),就投发到了小区楼下的菜鸟驿站,完事通知我去菜鸟驿站中去取(也就是 epoll_wait 被触发,将数据丢到就绪列表中,并通知 socket)
    4. 我取到快递服务完成(socket 收到通知之后,去就绪列表中取走数据

总结:
Redis 采用 epoll 的方式来做到的高并发,也就是多路 I/O 复用