`

Redis原理与简述

阅读更多
Redis是一个开源的key-value存储系统。
      与memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希表、列表、集合、有序集合以及基于这些数据类型的相关操作。
      Redis使用C语言开发,在大多数像Linux、BSD和Solaris等系统上无需任何外部依赖就可以使用。Redis支持的客户端语言非常丰富,常用的计算机语言如C、C#、C++、Object-C、PHP、Python、Java、Perl、Lua、Erlang等均有可用的客户端来访问Redis服务器。当前Redis的应用已经非常广泛,国内像新浪、淘宝,国外像Flickr、Github等均在使用Redis的缓存服务。

3)port 6379指定redis运行的端口,默认是6379;


Redis的常用数据类型
   与memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要有五种:String、Hash、List、Set和Sorted Set。

redis核心对象  

                      redisObject

Redis内部使用一个redisObject对象来表示所有的key和value。
redisObject最主要的信息如图所示:
      type代表一个value对象具体是何种数据类型
      encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。
       vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。

五种数据类型的使用和内部实现方式:
   1)String
     常用命令:set/get/decr/incr/mget等;
      应用场景:String是最常用的一种数据类型,普通的key/value存储都可以归为此类;
      实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。
  
   2)Hash
     常用命令:hget/hset/hgetall等
      应用场景:我们要存储一个用户信息对象数据,其中包括用户ID、用户姓名、年龄和生日,通过用户ID我们希望获取该用户的姓名或者年龄或者生日;
      实现方式:Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。如图2所示,Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据。当前HashMap的实现有两种方式:当HashMap的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,这时对应的value的redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。
 
    3)List
   常用命令:lpush/rpush/lpop/rpop/lrange等;
    应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现;
    实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。

    4)Set
   常用命令:sadd/spop/smembers/sunion等;
    应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;
    实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。

   5)Sorted Set
  常用命令:zadd/zrange/zrem/zcard等;
   应用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。
   实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。


Redis的持久化
   Redis虽然是基于内存的存储系统,但是它本身是支持内存数据持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。

  RDB快照:Redis支持将当前数据的快照存成一个数据文件的持久化机制。
   但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。
  
   我们可以通过Redis的save指令来配置RDB快照生成的时机,比如你可以配置当10分钟以内有100次写入就生成快照,也可以配置当1小时内有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。
  
   Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。
  
   但是,我们可以很明显的看到,RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的,我们也推荐这些业务使用RDB的方式进行持久化,因为开启RDB的代价并不高。但是对于另外一些对数据安全性要求极高的应用,无法容忍数据丢失的应用,RDB就无能为力了,所以Redis引入了另一个重要的持久化机制:AOF日志。

   AOF日志:AOF日志的全称是append only file,从名字上我们就能看出来,它是一个追加写入的日志文件。
   一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。当然,并不是发送发Redis的所有命令都要记录到AOF日志里面,只有那些会导致数据发生修改的命令才会追加到AOF文件
   那么每一条修改数据的命令都生成一条日志,那么AOF文件是不是会很大?答案是肯定的,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。
   AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的5个流程。那么写AOF的操作安全性又有多高呢。实际上这是可以设置的,在Redis中对AOF调用write(2)写入后,何时再调用fsync将其写到磁盘上,通过appendfsync选项来控制,下面appendfsync的三个设置项,安全强度逐渐变强。
   1)appendfsync no
当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。
   2)appendfsync everysec
当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。
    3)appednfsync always
当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。
  


Redis的内存管理机制
  Redis的内存管理机制主要通过源码中的zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存的头部。
  

  如图所示,real_ptr是redis调用malloc后返回的指针。redis将内存的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的计算出real_ptr的值,然后将real_ptr传给free释放内存。
 
Redis通过定义一个数组来记录所有的内存分配情况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT.数组的每一个元素代表当前程序所分配的内存块的个数,且内存块的个数,且内存块的大小为该元素的下标。 
在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。所以,总的来看,Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。

  
  • 大小: 20.4 KB
  • 大小: 8.5 KB
分享到:
评论

相关推荐

    redis源码日志

    - **目的**: 分享作者在研究Redis源码过程中的心得与体会,旨在帮助读者更好地理解Redis的工作原理。 #### 0.2 从哪里开始读起,怎么读 - **建议**: 作者推荐从基本概念入手,逐步深入到更复杂的主题。 - **方法**...

    Redis开发运维实践指南

    架构与实践中,介绍了主从复制-sentinel架构、高可用原理、发现原理、基本切换原理以及环境搭建部署架构等。 在内存管理方面,Redis提供了丰富的命令和方法来进行内存抽样分析统计,例如生产上比较大的key、查看key...

    Linux+redis实战视频教程.txt

    5. **虚拟机简述与安装** - **虚拟机概念**:虚拟机的基本原理和用途。 - **虚拟机软件选择**:比较常见的虚拟机软件,如VMware、VirtualBox等。 - **虚拟机安装步骤**:详细介绍如何在宿主机上安装虚拟机软件,...

    Memcached、Redis、MySQL存储层面试问题

    5. Memcache与Redis的区别都有哪些? Memcached和Redis都是缓存系统,但是Redis支持更多的数据类型和功能。 MySQL 1. MySQL中有哪几种锁? MySQL中有共享锁和排他锁两种,共享锁可以多个事务同时访问同一个资源,...

    p6机器学习期末理论

    1、字符串常用方法?...9、简述redis主从同步原理? 10、linux常见命令(10个以上)? 11、mysql常见的优化方式有哪些,至少写出五条? 12、post和get的区别是什么,至少写出三条? 13、你常用的mysql引擎有哪些?

    面试真题目录大全,详细版

    1. 机器学习算法(选择一种简述其原理) 2. 新浪网站和头条的新闻推荐算法分析 其他 1. JVM 的参数调整(Xss、Xmx) 2. JVM 的垃圾收集器(CMS、G1等) 3. ThreadLocal 的作用 4. SpringMVC 的 @Autowired 注解...

    解析Python网络爬虫_复习大纲.docx

    本文档是关于Python网络爬虫的复习大纲,涵盖了爬虫的基本概念、实现原理、技术、网页请求原理、抓取网页数据、数据解析、并发下载、抓取动态内容、图像识别与文字处理、存储爬虫数据、爬虫框架Scrapy等知识点。...

    ZooKeeper原理及其在Hadoop和HBase中的应用.docx

    Observer的角色与Follower类似,都能提供读服务,但不参与写操作和选举过程,这有助于在不影响写性能的同时增加系统的可扩展性。在大型分布式系统中,如Hadoop和HBase,ZooKeeper被用作重要的协调组件,确保集群的...

    1000道 互联网Java架构师面试题.pdf和JAVA核心知识整理.zip

    书籍1:互联网 Java 工程师面试题 内容涵盖:Java、MyBatis、ZooKeeper、Dubbo、Elasticsearch、Memcached、 ...27、简述 Mybatis 的插件运行原理,以及如何编写一个插件 等等 书籍2:JAVA核心知识整理

    java面试题,180多页,绝对良心制作,欢迎点评,涵盖各种知识点,排版优美,阅读舒心

    【Redis】Redis的存储结构,或者说如何工作的,与mysql的区别?有哪些数据类型? 133 【Redis】项目中用到redis,为什么选用redis 133 独特的键值对模型 134 内存储存,速度极快 135 丰富的附加功能 136 完善的文档 ...

    基于 visual studio开发的在线聊天室

    可以使用内存数据库如Redis或SQL Server的会话状态管理来存储这些信息。 6. **聊天内容展示** 聊天内容的展示涉及到前端开发。HTML、CSS和JavaScript(可能借助于jQuery或React等库)用于构建用户界面,将服务器...

    PHP网络编程自学手册(完整版源码)

    1. PHP框架:简述常见的PHP框架,如Laravel、Symfony、CodeIgniter等,及其特点和用途。 2. Composer依赖管理:掌握使用Composer安装、更新和管理PHP项目的依赖。 3. PHP扩展:理解PHP扩展的作用,如安装、配置和...

    《Java EE企业级应用开发教程Spring+Spring MVC+MyBatis》_源代码.zip

    9. **Chapter 16** - Spring与缓存:介绍Spring对缓存的支持,如EhCache和Redis。讲解如何配置缓存管理,提高应用程序性能。 10. **Chapter 17** - Spring Boot:简述Spring Boot快速开发框架,如何简化Spring应用...

    高级java笔试题-python-job:Python面试相关知识点汇总个人整理

    熟悉mysql,redis,mongo等常用数据库,具有数据库开发和设计能力; 熟悉linux系统,会熟练编写多进程多线程的程序,熟悉网络编程; 熟悉python异步IO 熟练使用Linux系统,掌握基本命令,可编写简单的shell脚本 了解...

    Guns 技术文档 v5.1.pdf

    - **介绍**:简述了XSS攻击的原理及其危害。 - **原理**:深入分析了Guns中的XSS过滤机制。 - **放过过滤**:介绍了如何配置特定路径使其不受XSS过滤的影响。 ##### 5. 核心思想 - **分包**:阐述了Guns中的...

    数据库基础

    常见的数据库类型包括关系型数据库(如MySQL、SQL Server)、非关系型数据库(如MongoDB、Redis)以及分布式数据库等。在关系型数据库中,数据以表格的形式存储,通过列定义数据类型,行代表具体的数据实例,而表与...

    精品--JAVA 面试宝典和简历模板V3.zip

    8. **框架与库**:熟悉Spring Boot、Spring MVC、MyBatis等主流Java框架,理解其工作原理和使用场景,以及如何进行性能优化。 9. **数据库**:SQL语言基础,事务管理,索引优化,以及NoSQL数据库如MongoDB、Redis等...

    数据库教学指导性资料

    9. NoSQL数据库:简述非关系型数据库的特点和应用场景,对比与关系型数据库的区别。 通过这份教学资料,初学者可以系统地学习数据库的各个方面,从基础理论到实践应用,逐步建立起对数据库的全面认识。同时,配合...

    Guns技术文档

    - **使用Redis**:解释如何使用Redis作为缓存工具。 - **XSS过滤器**:介绍XSS攻击、过滤器原理和配置方法。 ### 5. 核心思想 - **分包**:架构分包的概念和方法。 - **统一异常拦截**:讲解异常拦截机制的设计和...

Global site tag (gtag.js) - Google Analytics