当前位置: 首页 > news >正文

学设计的网站有哪些内容在哪里可以学到做网站

学设计的网站有哪些内容,在哪里可以学到做网站,wordpress用户注册打文章,域名备案成功怎么做网站文章目录 前言Redis key过期淘汰机制惰性删除机制定时扫描删除机制 前言 当我们创建Redis key时#xff0c;可以通过expire命令指定key的过期时间(TTL)#xff0c;当超过指定的TTL时间后#xff0c;key将会失效。 那么当key失效后#xff0c;Redis会立刻将其删除么#… 文章目录 前言Redis key过期淘汰机制惰性删除机制定时扫描删除机制 前言 当我们创建Redis key时可以通过expire命令指定key的过期时间(TTL)当超过指定的TTL时间后key将会失效。 那么当key失效后Redis会立刻将其删除么如果不会那么何时Redis才将其真正的删除呢我们来一起一探究竟。 Redis key过期淘汰机制 Redis中的key过期淘汰机制是由两种方式实现 惰性删除机制定时扫描删除机制 两种模式都不会在key达到过期时间后第一时间删除key而是等待特定的时机触发淘汰机制这个很好理解如果每一个key到达过期时间后redis都需要第一时间检测到并将其删除那么将会消耗大量的资源去实时的扫描全部key值这显然是不合理的。 下面我们来看一下两种方式的具体实现机制。 惰性删除机制 惰性删除很简单就是当有客户端的请求查询该 key 的时候检查下 key 是否过期如果过期则删除该 key。 在此种模式下触发key淘汰的时机是将删除过期数据的主动权交给了每次访问请求。 那么Redis具体是如何实现的我们来一起看一下源码实现。 淘汰删除的具体实现在db.c的#expireIfNeeded() int expireIfNeeded(redisDb *db, robj *key) {/* 通过调用getExpire函数获取key的过期时间。*/mstime_t when getExpire(db,key);mstime_t now;/* 当过期时间小于0时表示key没有设置过期时间直接返回0 */if (when 0) return 0; /* No expire for this key *//* 如果Redis正在进行数据加载直接返回0不进行后续的过期检查。 */if (server.loading) return 0;/* 获取当前时间如果当前是在执行Lua脚本中使用server.lua_time_start作为当前时间否则使用系统当前时间mstime作为当前时间 */now server.lua_caller ? server.lua_time_start : mstime();/* 如果Redis是主从复制模式并且当前节点是从节点则直接返回当前时间是否大于过期时间不进行后续的过期操作 */if (server.masterhost ! NULL) return now when;/* 如果当前时间小于等于过期时间则直接返回0表示key还没有过期 */if (now when) return 0;/* Delete the key *//* 增加已过期key的数量统计 */server.stat_expiredkeys;/* 向从节点发送key过期的命令保证从节点也能及时删除过期的key */propagateExpire(db,key);/* 向Redis的事件通知机制发送key过期的事件通知 */notifyKeyspaceEvent(REDIS_NOTIFY_EXPIRED,expired,key,db-id);/* 删除已过期的key并返回1表示删除成功 */return dbDelete(db,key); }/* Delete a key, value, and associated expiration entry if any, from the DB */ int dbDelete(redisDb *db, robj *key) {/* Deleting an entry from the expires dict will not free the sds of* the key, because it is shared with the main dictionary. */if (dictSize(db-expires) 0) dictDelete(db-expires,key-ptr);if (dictDelete(db-dict,key-ptr) DICT_OK) {return 1;} else {return 0;} }上面的源码即Redis执行key淘汰删除的核心过程具体操作可以参见注释通过方法名字expireIfNeeded()这是一个检查类型的方法那么说明是在进行key操作时会触发该方法进行检查key是否需要进行淘汰删除那么其调用时机在何时呢 在db.c的#lookupKeyRead()与lookupKeyWrite() robj *lookupKeyRead(redisDb *db, robj *key) {robj *val;expireIfNeeded(db,key);val lookupKey(db,key);if (val NULL)server.stat_keyspace_misses;elseserver.stat_keyspace_hits;return val; }robj *lookupKeyWrite(redisDb *db, robj *key) {expireIfNeeded(db,key);return lookupKey(db,key); }robj *lookupKeyReadOrReply(redisClient *c, robj *key, robj *reply) {robj *o lookupKeyRead(c-db, key);if (!o) addReply(c,reply);return o; }robj *lookupKeyWriteOrReply(redisClient *c, robj *key, robj *reply) {robj *o lookupKeyWrite(c-db, key);if (!o) addReply(c,reply);return o; }上面的代码是调用expireIfNeeded()的上游function通过名字可以看出#lookupKeyRead()与lookupKeyWrite()是读取和写入key的方法不得不说redis的代码命名非常的优秀值得我们学习那么调用该方法的一定就是执行获取key的地方这里我们以最简单的string的get命令为例 在t_string.c的#getCommand() /* string的get命令 */ void getCommand(redisClient *c) {getGenericCommand(c); }int getGenericCommand(redisClient *c) {robj *o;/* 通过调用lookupKeyReadOrReply函数查找指定key的值如果key不存在则向客户端返回空值并返回REDIS_OK如果查找到了key的值则将值保存到变量o中继续后续的操作 */if ((o lookupKeyReadOrReply(c,c-argv[1],shared.nullbulk)) NULL)return REDIS_OK;/* 判断获取到的值的类型是否为字符串类型 *//* 如果值的类型不是字符串类型向客户端返回错误响应并返回REDIS_ERR表示获取失败 */if (o-type ! REDIS_STRING) {addReply(c,shared.wrongtypeerr);return REDIS_ERR;} else {/* 如果值的类型是字符串类型向客户端返回获取到的字符串值并返回REDIS_OK表示获取成功 */addReplyBulk(c,o);return REDIS_OK;} }上述就是string get命令的执行过程我们可以清晰的看到redis是如何实现惰性淘汰删除机制其他的数据结构例如Hash、List、Set、Zset也是如此这里就不一样贴出源码进行举例说明了感兴趣的读者可以翻阅redis源码。 这里我们用一张string get命令的时序图总结一下get命令的执行流程 定时扫描删除机制 上面部分我们了解了惰性淘汰删除机制但是仅仅靠客户端访问来判断 key 是否过期才执行删除肯定不够因为有的 key 过期了但未来再也没人访问那岂不是GG这些数据要怎么删除呢 Redis在后台会启动一个定时任务定期扫描数据库中的所有key检查它们的过期时间是否已到期。但是这里需要注意定时任务并不是一次运行就检查所有的库所有的键而是随机检查一定数量的键。 为什么是随机抽查而不是全量从头到尾扫描一遍 很好理解如果redis中的key特别多如果进行全量扫描那对redis的性能会存在巨大的影响如果有一个亿的key每次定时任务执行都进行全量扫描CPU岂不是爆炸。 上图的流程图简单的描述了定时任务的执行逻辑实际上会复杂很多还是老规矩不多逼逼上源码Redis具体是如何实现的我们来一起看一下源码实现。 定时任务的实现在redis.c的#activeExpireCycle() void activeExpireCycle(int type) {....此处省略部分前置逻辑/* 循环redis全部的db */for (j 0; j dbs_per_call; j) {....此处省略部分前置逻辑do {unsigned long num, slots;long long now, ttl_sum;int ttl_samples;/* 获取dict中设置了TTL的key集合中计算集合的数量 */if ((num dictSize(db-expires)) 0) {db-avg_ttl 0;break;}....此处省略部分前置逻辑/* 如果过期的key数量超过了20那么扫描数量设置为20 */if (num ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP)num ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP; /* ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP 20 *//* 循环处理 */while (num--) {dictEntry *de;long long ttl;/* 获取dict中设置了TTL的key集合中随机获取一个key */if ((de dictGetRandomKey(db-expires)) NULL) break;/* 计算TTL剩余时间 */ttl dictGetSignedIntegerVal(de)-now;/* 如果当前的key已经过期则执行删除操作并将过期key的数量加1 */if (activeExpireCycleTryExpire(db,de,now)) expired;if (ttl 0) ttl 0;ttl_sum ttl;ttl_samples;}....此处省略部分后置逻辑/* 如果过期的key数量超过阈值的25%继续循环否则退出扫描 *//* 这也就意味着在任何时候过期 key 的最大数量等于每秒最大写入操作量除以4 5*/ } while (expired ACTIVE_EXPIRE_CYCLE_LOOKUPS_PER_LOOP/4);} }上面的代码就是定时任务扫描过期key的执行流程笔者删除了部分代码仅保留的核心执行部分方便读者阅读核心执行逻辑可以参见注释部分 如果用一句话概括说明定时任务的流程那么可以总结为 定时任务循环扫描每个redis数据库从设置了TTL的key的集合中随机挑选N个key进行检查如果过期干掉否则跳过直到过期key的数量小于25%退出扫描 以上就是Redis删除过期key的两种实现方式由于笔者对C的理解很有限因此仅仅截取了部分源码进行解读也可能有很多解读不对的地方望读者见谅。 事实上仅仅通过惰性删除定时任务扫描仍会可能存在很多“漏网之鱼”毕竟定时任务删除并非全量扫描那么如果Redis的使用容量达到了最大内存Redis会如何操作 这就涉及到了Redis的key淘汰策略本篇的内容就此为止关于Redis的淘汰策略解读我们下次再聊。
http://www.zqtcl.cn/news/801813/

