100亿内存只需要100MB内存?这个难道离不开Redis?( 二 )


参照上图 , 简单来说 , 就是 。 我们的redis-client在操作的时候 , 会产生具有不同事件类型的socket 。 在服务端 , 有一段I/0多路复用程序 , 将其置入队列之中 。 然后 , 文件事件分派器 , 依次去队列中取 , 转发到不同的事件处理器中 。 需要说明的是 , 这个I/O多路复用机制 , redis还提供了select、epoll、evport、kqueue等多路复用函数库 , 大家可以自行去了解 。
4、redis的数据类型 , 以及每种数据类型的使用场景 【100亿内存只需要100MB内存?这个难道离不开Redis?】分析:是不是觉得这个问题很基础 , 其实我也这么觉得 。 然而根据面试经验发现 , 至少百分八十的人答不上这个问题 。 建议 , 在项目中用到后 , 再类比记忆 , 体会更深 , 不要硬记 。 基本上 , 一个合格的程序员 , 五种类型都会用到 。 回答:一共五种(一)String这个其实没啥好说的 , 最常规的set/get操作 , value可以是String也可以是数字 。 一般做一些复杂的计数功能的缓存 。 (二)hash这里value存放的是结构化的对象 , 比较方便的就是操作其中的某个字段 。 博主在做单点登录的时候 , 就是用这种数据结构存储用户信息 , 以cookieId作为key , 设置30分钟为缓存过期时间 , 能很好的模拟出类似session的效果 。 (三)list使用List的数据结构 , 可以做简单的消息队列的功能 。 另外还有一个就是 , 可以利用lrange命令 , 做基于redis的分页功能 , 性能极佳 , 用户体验好 。 (四)set因为set堆放的是一堆不重复值的集合 。 所以可以做全局去重的功能 。 为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署 , 使用JVM自带的Set , 比较麻烦 , 难道为了一个做一个全局去重 , 再起一个公共服务 , 太麻烦了 。 另外 , 就是利用交集、并集、差集等操作 , 可以计算共同喜好 , 全部的喜好 , 自己独有的喜好等功能 。 (五)sorted setsorted set多了一个权重参数score,集合中的元素能够按score进行排列 。 可以做排行榜应用 , 取TOP N操作 。 sorted set可以用来做延时任务 。 最后一个应用就是可以做范围查找 。
5、redis的过期策略以及内存淘汰机制分析:这个问题其实相当重要 , 到底redis有没用到家 , 这个问题就可以看出来 。 比如你redis只能存5G数据 , 可是你写了10G , 那会删5G的数据 。 怎么删的 , 这个问题思考过么?还有 , 你的数据已经设置了过期时间 , 但是时间到了 , 内存占用率还是比较高 , 有思考过原因么?
回答:redis采用的是定期删除+惰性删除策略 。
为什么不用定时删除策略?定时删除,用一个定时器来负责监视key,过期则自动删除 。 虽然内存及时释放 , 但是十分消耗CPU资源 。 在大并发请求下 , CPU要将时间应用在处理请求 , 而不是删除key,因此没有采用这一策略.
定期删除+惰性删除是如何工作的呢?定期删除 , redis默认每个100ms检查 , 是否有过期的key,有过期key则删除 。 需要说明的是 , redis不是每个100ms将所有的key检查一次 , 而是随机抽取进行检查(如果每隔100ms,全部key进行检查 , redis岂不是卡死) 。 因此 , 如果只采用定期删除策略 , 会导致很多key到时间没有删除 。
于是 , 惰性删除派上用场 。 也就是说在你获取某个key的时候 , redis会检查一下 , 这个key如果设置了过期时间那么是否过期了?如果过期了此时就会删除 。
采用定期删除+惰性删除就没其他问题了么?不是的 , 如果定期删除没删除key 。 然后你也没及时去请求key , 也就是说惰性删除也没生效 。 这样 , redis的内存会越来越高 。 那么就应该采用内存淘汰机制 。
在redis.conf中有一行配置
# maxmemory-policy volatile-lru
该配置就是配内存淘汰策略的(什么 , 你没配过?好好反省一下自己)1)noeviction:当内存不足以容纳新写入数据时 , 新写入操作会报错 。 应该没人用吧 。 2)allkeys-lru:当内存不足以容纳新写入数据时 , 在键空间中 , 移除最近最少使用的key 。 推荐使用 , 目前项目在用这种 。 3)allkeys-random:当内存不足以容纳新写入数据时 , 在键空间中 , 随机移除某个key 。 应该也没人用吧 , 你不删最少使用Key,去随机删 。 4)volatile-lru:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 移除最近最少使用的key 。 这种情况一般是把redis既当缓存 , 又做持久化存储的时候才用 。 不推荐5)volatile-random:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 随机移除某个key 。 依然不推荐6)volatile-ttl:当内存不足以容纳新写入数据时 , 在设置了过期时间的键空间中 , 有更早过期时间的key优先移除 。 不推荐ps:如果没有设置 expire 的key, 不满足先决条件(prerequisites); 那么 volatile-lru, volatile-random 和 volatile-ttl 策略的行为, 和 noeviction(不删除) 基本上一致 。