最近写了一篇自己搭建redis集群并在自己项目中使用的文章。今天早上看了别人的面试,发现redis在面试中问的还是比较多的(我是python方向的)。于是查阅官方文档和别人造的轮子,总结一些redis面试学习必须掌握的问题。不可能涵盖所有的细节,尽量把比较常见的写出来。什么是Redis?安装RedisRedis的代码是按照ANSI-C编写的,可以在所有POSIX系统(如Linux、*BSD、MacOSX、Solaris等)上安装运行。而且Redis不依赖任何非标准库,不需要添加编译参数。redis的安装出奇的简单,这可能也是它受欢迎的原因之一,上手容易。Redis是一个用C语言编写的开源键值数据库。.与Memcached类似,它支持相对更多的值类型进行存储,包括string(字符串)、list(链表)、set(集合)、zset(sortedset——有序集合)和hash(散列类型)。这些数据类型支持push/pop、add/remove、intersection、union、difference等更丰富的操作,而且这些操作是原子的。在此基础上,redis支持多种方式的排序。和memcached一样,数据缓存在内存中以保证效率。不同的是redis会周期性的将更新的数据写入磁盘或者将修改操作写入附加的记录文件,并在此基础上实现主从(master-slave)同步。目前,Vmware正在资助redis项目的开发和维护。Redis与Memcached的区别与比较1.Redis不仅支持简单的k/v类型数据,还提供了list、set、zset、hash等数据结构的存储。memcache支持一种简单的数据类型,String。2、Redis支持数据备份,即主从模式下的数据备份。3、Redis支持数据持久化。它可以将内存中的数据保存在磁盘上。重启时可以再次加载使用。Memecache将所有数据存储在内存中。4、redis的速度比memcached快很多。5.Memcached是一种多线程、非阻塞的IO多路复用网络模型;Redis采用单线程IO多路复用模型。想深入了解的话,可以看看慕课上的这篇笔记(非常推荐):《脚踏两只船的困惑 - Memcached与Redis》:www.imooc.com/article/235...Redis和Memcached选择攻略:使用RedisString类型的东西可以用Memcached代替,换取更好的性能;另外,优先使用Redis;使用redis有什么好处?(1)速度快,因为数据是存储在内存中的,类似于HashMap,HashMap的优点是查找和运算的时间复杂度为O(1)(2)支持丰富的数据类型,支持string,list,set,sortedset,hash(3)支持事务,操作是原子的。所谓原子性,就是所有的数据变化要么被执行,要么根本不执行。(4)丰富的功能:可用于缓存、消息、key设置过期时间。普通Redis数据结构过期后会自动删除。使用场景1、String常用命令:set、get、decr、incr、mget等String数据结构是一种简单的key-value类型,value其实不仅可以是String,还可以是数字。常规键值缓存应用;常规统计:微博数、粉丝数等。2.哈希常用命令:hget、hset、hgetall等。哈希是字符串类型字段和值的映射表,哈希特别适合存储对象。比如我们可以使用Hash数据结构来存储用户信息、商品信息等。举个例子:最近一个电商网站项目的首页使用了redis的hash数据结构进行缓存,因为一个网站的首页访问量是最多的,所以通常网站的首页可以通过redis进行缓存,以提高性能和并发。我使用jedis客户端连接和操作我搭建的redis集群或者单机redis。使用jedis可以方便的对redis进行相关操作。总的来说,从搭建一个简单的集群到将redis实现为缓存的整个步骤并不难。有兴趣的可以看看我昨天写的这篇文章:《一文轻松搞懂redis集群原理及搭建与使用》:juejin.im/post/5ad54d...3.列出常用命令:lpush、rpush、lpop、rpop、lrange等。list是链表,而Redis列表的应用场景很多,也是Redis最重要的数据结构之一。比如微博的关注列表、粉丝列表、热搜榜等功能都可以通过Redis列表结构来实现。RedisList实现为双向链表,可以支持反向查找和遍历,操作起来更方便,但是带来了一些额外的内存开销。4、设置常用命令:sadd、spop、smembers、sunion等。set提供的功能与list类似,都是列表功能。特殊之处在于set可以自动排序权重。当你需要存储一个数据列表,不希望有重复的数据时,Set是一个不错的选择,而且set提供了一个重要的接口来判断一个成员是否在一个set集合中,这是list所不能提供的。在微博应用中,可以将一个用户的所有关注者存储在一个集合中,将所有的粉丝存储在一个集合中。Redis可以很方便的实现共同关注、共同喜好、二度好友等功能。5、SortedSet的常用命令:zadd、zrange、zrem、zcard等。与set相比,sortedset增加了一个权重参数score,使得set中的元素可以根据score有序排列。示例:在直播系统中,实时排名信息包括直播间在线用户列表、各种礼物排名、弹幕消息(可以理解为按消息维度的消息排名)等信息,适合在Redis中使用SortedSet结构存储。MySQL有2000万条数据,Redis只有20万条数据。如何保证Redis中的数据都是热数据(redis有哪些数据淘汰策略???)相关知识:当redis内存数据集的大小上升到一定大小时,数据淘汰策略(回收策略)将实施。redis提供了6种数据淘汰策略:volatile-lru:从数据集(server.db[i].expires)中选择最近最少使用的有过期时间的数据进行淘汰volatile-ttl:从有过期时间的数据集中淘汰set(server.db[i].expires)选择即将过期的数据。消除volatile-random:从数据集(server.db[i].expires)中选择有过期时间的数据。Eliminateallkeys-lru:从数据集中选择最近最少使用的数据(server.db[i].dict)Eliminateallkeys-random:从数据集中随机选择数据(server.db[i].dict)淘汰no-enviction(逐出):不逐出Redis数据并发竞争问题如何解决?Redis是单进程单线程模式,采用队列模式将并发访问转化为串行访问。Redis本身没有锁的概念。Redis不存在多个客户端连接的竞争,但是当Jedis客户端并发访问Redis时,会出现连接超时、数据转换错误、阻塞、客户端关闭连接等问题。这些问题都是由于客户端连接混乱造成的。对此有两种解决方案:1、从客户端的角度,为了保证各个客户端正常有序的与Redis通信,将连接池化,客户端的读写采用内部锁synchronized编写Redis操作。2、从服务器的角度,使用setnx实现锁。注意:对于第一种,应用需要自己处理资源同步。可以使用的方法比较流行,可以使用synchronized或者lock;第二种需要使用Redis的setnx命令,但是需要注意一些问题。Redis数据结构Redis的作者Antirez曾将其称为数据结构服务器(datastructuresserver),这是一个非常准确的表述。Redis的所有功能都是将数据保存在其固有的结构中,并提供给用户操作。这些结构的接口。我们可以想象各种语言中的那些固有数据类型及其操作。Redis目前提供四种数据类型:string、list、set、zset(sortedset)和Hash。string是最简单的类型,可以理解为和Memcached一样的类型,一个key对应一个value,支持的操作和Memcached类似。但它的功能更丰富。list是一个链表结构,主要功能有push、pop、获取一个范围内的所有值等等。操作中的key理解为链表的名称。Set就是集合,类似于我们数学中的集合概念。对集合的操作包括元素的添加和删除,以及多个集合的相交和相减等操作。操作中的键被理解为集合的名称。Zset是set的升级版。它在集合的基础上增加了一个序列属性。添加和修改元素时可以指定该属性。每次指定后,zset会根据新值自动重新调整序列。可以这样理解,mysql表有两列,一列存值,一列存序列。操作中的键被理解为zset的名称。Hash数据类型允许用户使用Redis来存储对象类型。Hash数据类型的一个重要优点是,当你存储只有几个键值的数据对象时,数据存储的内存消耗会非常小。更多关于Hash数据类型请参考:http://code.google.com/p/redis/wiki/HashesRedis数据存储Redis存储分为三部分:内存存储、磁盘存储和日志文件。配置文件中有三个参数来配置它configuration。savesecondsupdates,saveconfiguration,指出有多久,多少次有更新操作,数据会同步到数据文件。这个可以结合多个条件,比如默认配置文件中的设置,设置三个条件。appendonlyyes/no,appendonly配置,表示每次更新操作后是否记录日志,如果不启用,可能会导致断电一段时间内数据丢失。因为redis本身是按照上面的save条件来同步数据文件的,所以有些数据只会在内存中存在一段时间。appendfsyncno/always/everysec,appendfsync配置,no表示等待操作系统将数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写入磁盘,everysec表示每秒同步一次。
