Redis服务器将所有数据库都保存在服务器状态redis.h/redisServer结构的db数组中,db数组的每一项都是一个redis.h/redisDb结构,每个redisDb结构代表一个数据库,服务器设置dbnum属性为初始数据库的个数,这个属性一般由数据库服务器配置conf文件中的database节点来配置,默认情况下这个初始值是16。

struct redisServer{    //数据库    redisDb *db;    //服务器数量    int dbnum;};

数据库切换

前面我们说到默认的redis数据库有16个,那么我们如何来切换数据库呢?

127.0.0.1:6379> get name"mango"127.0.0.1:6379> select 1OK127.0.0.1:6379[1]> get name(nil)127.0.0.1:6379[1]> select 0OK127.0.0.1:6379> get name"mango"

默认情况下我们操作的都是第一个数据库,数据库数组索引为[0],我们通过select命令来切换数据库,通过修改客户端的指针,来指向第二个数据库。

注意:这里我们值得注意的是,我们在维护redis的时候执行一些敏感的指令时养成一个习惯就是先切换数据库,然后执行。

数据库键空间

Redis 中的每个数据库,都由一个 redis.h/redisDb 结构表示,下面我们来看看代码。

typedef struct redisDb {    // 保存着数据库以整数表示的号码    int id;    // 保存着数据库中的所有键值对数据,这个属性也被称为键空间(key space)    dict *dict;    // 保存着键的过期信息    dict *expires;    // 实现列表阻塞原语,如 BLPOP    dict *blocking_keys;    dict *ready_keys;    // 用于实现 WATCH 命令,在事务中有提到    dict *watched_keys;} redisDb;

因为Redis本身就是一个字典类型的数据库,我们可以看到在RedisDb中,dict保存数据库的所有键值对数据。

字典的键是一个字符串对象(StringObject)

字典的值则可以包括Redis的五种基础结构的任意一种(字符串、列表、哈希表、集合或有序集),例如:列表就是一个ListObject,哈希就是HashObject等。

如图所示,每个类型对应数据结构不同。

关于Redis数据库的增、删、改、查操作这里就不过多解释了,跟java或是c#中的实现是相似的,只不过对于字典扩容稍有不同,Redis的扩容是一种渐进式的方式,一点点的将旧表迁入新表,不会在扩容的时候阻塞其他操作。

其他操作
除了增删该查的键值操作之外,还有很多针对数据库本身的命令,也是通过对键空间进行处理:
• FLUSHDB 命令:删除键空间中的所有键值对。
• RANDOMKEY 命令:从键空间中随机返回一个键。
• DBSIZE 命令:返回键空间中键值对的数量。
• EXISTS 命令:检查给定键是否存在于键空间中。
• RENAME 命令:在键空间中,对给定键进行改名。

过期设置

数据过期操作命令通过EXPIRE、PEXPIRE、EXPIREAT和PEXPIREAT四个命令,客户端可以给某个存在的键设置过期时间,当键的过期时间到达时,键就不再可用。当然SETEX也是可以的,只不过它是一个限定类型命令(可以说是一个复合命令),跟其他的过期时间设置原理一样。

>set name mango(integer)1>expire name 5    #设置过期时间

过期时间是一个UNIX时间戳,当键的过期时间到了,这个键就会在数据库中被删除。那么我们可以通过TTL和PTTL命令来返回距离过期时间还有多长时间

> SETEX key 10086 valueOK> TTL key(integer) 10082> PTTL key(integer) 10068998

过期时间保存

前面我们给出的RedisDb里面的一个属性dict *expires是保存过期时间的,我们可以看到它也是一个dict键值的指针类型,其中这个过期字典中的是一个long long类型的整数,这个整数保存的是过期时间。下面我们来画一个图加深印象。

注意:这里的过期时间的字典是指向的键空间的,只不过为了区分才这样画的。

如何检测key是否过期?

  1. 检查这个key是否存在expires中

  2. 检查当前时间是否大于过期时间,如果大于则过期,反之未过期

过期key删除策略

Redis设置好过期时间后,如果key的过期时间到期,我们的redis没有及时回收资源可能会导致Redis内存溢出,所以我们需要及时清理过期的key来释放资源。

定时清理:

此方法就是我设置一个定时器,到点了我就去清理已经过期的key。

优点:就是方便简洁,保证key过期及时处理;

缺点:也很明显,扫描整个字典是一个O(n)的时间复杂度,使用这种方式的时候会占用大量的cpu可能会导致服务器卡顿等现象,我们说过Redis尽量避免使用这类的操作,这样处理并不高效。

惰性清理:

这种方式就是客户端请求这个key的时候去判断时间是否过期,过期则清理。

优点:对cup很友好,使用的时候去清理

缺点:对内存不友好,无效key不及时清理内存得不到释放,积压的内存越来越多,如果过期key特别多而且永远不访问,可能会导致内存溢出。

定期清理:

定期删除是结合定是清理和惰性清理的特点选择一个折中处理,一段时间内处理一定量的key,这样减少使用cpu带来的阻塞,一定程度的减少内存积压。

定期清理的难点在于清理算法,也就是说什么时候清理多少key这个量度是很难把握的。

那么我们介绍了这三种清理方式后,Redis的清理过期key的方式是通过惰性清理和定期清理两种策略来实现的。通过这两种方式使Redis在cpu和内存之间取得平衡,这两种方式也是在不同的时期进行的。

过期键对AOF、RDB和复制的影响
前面的内容讨论了过期键对cpu和内存的影响,那么过期键在RDB文件、AOF 文件、AOF重写以及复制中的影响。RDB文件在创建新的RDB文件时,程序会对键进行检查,过期的键不会被写入到更新后的RDB文件中,过期键对更新后的RDB文件没有影响。

AOF文件在键已经过期,但是还没有被惰性删除或者定期删除之前,这个键不会产生任何影响,AOF文件也不会因为这个键而被修改。当过期键被惰性删除、或者定期删除之后,程序会向AOF文件追加一条DEL命令,来显式地记录该键已被删除。AOF重写时程序对键进行检查,过期的键不会被保存到重写后的AOF文件。过期键对重写后的AOF文件没有影响。复制:当服务器带有附属节点时,过期键的删除由主节点统一控制:

• 如果服务器是主节点,那么它在删除一个过期键之后,会显式地向所有附属节点发送一个DEL命令。
  • 如果服务器是附属节点,那么当它碰到一个过期键的时候,它会向程序返回键已过期的回复,但并不真正的删除过期键。因为程序只根据键是否已经过期、而不是键是否已经被删除来决定执行流程,所以这种处理并不影响命令的正确执行结果。当接到从主节点发来的DEL命令之后,附属节点才会真正的将过期键删除掉。附属节点不自主对键进行删除是为了和主节点的数据保持绝对一致,因为这个原因,当一个过期键还存在于主节点时,这个键在所有附属节点的副本也不会被删除。这种处理机制对那些使用大量附属节点,并且带有大量过期键的应用来说,可能会造成一部分内存不能立即被释放,但是,因为过期键通常很快会被主节点发现并删除

总结一下

  1. Redis默认有16个数据库,但如果没有切换那么使用的是第一个默认的数据库

  2. 数据库主要由dict和expires两个字典构成,其中dict保存键值对,而expires则保存键的过期时间。
    数据库的键总是一个字符串对象,而值可以是任意一种 Redis 数据类型,包括字符串、哈希、集合、列表和有序集。

  3. expires的某个键和dict的某个键共同指向同一个字符串对象,而expires 键的值则是该键以毫秒计算的 UNIX 过期时间戳。

  4. Redis使用惰性删除和定期删除两种策略来删除过期的键。

  5. 更新后的RDB文件和重写后的AOF文件都不会保留已经过期的键。

  6. 当一个过期键被删除之后,程序会追加一条新的DEL命令到现有AOF文件末尾。

  7. 当主节点删除一个过期键之后,它会显式地发送一条DEL命令到所有附属节点,而从节点是不会主动删除某个key,这样保证主从一致性问题。

一名正在抢救的coder

笔名:mangolove

CSDN地址:https://blog.csdn.net/mango_love

GitHub地址:https://github.com/mangoloveYu

c# redis hashid如何设置过期时间_Redis数据库实现原理(划重点)相关推荐

  1. c# redis hashid如何设置过期时间_Redis中Key过期策略amp;淘汰机制

    1. Redis中设置Key过期时间 我们有两种方式设置过期时间 1.1 设置多久后过期 设置一个 key 10s 过期,可以这样 127.0.0.1:6379> SET key value E ...

  2. c# redis 如何设置过期时间_Redis Hash存储token、及设置过期时间

    相信大家在很多业务场景都会遇到对数据设置过期时间,如安全认证token.短信验证码等.一般我们的解决有几种:存redis.存数据库.实时计算(如JWT),不管使用哪种方式,需求就是过期了对数据的清理. ...

  3. java redis设置过期时间_Redis的一些核心原理

    点关注,不迷路:持续更新Java相关技术及资讯!!! 一.Redis的单线程和高性能 Redis 单线程为什么还能这么快? 因为它所有的数据都在内存中,所有的运算都是内存级别的运算(纳秒),而且单线程 ...

  4. c# redis 如何设置过期时间_Redis 过期时间与内存管理

    http://www.redis.cn/commands/expire.html http://www.redis.cn/topics/lru-cache.html 内存管理 当 Redis 作为缓存 ...

  5. redistemplate.opsforhash设置过期时间_Redis详解(十一)------ 过期删除策略和内存淘汰策略...

    大家好,我是可乐,一个专注原创,乐于分享的程序猿. 本系列教程持续更新,可以微信搜索「 IT可乐 」第一时间阅读.回复<电子书>有我为大家特别筛选的海量免费书籍资料 在介绍这篇文章之前,我 ...

  6. redis: string类型设置过期时间后 再进行set操作,会清除过期时间

    redis的set操作实际上是: 删除之前的key,再创建一个新的key,所以之前key就会被删除连带赋予的过期时间, 这时我们建议使用setrange 命令进行覆盖操作,避免过期时间被删除. red ...

  7. redis文档翻译_key设置过期时间

    Available since 1.0.0.    使用開始版本号1.01 Time complexity: O(1)  时间复杂度O(1) 出处:http://blog.csdn.net/colum ...

  8. stringredistemplate设置过期时间_Redis的过期删除策略和内存淘汰机制

    Redis的key可以设置过期时间,那是否意味着时间一到就会马上被删除呢? Redis的数据存储大小是有限的,假如内存不足Redis有什么应对策略呢? 本篇文章将介绍一下Redis的过期策略和内存淘汰 ...

  9. springboot开启redis共享session设置过期时间

    开启Redis共享sessions的配置类的注解设置maxInactiveIntervalInSeconds的值,单位为秒,默认值为1800秒 /*** redis-session配置类,默认过期时间 ...

最新文章

  1. Hexo集成Algolia实现搜索功能
  2. Android SDK更新下载失败以及Studio首次安装取消自动下载SDK
  3. 函数(一.return)
  4. android 判断ip地址合法
  5. iec104点号_IEC104报文流程(有常用类型标识解释)
  6. 在wince中添加微软的雅黑字体
  7. easyui datagrid 获得共多少条记录_聊城市优化简化获得电力流程做法在全省供电系统推广...
  8. Apache+tomcat配置集群(1)
  9. 解耦模式--服务定位器
  10. 各历史版本NDK下载地址
  11. putty中文版 v0.61中文绿色软件
  12. html返回按钮 超链接,ppt超链接返回键
  13. 科来网络分析系统与数据包分析
  14. 使用node的Hapi框架搭建后台(一)——搭建项目
  15. 上海万国驾校 科目三考试
  16. Java7 新特性:MethodHandler,MethodHandles,MethodHandles.Lookup用法详解
  17. 亚马逊云科技2022热招岗位
  18. (原创)详解Quartus导出网表文件:.qxp和.vqm
  19. git branch常用分支操作
  20. 使用TortoiseGit将已有的id_rsa转化为ppk

热门文章

  1. 将服务器置于最终用户附近可解决性能问题?—Vecloud微云
  2. OpenCV神经网络ANN代码编译运行与解读(一)
  3. 算法导论笔记:13-02红黑树插入
  4. C# Graphic 绘制圆、三角形、椭圆、图片
  5. Eclipse生成JavaDoc时指定字符集, 避免页面乱码
  6. 系统管理员设置了系统策略,禁止进行此安装
  7. 世界机器人大会特种机器人报到高难度的高危险的活让它们来!
  8. 对vector等STL标准容器进行排序操作
  9. LabVIEW系列—将串口二进制数据转换成ASCII字符
  10. 使用c语言读写netcdf文件,[原][c][netcdf]读取函数