相关文章:

  • 校园网站建设的意见新闻聚合网站开发 技术
  • 网站推广公司兴田德润电话多少wordpress 弹框
  • 大连网站建设谁家好软件开发需要什么技术
  • 广州网站建设哪家便宜成都电商app开发
  • 网站qq访客统计青岛网站设计定制
  • 山东嘉祥做网站的有哪几家销售外包
  • 怎么做网站_旅游网站定位
  • 湛江seo推广公司aso优化渠道
  • 网站设计培训机构内蒙古网上办事大厅官网
  • 什么是网站空间信息网站备案号中信息有变
  • 网站建设的基础怎么提升网站流量
  • 网站开发线框网页设计网站建设过程报告
  • 怎么用html做移动网站吗免费装修设计软件
  • 门头沟石家庄网站建设鞍山怎么样做一个自己的网站
  • 网站安装代码宣传网站建设背景
  • 网站空间续费东莞网站建设(信科分公司)
  • 少儿教育网站建设价格网页制作讲解视频
  • 网站开发方向的工作网站怎么做排名
  • 建设网站烧钱iis配置网站是什么
  • 新网站建设特色网站建设信息表
  • 商城做网站家具网站模板
  • 国有企业网站建设网站悬浮qq
  • 上海建站宝盒微网站生成app
  • 做网站是什么时候分页有哪些制作网站的公司
  • 专业柳州网站建设哪家好5千ip的网站能赚多少钱
  • 网站开发代理最火网页游戏
  • 做网站运营工资多少网站建设协议需要注意的问题
  • 如何建设一个人工智能网站qq头像网站源码
  • 有什么网站可以做外贸出口信息泉州网站制作运营商专业
  • 创业seo快速排名优化公司