`
905766491
  • 浏览: 31528 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

谈谈Memcached与Redis(二)

 
阅读更多

2.2 Redis的常用数据类型

与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。在具体描述这几种数据类型之前,我们先通过一张图来了解下Redis内部内存管理中是如何描述这些不同数据类型的。
Redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如图1所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:"123" "456"这样的字符串。这里需要特殊说明一下vm字段,只有打开了Redis的虚拟内存功能,此字段才会真正的分配内存,该功能默认是关闭状态的。通过Figure1我们可以发现Redis使用redisObject来表示所有的key/value数据是比较浪费内存的,当然这些内存管理成本的付出主要也是为了给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,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。
2.3 Redis的持久化
Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。我们会在下文分别介绍这两种不同的持久化策略。
2.3.1 Redis的AOF日志
Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。这种方法是非常好理解的,但是一个持续写入的数据库如何生成快照呢?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日志。
2.3.2 Redis的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,所以其性能也会受到影响。
分享到:
评论

相关推荐

    memcache与redis

    通过《谈谈Memcached与Redis》这篇文档,我们可以深入理解这两种技术的原理、优缺点,并根据具体需求选择合适的缓存解决方案。同时,文档可能还会涵盖安装配置、优化技巧以及实际案例分析,帮助读者更好地掌握和应用...

    互联网 Java 工程师面试题1000道500页

    6. **缓存技术**:Memcached和Redis都是高速缓存,面试中会讨论它们的区别、应用场景、数据结构及操作命令。 7. **数据库**:MySQL是常用的SQL数据库,面试会涉及SQL优化、事务、索引、存储引擎等相关知识。 8. **...

    saleor的二次开发,微信支付宝支付加入django,saleor上传文件,商品页修改.zip

    例如,使用Redis或Memcached作为缓存系统,以减少数据库查询;利用Celery或其他异步任务框架处理耗时操作,如发送邮件通知、生成PDF发票等,以提高系统响应速度。 总结来说,这个项目涵盖了Saleor的深度定制,包括...

    存储cache文档+论文.rar

    此外,还有分布式缓存系统,如Memcached和Redis,它们为应用提供高性能的数据缓存服务,特别适用于数据库的读取优化。 在“PD201909300945191818677”这份文档或论文中,可能详细探讨了上述存储技术的实现、优化...

    轻松实现Apache_Tomcat集群和负载均衡

    可以使用分布式会话管理,例如Memcached或Redis来存储会话信息。 2. **修改Tomcat配置**:在每个Tomcat实例的server.xml文件中,添加`<Cluster>`元素,配置集群通信协议(如TCP)和序列化机制。 3. **复制应用程序...

    pHP信电系网站建设设计.zip

    对于性能优化,可以使用索引来加快数据库查询速度,合理设计数据库表结构以减少冗余,以及使用缓存技术如Memcached或Redis来减少数据库访问。 在开发过程中,版本控制工具如Git可以帮助团队协作和管理代码。使用...

    谈谈业务中使用分布式的场景1

    另一种解决方案是利用Memcached这类内存数据库,但效率较低。 **分布式事务**:随着业务复杂度的增加,单体应用的事务管理变得困难。分布式事务解决方案如TCC(Try-Confirm-Cancel),通过预操作、确认和补偿机制...

    谈谈MYSQL那点事.ppt

    架构优化则可能涉及主从复制(Master/Slave)、分表分片、分布式数据库,以及利用缓存服务如Redis或Memcached来缓解数据库压力。此外,优化查询语句、事务管理、数据库设计和数据分布也是提升性能的关键。例如,避免...

    互联网高频Java后端面试题20道(适合1~3年)V1.0.46.docx

    问题 13:请解释 Redis 与 Memcached 的异同,以及它们各自适用的场景。答案:Redis 和 Memcached 都是高性能的内存数据存储,常用于缓存。Redis 支持更多数据结构(如字符串、列表、哈希表等),支持持久化,可以...

    气泡提示与文本框绑定事件与缓存

    在服务器端,应用可能会使用内存缓存(如Redis或Memcached)或数据库缓存来加速数据检索。 综合以上,气泡提示和文本框绑定事件关注的是提升用户体验和增强交互性,而缓存技术则旨在优化性能和响应速度。在实际项目...

    海量数据库的查询优化及分页算法方案 - CSDNBlog

    4. **数据库缓存**:使用如Redis或Memcached等内存数据库作为缓存,可以存储经常访问的数据,减少对硬盘的读取,提高响应速度。 5. **分区和分片**:将大表分为多个小表,可以分散负载,提高查询效率。分区通常是...

    nginx+tomcat的负载均衡session共享和ant构建全流程

    2. 共享存储:使用Redis、Memcached等缓存服务作为共享存储,将Session数据持久化并由所有Tomcat实例访问。 3. 使用Cookie或URL重写来携带Session ID,让服务器根据ID查找对应的Session。 接下来,我们谈谈ANT。Ant...

    大型网站技术架构:核心原理与案例分析

    3. **缓存技术**:为了加速数据访问,大型网站会广泛使用缓存,如Redis或Memcached,以减少数据库的读取压力。缓存策略包括页面缓存、对象缓存和数据库查询缓存等。 4. **数据库集群**:单一数据库难以应对大量并发...

    PHP实例开发源码—DSShop TP5框架B2C开源商城源码(单店铺).zip

    8. **性能优化**:缓存技术的应用,如页面静态化、Redis或Memcached的使用,以提高系统响应速度。 9. **SEO优化**:通过设置元标签、URL重写等方式提高搜索引擎的友好性,提升网站的流量。 10. **移动适配**:考虑...

    网络游戏-无线数据网络中的分布式缓存和再分布系统及其方法.zip

    常见的分布式缓存系统有Redis、Memcached等,它们能够提供高并发、低延迟的数据访问。 其次,无线数据网络环境下的网络游戏需要面对带宽限制、网络抖动等问题。分布式缓存通过预加载热门游戏资源到离玩家最近的缓存...

    Galbanum.Orm源代码

    本地缓存适用于单机应用,而分布式缓存适用于多服务器环境,例如使用Redis或Memcached。通过合理利用缓存,可以显著降低数据库负载,提升系统响应速度。 再来说说Galbanum的Logger模块。日志记录对于软件的调试、...

    vagrant安装包2.2.19 windows

    Homestead是Laravel官方推荐的开发环境,它是一个预配置的Vagrant Box,包含了开发Laravel应用所需的所有组件,如Nginx web服务器、PHP、Composer、MySQL、PostgreSQL、Redis、Memcached等。使用Homestead,开发者...

    服务器端代码(异步,大并发)

    6. **缓存优化**:使用缓存(如Redis或Memcached)来减少对后端数据库的访问,降低延迟,提升性能。 7. **数据库优化**:例如使用主从复制、分区、索引等策略,提高数据库的并发处理能力。 8. **硬件升级**:增加...

    PHP面试题(最牛)

    - **缓存机制**:使用缓存策略减轻数据库压力,如Memcached或Redis。 #### 7. PHP的意思 PHP是Hypertext Preprocessor的缩写,是一种通用开源脚本语言,尤其适用于Web开发,可以嵌入HTML中。 #### 8. MYSQL取得...

    一份超级全面的PHP面试题

    - **缓存机制**:使用如Redis等缓存技术来存储常用查询结果,减少数据库负担。 ### 7. PHP的意思(送1分) - **知识点**:PHP代表“PHP: Hypertext Preprocessor”,是一种广泛使用的开源服务器端脚本语言。 ### ...

Global site tag (gtag.js) - Google Analytics