首页 > 数据库 >redis——基础服务

redis——基础服务

时间:2024-06-18 19:09:48浏览次数:27  
标签:服务 删除 过期 基础 redis 键值 内存 淘汰

首先为什么要做一个redis出来?数据库不够用了吗?考虑到原本的应用程序是客户端访问服务端,服务端访问业务数据需要去数据库去拿,而数据库是个持久化的应用程序,是需要磁盘IO的,这就导致了速度会慢,并且如果存在大量的访问,会导致数据库崩溃。除去导致崩溃这样严重且极端的情况,这点性能虽然对一个二个用户来说并没有什么感知,但是对于应用程序来说,是个有着很大加速空间的点,为了吃这部分性能,出现了redis[1],承担了缓存的作用。目前,redis因为它的高性能,出现了很多应用场景。

[redis是什么初衷 • Worktile社区](https://worktile.com/kb/ask/755946.html)

什么是Redis?为什么要用Redis? - 知乎 (zhihu.com)

做一个缓存简单,应用程序选择合适的数据结构向redis中存储键值对,redis开辟内存空间存储,一个缓存就做好了。有什么问题吗?想想应用程序是如何使用redis的:不论是数据库亦是应用程序本身的键,选择redis提供的数据结构,然后向里面set后,数据就保存在里面了,就这么一直一直放,即便有过期时间,也有把内存塞满的可能,哪怕几率很小,那作为一个为其他服务提供服务的服务,也要解决这个问题——不能让应用程序把自己的内存空间塞满而崩溃。

这样就会主要涉及到两个问题:

  • 过了期的键怎么删除
  • 内存满了怎么处理

针对上面的两个问题,按顺序介绍解决方案,以及为什么是这样:

  • 删除过期键?

    挨个检索是不现实的,数量太大,如果停下来去专门清理,则会影响到主要的业务,那么就需要其他的策略。但是删除前需要准确地找到设置了过期时间的键,这涉及到redis的内存是怎么组织的(键管理)。

    (这个图我不会画,也画不好,因此找到了网上几篇优秀的博客的图片并附上链接以作补充)

    图片 普通的键值对存储 较完整的redis键管理
    来源 一文讲清楚Redis 内存模型,Redis 的快是有理由的! - 知乎 (zhihu.com) 详解 Redis 内存管理机制和实现 - 知乎 (zhihu.com)

    左图是一对键"hello"->"world"的存储模型,如果是默认的存储(默认redis创建16个db,redis-cli连接到redis-server使用的是db0),并且没有设置过期时间,就是存到db0的redisDb中的dict下,table指向dictEntry按顺序往下存储,dictEntry的组织形式如图所示。内存模型传递的一个信息很重要,也就是设置了过期时间的键存储在一起的,这也是redis可以随机删除过期了的键的基础,不然删除时找一个键是永久的,再找一个还是永久的,删除过期的键这个任务又要快速,岂不是这次任务执行的效率极低?

    从内存模型扯回来谈过期策略。redis提供了两种过期策略,分别是:

    • 惰性删除: 惰性删除很好理解,当有人要用到这个键,查到键是在过期字典里,那先判断是不是过期了,如果过期了就不返回,并且将键删除。可能有人有疑问,既然还在内存中,已经有请求想要访问这个键,为什么不返回一次再删除?我个人的理解是绝对不可以返回,有几点理由:
      • 返回不符合逻辑:已经过期的键,理想状态下就应该不存在。我是被动地让它存在在内存中,如果我有更好的办法能让它自动消失,它早已不存在,返回的话语义不一致。
      • 可能造成错误:这个要根据场景来具体地考虑。比如存储token,如果token已经过期,那么用户携带的token不应该能通过登录,如果还能成功返回用户就可能登录成功访问账户里的资源,这一操作可能是危险的。(比如token过期了几天,这个键值对都好运地没有被删除)
    • 定时删除: 这是一个相对复杂的算法。现在我们已知的是,所有存放了过期时间的键已经码好了,排成一排放在那,redis提供的策略是每秒扫描 10 次,即100ms检查一次是否有键过期,这是可以通过配置调整的。不过这一过程不能扫描全部,上面也提到这样做会阻塞线程,导致主要的工作长时间不响应,本身redis就是用来应对高并发,这是致命的。那么具体是怎么做的呢?首先推荐一篇博客,从源码级别来解读,并且条理清晰:Redis学习笔记(三)redis 的键管理 - 归思君 - 博客园 (cnblogs.com)不过,既然作为我自己的学习笔记,一定要留下我的理解和记录,大致流程——从过期字典中随机抽取20个键进行删除,如果删除超过25%就再次执行,再抽取20个键删除,直到删除的个数小于等于25%,这是do-while循环中做的。并且会确定一个执行删除算法的时长,如果执行删除算法的时间太长,则会退出这个删除过程,默认删除过程最多执行25ms左右。也即如果这时有key想要set,最多也就等待25ms。redis删除的操作显得格外小心,以提供安稳的服务,这对于我们应用开发者有启示吗?当然是有的。这提示我们要设置合理的过期时间,在应用程序中也要精打细算,尽可能不然大量的key在同一时间过期[2],那么最佳实践是如果有很多key要一起放入redis中的时候,最好将过期时间分散一下,在”应用需要的过期时间后“加上一个随机的散列值,使得删除时的循环尽可能地早退出。
  • 内存(快)满了怎么办?

    即便有过期时间的限制,redis依然有可能被“挤满”,这是不可避免的。而redis无法控制应用程序的行为,那么只能本身提供坚强的服务,当内存满了的时候,redis应该怎么做能让自己运行的更久,这是redis的开发者应该考虑的事情。

    没有什么别的办法,内存满了就只能删除,即常常提到的内存淘汰。首先是时机,redis有很多监控自己状态的指标,这里用到的是maxmemory。字面意思,当使用的内存达到了这个值,那么redis就认为自己已经存满了,就要执行一些内存淘汰策略来释放自己的空间。主要有以下几种策略:

    • noeviction:不淘汰任何数据,当内存不足时,执行缓存新增操作会报错,默认
    • allkeys-lru:淘汰整个键值中最久未使用的键值。
    • allkeys-random:随机淘汰任意键值。
    • volatile-lru:淘汰所有设置了过期时间的键值中最久未使用的键值。
    • volatile-random:随机淘汰设置了过期时间的任意键值。
    • volatile-ttl:优先淘汰更早过期的键值。
    • **volatile-lfu: **淘汰所有设置了过期时间的键值中最少使用的键值。
    • **alkeys-lfu: **淘汰整个键值中最少使用的键值

    alkeys 开头的表示从所有键值中淘汰相关数据,而 volatile 表示从设置了过期键的键值中淘汰数据。


  1. 很多人盲目地引入redis技术,其实单访问数据库不是不可以,数据库也是有缓存的,如果并没有特别高性能的访问需求,没有必要一定引入redis技术,要根据实际情况来选择技术。多一个redis服务也是要吃服务器的资源的。 ↩︎

  2. 这么做不止对减少删除所用时间有好处,与后面介绍的“缓存雪崩”有关,这是实际开发当中会遇到的一个具体的问题,最佳实践与之相同,可谓“一箭双雕”。 ↩︎

标签:服务,删除,过期,基础,redis,键值,内存,淘汰
From: https://www.cnblogs.com/pidanhub/p/18254967

相关文章

  • 【接口自动化测试】第一节.接口自动化测试基础和框架介绍
    文章目录前言一、接口自动化基础   1.1接口自动化基础介绍   1.2接口自动化测试流程   1.3选取自动化测试用例   1.4搭建自动化测试环境二、接口自动化测试框架   2.1接口自动化框架设计思路   2.2定义项目目录结构总结前......
  • Linux项目开发,你必须了解Systemd服务!
    1. Systemd 简介Systemd是什么,以前linux系统启动init机制,由于init一方面对于进程的管理是串行化的,容易出现阻塞情况,另一方面init也仅仅是执行启动脚本,并不能对服务本身进行更多的管理。Systemd就是为了解决这些问题而诞生的。它的设计目标是,为系统的启动和管理提供一套完整的解......
  • Python编程基础:f-字符串格式
    本文探讨使用Pythonf-字符串格式,也称为“格式化字符串文字”。f-string是格式化字符串的一种很好且简单的方法,适用于Pythonv3.6+。如果你仍然使用.format()方法,必须了解f-字符串。使用字符串格式的优势之一是能够“插入”并格式化字符串数据中的变量。Python字符串format()方......
  • 网络基本认知(1)--网络基础知识
    实验目的和要求理解和掌握有关网络的概念、分类、组成等基本知识。通过使用网络,了解a网络的基本功能。网络性能对网络使用者来说至关重要,理解影响网络的使用有关因素。通过对互联网的认知,从某一方面探讨对《互联网+》中的“+”理解,并谈一谈您的想法。(宋体小四或......
  • 认识Redis
    认识RedisRedis是目前最受欢迎的NoSQL数据库之一;db-engines排名上,所有数据库类型排名第六,键值对数据库排名第一。Redis是用C语言编写的开源、支持多种数据结构、支持网络、基于内存、可选持久性的键值对内存型数据库,具备以下特征:基于内存运行、效率高单线程运行支持分布式......
  • C基础0613作业
    练习一使用二维数组计算杨辉三角11112113311464115101051.....#include<myhead.h>intmain(intargc,constchar*argv[]){ intn; printf("Pleaseentertherank:"); scanf("%d",&n); intarr[n][n],i,j; for(i=0;i......
  • 部署YUM仓库及NFS共享服务
    部署YUM仓库及NFS共享服务部署YUM软件仓库准备网络安装源(服务器端)配置软件仓库位置(客户端)使用yum工具管理软件包查询软件包安装、升级、卸载软件包NFS共享储存服务使用NFS发布共享资源在客户机中访问NFS共享资源部署YUM软件仓库借助于YUM软件仓库,可以......
  • 【暑假Python上岸计划】最新20+Python实战案例,全程干货,30天看完即可接单就业!(基础+进阶
    前言今天给大家分享20+个基于python的实战案例,主要包含:数据分析、可视化、机器学习/深度学习、时序预测等,案例的主要特点:*提供源码:代码都是基于jupyternotebook,附带一定的注释,运行即可*数据齐全:大部分案例都有提供数据,部分案例使用内置数据集学习资料已打包,需要......
  • 【面试八股总结】Redis数据结构及底层实现
    一、五种基本数据结构        Redis提供了丰富的数据类型,常见的有五种数据类型:String(字符串),Hash(哈希),List(列表),Set(集合)、Zset(有序集合)结构类型结构可存储值结构读写能力使用命令底层数据结构String字符串、整数或浮点数对字符串或字符串的一部分进行操作,对整数或浮点......
  • 部署YUM仓库及NFS共享服务
    部署YUM软件仓库借助于YUM软件仓库,可以完成安装、卸载、自动升级rpm软件包等任务,能够自动找并解决rpm 包之间的依赖关系,而无须管理员逐个、手工地去安装每个rpm包,使管理员在维护大量Linux服务器时更加轻松自如。特别是在拥有大量Linux主机的本地网络中,构建一台“源”服务器可......