`

从redis谈数据结构

 
阅读更多

     说到redis,最近可是挺火的呀,越来越多的互联网公司都开始使用了,所以我最近也研究了一下,顺带把我的理解写下来,如果有什么问题的话,请指正.

 
首先redis相比memcache一个很不一样的一点就是支持一些复杂的数据结构,比如list,set ,sorted set,hash等,所以我们就先从这些数据结构入手,进行讲解
 
1.list 列表
这个是一个非常常见的数据,相应的实现也有多种,比较常见的是基于数组和基于链表的(比如java中的ArrayList和LinkedList)
那我们先了解到最开始的两个数据结构了
数组:别告诉我这个你不懂 ,new String[3]这样的用过吧??这个结构最简单了
这个结构有个好处就是通过索引来定位数据非常快,但是呢,增加,删除数据的时候就麻烦了,需要移动大量的指针,就好比排队买枣糕王,前面的人买好走了,那是不是大家都要移动??而且我们查找人的时候经常还会需要根据具体的值来查找,比如排队的时候,我们要找具体某个人,我们一般不会知道它在队列中的索引,而只知道TA的名字,这个时候,就需要遍历整个队列来寻找了(众人:你不会叫名字呀???不是一下就找到了?? 我: -_-!!! 数组中的数据也这么智能的话可以考虑...)
于是,下面这位同学登场了
链表:为了简单,我就拿单向链表举例,大概就是长这个样子(一图胜千言):
      

 
 
     上面这个图不知道大家看懂没(画图是我的硬伤.....),不过这个链表相比数组肯定是复杂了一些,但是也带来了一些好处,就是我们修改的时候方便了,在我们增加和删除节点的时候,只需要改一下链接就行了,时间复杂度为o(1) .什么??你不懂啥叫时间复杂度... 
     好吧,我简单介绍下啥叫时间复杂度,首先时间复杂度一般涉及查找和修改(添加,删除)的时间复杂度.简单你可以理解为CPU在处理你的查找或者修改的时候需要执行的时间度量.举个例子吧,比如刚才的数组,你如果要根据值查找的话,需要遍历整个数组(假设数组长度为n)来寻找,那就是让CPU去运行n次对比的操作(虽然实际对比次数<=n),那我们就说查找的时间复杂度是o(n),插入和删除的时候我们也可能移动n个数据的位置,所以修改的时间复杂度也是o(n),也就是说,这里的时间复杂度只是一个大体的估计,或者说叫一个时间的数量级吧.
     了解了时间复杂度,就可以知道链表增加和删除节点的代价是很小的,但是,查找数据怎么办呢??还是o(n)的复杂度呀?这个问题等下我再回答,因为这里讨论的是list的实现,用这里的知识就可以了
     redis中list的实现有两种,一种是ziplist,还有一种就是linkedlist,ziplist我就不介绍了,就是linkedlist的一种优化,这里主要讲解的是linkedlist,这里使用的是双向链表,和单向链表不同的地方就是多了一个指针指向前一个节点,这样可以方便的进行逆向的遍历
     既然list是用双向链表实现的,那就会有链表的特点,可以看到lpush的时间复杂度为o(1),而查找比较慢,比如根据数值删除的操作lrem复杂度为o(n)
 
2.set 无序集合
     说到set,在java中,大家用的最多的应该是hashset吧,其实hashset就是更加常用的hashmap实现的,而redis中的set实现有两种,一种是intset,还有一种是hashtable实现的set,intset算是一种特定的优化版本,在数据量小,并且set中是数值的时候,会使用,如果超过了一定量(set_max_intset_entries参数指定,默认512),就会变成hashtable版本的,而intset实际上就是普通的数组结构,所以接下来主要介绍的还是hashtable的实现
     hashtable(哈希表)就是为了解决我们刚才说的查找数据慢产生的,大体上是由hash算法 + 数组 + 链表实现的(听起来就感觉比较强大吧^^),简单的说,就是把需要存储的数据先均匀的进行分组(hash + 数组),之后,数组中存储的元素是一个链表,链表中将相同hash值的元素串起来,这样在进行搜索的时候,就可以通过hash迅速的定位到数据了,所以我们看到sismember的时间复杂度是o(1),而且由于元素以链表进行组织,修改的时间复杂度也是o(1),哈哈,多么强大的数据结构呀,这似乎已经完美了......但是,我们忘了重要的一点,它是无序的,所以我们还需要下面这个数据结构来做支撑.
 
3.sorted set 有序集合
     说到排序,这个也算是算法中很重要的一部分了,还记得那些冒泡,快速,选择排序等么,这些都是为了提高排序的速度产生的,但是它们是基于已经存在的数组,而我们这里的排序是数据在进行修改的时候进行的,也就是说,你添加和删除元素的时候,就保证了数据是有序的了,而且你还需要保证查找的速度够快,这个可不是一个简单的问题,为了让这几个条件都满足,各种数据结构都出现了(所以也就没那么简单了),比如数据库和文件系统中常用的B+tree,还有常见的平衡二叉树--红黑树,还有我们就是redis的sorted set的实现--skiplist,也许你会问为啥不用红黑树,我觉得是因为实现难易程度的原因,skiplist实现起来比较简单,而且各方面性能和红黑树差不多,查找,修改的复杂度都为log(n) (指数为2).
     redis中的sorted set其实并不是简单的由skiplist实现的,它还使用了一个hashtable来存储 数据与score的映射(这里提一个疑问,不知道为啥,redis的作者把zskiplist的定义写在了redis.h中,而没有单独放到一个文件里),实际上skiplist中已经存储了score了,把数据做冗余应该是为了提高查询的速度.
     
     今天就写到这里吧,其实之前总是觉得java程序员好像不需要学习数据结构,算法这些吧,但是最近渐渐的发现,其实这些都是基础,不管是学习什么语言都应该掌握,可能我们不会自己去实现这些数据结构和算法,但是了解了这些,你才能更好的去使用基于这些基础搭建起来的软件,才能使用的更加得心应手^^
 

 

 

  • 大小: 8.4 KB
1
0
分享到:
评论
2 楼 zh_harry 2013-07-23  
redis我挺熟的,不要脸一把
1 楼 sharewind 2013-03-18  
牛人啊,膜拜一下

相关推荐

    Redis之基本数据结构

    相当于LinkedList队列-右边进左边出栈-右边进右边出ltrim截取hash字典-相当于hashmapset集合-相当于hashSetzset有序集合-相当于sortedSet容器型数据结构通用规则 如果不能深入地了解系统,技术和框架背后的深层原理...

    Redis应用场景--Redis作者谈Redis应用场景

    Redis通过`List`数据结构能够高效地支持此类场景。 - **实现步骤**: - 使用`LPUSH latest.comments &lt;ID&gt;`命令将新评论的ID添加到列表头部。 - 使用`LTRIM latest.comments 0 5000`确保列表长度保持在5000以内。 ...

    exceptionOne-redis-master.zip windows 解压可用的redis压缩包

    它支持多种数据结构,如字符串、哈希、列表、集合、有序集合,这使得Redis在处理复杂的数据操作上具有极大的灵活性。 标题中的"exceptionOne-redis-master.zip"表明这是一个包含Redis服务器的压缩包,可能是某个...

    session共享之memcache Redis

    2. **Redis**:与memcache类似,Redis也是内存数据库,但它支持更多数据结构(如字符串、哈希、列表、集合等),因此在处理复杂数据时更为灵活。在处理Session时,我们可以将Session ID作为键,Session数据作为值...

    Redis基础笔记总结

    - **总结**: Redis凭借其高性能、丰富的数据结构和强大的功能集,在缓存、消息队列、排行榜等领域有着广泛的应用。 #### 二、Redis下载 - **官网地址**: - 英文: &lt;https://redis.io&gt; - 中文: - 文档: ...

    美团redis实践

    在内存使用优化方面,美团提出了一些针对性的解决方案,比如根据实际的使用场景选择合适的数据结构,将存储string类型数据的key转化为hash类型来优化内存使用。具体操作是将原本存储一个用户信息的string类型key分解...

    浅谈redis在项目中的应用

    5. 数据结构操作:Redis支持多种数据结构操作,包括字符串、列表、集合、有序集合和哈希表。在插入信息和获取信息的示例中,演示了如何使用列表数据结构存储和读取数据。 6. 数据持久化:Redis支持RDB和AOF两种持久...

    Redis小记

    1. **数据类型**:Redis支持五大数据类型,包括字符串(String)、哈希(Hash)、列表(List)、集合(Set)和有序集合(Sorted Set),这些数据结构提供了多种操作和功能,满足不同场景需求。 2. **持久化**:为保证数据安全...

    浅谈Redis数据库的键值设计

    Redis作为一个高性能的键值存储系统,其丰富的数据结构(如字符串、哈希、列表、集合、有序集合等)为开发者提供了极大的灵活性。与关系型数据库不同,Redis允许开发者直接操作数据结构,从而在设计键值时需要更深入...

    浅谈Redis在分布式系统中的协调性运用

    Redis,作为一个高性能的键值存储系统,因其丰富的数据结构和高效的内存操作,常被用于实现分布式环境下的协调任务。本文将深入探讨Redis如何在分布式系统中发挥协调作用,尤其是在进程调度、线程管理和消息队列中的...

    Redis_TIA_Liberty:工具实战谈Redis

    它支持多种数据结构,如字符串、哈希、列表、集合、有序集合,这使得Redis在处理复杂的数据操作时具有很高的效率。在本教程“Redis_TIA_Liberty”中,我们将深入探讨如何利用Redis进行实际的开发工作,结合...

    redis-65-3.2.100

    REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-...它通常被称为数据结构服务器,因为值(value)可以是 字符串(String), 哈希(Map), 列表(list), 集合(sets) 和 有序集合(sorted sets)等类型

    浅谈python处理json和redis hash的坑

    如果这些数据需要写入Redis的hash结构中,会遇到问题,因为JSON格式的字符串不包含Unicode字符标识。所以,在写入Redis之前,需要将unicode字符串转换成普通的字符串。 其次,作者提到JSON格式要求所有的key都必须...

    自用学习的项目.结合maven聚合,redis,mysql主从复制,dubbo,以及一系列该并发的前沿技术的项目.zip

    了解Redis的数据结构(如字符串、哈希、列表、集合和有序集合)以及命令操作对于高效利用Redis至关重要。 MySQL主从复制是数据库高可用性和数据冗余的一种常见方案。在这个项目中,你会学习如何配置MySQL的主从复制...

    Nginx-Windows版

    其特点是数据结构丰富(如字符串、哈希、列表、集合、有序集合等),支持事务、持久化和主从复制,且具备高性能、低延迟特性。在处理高访问量的Web应用时,Redis常常被用作热点数据的缓存,以减少对后端数据库的访问...

    浅谈分布式锁的几种使用方式(redis、zookeeper、数据库)

    Redis是一个内存数据结构存储系统,其速度非常快,适合实现锁。使用Redis实现分布式锁通常有两种方法:`SETNX`命令和`lua`脚本。`SETNX`命令在键不存在时设置键值,实现互斥锁。为了防止锁不能被释放(例如,客户端...

    缓存技术浅谈

    7. **源码分析**:文章可能深入到具体缓存库的源码层面,如分析Guava Cache的工作原理,或者Redis的数据结构和操作命令实现。 8. **工具应用**:可能介绍了一些用于缓存管理、监控的工具,例如JMX监控缓存命中率,...

    浅谈分布式锁

    2. 基于缓存实现:常见的缓存组件有Redis,利用Redis提供的数据结构(如setnx命令)和特性(如过期时间设置)来实现分布式锁。但要注意Redis的复制是异步的,且单点故障可能会导致锁失效。 3. 基于ZooKeeper实现:...

    缓存应用的实践分享,项目中实际使用

    科云平台主要使用Redis提供的数据结构,如key-value、hash、zSets和list。key-value适用于简单的键值对存储;hash适合存储单个实体数据和查询索引;zSets用于范围查询索引;而list则常作为消息队列使用。 ### 缓存...

Global site tag (gtag.js) - Google Analytics