Redis学习总结

Redis

Redis 是完全开源免费的,遵守BSD协议,是一个高性能的key-value数据库。
  • Redis支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。
Redis的优势:
  • 性能极高 - Redis读的速度可达110000/s,写的速度81000次/s
  • 丰富的数据类型
    • String List Hashe Set Ordered Set数据类型
  • 原子性,Redis的所有操作都是原子性,要么成功要么失败
  • Redis支持puglish/subscribe,通知,key过期等特性
什么是BSD协议?
  • BSD开源协议是一个给于使用者很大自由的协议。可以自由的使用,修改源代码,也可以将修改后的代码作为开源或者专有软件再发布
首先呢,说说它的安装和初步使用
  • 1.通过官网等路径,,下载redis版本的压缩包
    • Redis-3 .2.100 -Windows- 32.zip
  • 2、解压后会有一个Redis文件,这就是我们要操作路径等信息,
    • 注意,因为在linux下安装,redis是c++写的,所以要先进行编译
      • make --编译命令
    • 建议,将核心配置redis.windows.conf(因为安装的是windows版本的,所以这里多了windows)文件做一个备份文件,就在当前文件夹新建就可以
    • redis的配置:
      • 表明在后台运行建议开启 deamonize yes;
      • 注释bind 127.0.0.1 本地连接
      • 修改protected mode no :关闭保护,才可以远程连接
  • 3、使用命令启动redist服务
    •  
      redis-server myconf / bgredis .conf < ! -- 这里可以是备份的文件 -->
      //添加 ./ redis-server 才可以运行
      < ! -- 若启动失败,可以直接在 Redis 目录下启动 redis-server .exe 也可 -->
  • 4、进入redis中
    •  
      redis-cli -p 6379 ( 6379 redis 默认的端口号)
  • 5、测试redis是否可用
    •  
      ping 可用情况下为 PONG 若不可用是没有下文的
  • 6、停redis服务
    •  
      shutdown not connected >关闭
  • 7、退出
    •  
      exit
 
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。
Redis 客户端可以订阅任意数量的频道。
下图展示了频道 channel1 , 以及订阅这个频道的三个客户端 —— client2 、 client5 和 client1 之间的关系:
当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端:

实例

以下实例演示了发布订阅是如何工作的。在我们实例中我们创建了订阅频道名为  redisChat :
redis 127.0 . 0.1 : 6379 > SUBSCRIBE redisChat
 
Reading messages ... ( press Ctrl - C to quit ) 1 ) "subscribe" 2 ) "redisChat" 3 ) ( integer ) 1
现在,我们先重新开启个 redis 客户端,然后在同一个频道 redisChat 发布两次消息,订阅者就能接收到消息。
redis 127.0 . 0.1 : 6379 > PUBLISH redisChat "Redis is a great caching technique"
 
( integer ) 1
 
redis 127.0 . 0.1 : 6379 > PUBLISH redisChat "Learn redis by runoob.com "
 
( integer ) 1
 
# 订阅者的客户端会显示如下消息 1 ) "message" 2 ) "redisChat" 3 ) "Redis is a great caching technique" 1 ) "message" 2 ) "redisChat" 3 ) "Learn redis by runoob.com "
 
 
基本命令
  •  
    set key value 赋值
    get key 取值
    select index 切换库( redis 里面有 16 个仓库)
    dbsize 查询当前库中中的数据个数
    flushdb 清空当前库
    flushall 清空所有库
    keys * 查看所有 key
    ? 匹配一个字符
    [] 匹配括号内的任意字符,可以使用 - 表示一个范围,如 a-b
    exists key 判断键是否存在,存在返回 1 ,否则返回 0
    type key 返回参数的类型
    move key db 将参数剪切至其他库
    expire key time (秒) 给指
    ttl key 查看还有还有多少秒过期
    gettest key valud 获取旧值,设置新值
    strlen key 返回长度
  • 定的参数设置过期时间
数字命令
  •  
    incr key key 中存储的数字加一
  •  
Hash哈希
  • hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。类似Java里面的Map <String,Object>
  • hset key field value hash 添加一个键值对,字段名为 name
    hget key field hash 方式获取
    hmset key field value field value 存储一个或多个参数
    hmget key field field 获取一个或多个参数
    hgetall key 获取哈希表中指定 key 的所有字段和值
    hdel key field field 删除一个或多个哈希表字段
    hkeys key 获取所有哈希表中的字段
    hvals key 获取哈希表中所有的值
     
    hlen key 获取哈希表中字段的数量
    hexists key field 查询哈希表中 key ,指定的字段是否存在,存在为 1 ,反着为 0
    hincrdy key field value 为哈希表中的指定字段的整数值加上 value 的值( value 必须为数字)
    hincrbyfloat key field value 为哈希表中 key 的指定字段加浮点数值
  •  
使用java代码实现
  •  
    Jedis jedis = new Jedis ( "localhost" );
    //测试
    System . out . println ( "jedis ping " + jedis . ping ());
    //添加一个参数
    jedis . set ( "alone" , "2" );
    //检查获取参数
    System . out . println ( "jedis : " + jedis . get ( "alone" ));
List
  • redis中的list与java中的list是不一样的,java中list底层是数组,而redist中的list是链表,
  • Redis list的应用场景非常多,例如微博的关注列表,粉丝列表等,
  • 使用list结构,可以轻松实现最新消息排行的功能
基本命令:
  •  
    lpush key value1 [ value2 ..] 将一个或者多个插入到列表头部(允许值重复)
    rpush key value1 [ values2 ..] 将一个或者多个插入到列表尾部(允许值重复)
    lrange key startindex endindex 获取指定范围内的元素( 0 -1 获取全部)
    lindex key index 通过索引获取列表中的元素
    llen key 获取指定 key 值的个数
    lpop key 移除并获取列表中的第一个元素
    rpop key 移除并获取列表最后一个元素
    rpoplpush list1 list2 要求吧 list1 中的尾元素放入 list 头部
  •  
    lrem key count value 例如有多个相同的值,删除几个相同的值
    ltrim key start end 对一个列表进行修剪( trim ),就是说,让列表只保留指定区间内的元素,不在指定区间之内的元素都将被删除
    lset key index values 通过索引设置列表元素的值
    linsert key BEFORE | AFTER value1 value 在列表指定的元素前或者后插入元素
Set
  • Set是String类型的无序集合,它通过HashTable实现的,线程是安全的
应用场景:
  • set集合的概念就是一堆不可重复值的组合,
  • Redis 的 Set 是 String 类型的无序集合。集合成员是唯一的,这就意味着集合中不能出现重复的数据。
  • Redis 中集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是 O(1)。
常用命令:
  •  
    sadd key value1 [ value2 ..] 向集合中添加一个或多个成员
    srem key value 删除集合中指定元素
    smembers key 返回集合中的所有成员
    scard key 获取集合里面的元素个数
    sismemeber key member 判断 member 元素是否是集合 key 的成员
    spop key [ count ] 移除集合中一个随机元素并返回这个元素
    srandmemeber key [ count ] 随机返回集合中一个或多个值
    sdiff key1 key2 返回给定所有集合的差集
    sinter key1 key2 返回给定所有集合的交集
    sunion key1 key2 返回给定所有集合的并集
Zset
  • zset 和 set也是String类型元素的集合,且不允许重复的成员,不同的事每个元素都会关联一个double 类型的分数,redis正是通过分数来为集合中的成员来进行从小到大排序的,
  • zset成员唯一,分数(score可以重复
应用场景:
  • Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序
常用命令:
  •  
    zadd key score1 member1 [ score2 member2 ] 向有序集合添加一个或多个成员,或者更新已存在成员的分数
    zrange key startindex endindex [ withscores ] 通过索引范围返回指定成员, withscores 携带分数
    zscore key member 返回集合中,成员的分数值
    zrangebyscore key min max [ withscores ] 通过分数返回集合指定区域的成员
    zrem key member [ member ..] 删除一个或多个
    zcard key 获取集合中所有的成员数
redis类型使用场景
  • String类型
    • String 类型是二进制类型,可以将图片和视频,保存起来,例如一些静态文件,如js、css
  • list类型
    • list类型是双向链表结构,例如微博中我的关注或者论坛中所有回帖用于的数据等等,例如一个简单的评论消息,双向链表,
  • set类型
    • set类型是无序类型,在redis中是通过哈希Table实现的,查询和删除元素十分快速,用于记录一些不能重复的数据, 例如,每次注册都可以将用户名存起来,再次注册新用户时,都可以先set查询该用户名是否存在,效率极高
 
Jedis jedis = new Jedis ( "localhost" , 6379 );
jedis . select ( 1 ); //切换仓库
System . out . println ( "获取1仓库中的所有键: " + jedis . keys ( "*" ));
//list集合
System . out . println ( "获取list集合中的参数:" + jedis . lrange ( "student" , 0 , - 1 ));;
System . out . println ( "获取指定key的个数:" + jedis . llen ( "student" ));
//System.out.println("将数据插入到list头部中: " + jedis.lpush("student","s2","s3"));
// System.out.println("将数据插入到list尾部: " +jedis.rpush("student","s4","s5"));
// System.out.println("将list1的尾元素放入list2的头部:" + jedis.rpoplpush("student", "student"));
//System.out.println("删除指定key值: " + jedis.del("studnet"));
System . out . println ( "返回该键的所属类型: " + jedis . type ( "clas" ));
 
//set集合
System . out . println ( "切换仓库: " + jedis . select ( 2 ));
Set < String > keys = jedis . keys ( "*" );
System . out . println ( "查询出该仓库所有的键:" + keys );
for ( String string : keys ) {
//得出它们所属的类型
System . out . println ( string + "的所属类型: " + jedis . type ( string ));
}
 

分布式

分布式(distributed), 是当业务量、数据量增加时,可以通过任意增加减少服务器数量来解决问题。
集群时代 
至少部署两台Redis服务器构成一个小的集群,主要有2个目的:
高可用性:在主机挂掉后,自动故障转移,使前端服务对用户无影响。 
读写分离:将主机读压力分流到从机上。 
可在客户端组件上实现负载均衡,根据不同服务器的运行情况,分担不同比例的读请求压力。
 
 
Redis有哪些数据结构?
字符串String、字典Hash、列表List、集合Set、有序集合SortedSet。
如果你是Redis中高级用户,还需要加上下面几种数据结构HyperLogLog、Geo、Pub/Sub。
如果你说还玩过Redis Module,像BloomFilter,RedisSearch,Redis-ML,面试官得眼睛就开始发亮了。
使用过Redis分布式锁么,它是什么回事?
先拿setnx来争抢锁,抢到之后,再用expire给锁加一个过期时间防止锁忘记了释放。
这时候对方会告诉你说你回答得不错,然后接着问如果在setnx之后执行expire之前进程意外crash或者要重启维护了,那会怎么样?
这时候你要给予惊讶的反馈:唉,是喔,这个锁就永远得不到释放了。紧接着你需要抓一抓自己得脑袋,故作思考片刻,好像接下来的结果是你主动思考出来的,然后回答:我记得set指令有非常复杂的参数,这个应该是可以同时把setnx和expire合成一条指令来用的!对方这时会显露笑容,心里开始默念:摁,这小子还不错。
假如Redis里面有1亿个key,其中有10w个key是以某个固定的已知的前缀开头的,如果将它们全部找出来?
使用keys指令可以扫出指定模式的key列表。
对方接着追问:如果这个redis正在给线上的业务提供服务,那使用keys指令会有什么问题?
这个时候你要回答redis关键的一个特性:redis的单线程的。keys指令会导致线程阻塞一段时间,线上服务会停顿,直到指令执行完毕,服务才能恢复。这个时候可以使用scan指令,scan指令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复概率,在客户端做一次去重就可以了,但是整体所花费的时间会比直接用keys指令长。
使用过Redis做异步队列么,你是怎么用的?
一般使用list结构作为队列,rpush生产消息,lpop消费消息。当lpop没有消息的时候,要适当sleep一会再重试。
如果对方追问可不可以不用sleep呢?list还有个指令叫blpop,在没有消息的时候,它会阻塞住直到消息到来。
如果对方追问能不能生产一次消费多次呢?使用pub/sub主题订阅者模式,可以实现1:N的消息队列。
如果对方追问pub/sub有什么缺点?在消费者下线的情况下,生产的消息会丢失,得使用专业的消息队列如rabbitmq等。
如果对方追问redis如何实现延时队列?我估计现在你很想把面试官一棒打死如果你手上有一根棒球棍的话,怎么问的这么详细。但是你很克制,然后神态自若的回答道:使用sortedset,拿时间戳作为score,消息内容作为key调用zadd来生产消息,消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理。
到这里,面试官暗地里已经对你竖起了大拇指。但是他不知道的是此刻你却竖起了中指,在椅子背后。
如果有大量的key需要设置同一时间过期,一般需要注意什么?
如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。一般需要在时间上加一个随机值,使得过期时间分散一些。
Redis如何做持久化的?
bgsave做镜像全量持久化,aof做增量持久化。因为bgsave会耗费较长时间,不够实时,在停机的时候会导致大量丢失数据,所以需要aof来配合使用。在redis实例重启时,会使用bgsave持久化文件重新构建内存,再使用aof重放近期的操作指令来实现完整恢复重启之前的状态。
对方追问那如果突然机器掉电会怎样?取决于aof日志sync属性的配置,如果不要求性能,在每条写指令时都sync一下磁盘,就不会丢失数据。但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s的数据。
对方追问bgsave的原理是什么?你给出两个词汇就可以了,fork和cow。fork是指redis通过创建子进程来进行bgsave操作,cow指的是copy on write,子进程创建后,父子进程共享数据段,父进程继续提供读写服务,写脏的页面数据会逐渐和子进程分离开来。
Pipeline有什么好处,为什么要用pipeline?
可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性。使用redis-benchmark进行压测的时候可以发现影响redis的QPS峰值的一个重要因素是pipeline批次指令的数目。
Redis的同步机制了解么?
Redis可以使用主从同步,从从同步。第一次同步时,主节点做一次bgsave,并同时将后续修改操作记录到内存buffer,待完成后将rdb文件全量同步到复制节点,复制节点接受完成后将rdb镜像加载到内存。加载完成后,再通知主节点将期间修改的操作记录同步到复制节点进行重放就完成了同步过程。
是否使用过Redis集群,集群的原理是什么?
Redis Sentinal着眼于高可用,在master宕机时会自动将slave提升为master,继续提供服务。
Redis Cluster着眼于扩展性,在单个redis内存不足时,使用Cluster进行分片存储。
1.Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。
2.Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。
3.Redis支持数据的备份,即master-slave模式的数据备份。
4.Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。
我个人认为最本质的不同是Redis在很多方面具备数据库的特征,或者说就是一个数据库系统,而Memcached只是简单的K/V缓存
总结三:
redis和memecache的不同在于:
1、存储方式:
memecache 把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小
redis有部份存在硬盘上,这样能保证数据的持久性。
2、数据支持类型:
redis在数据支持上要比memecache多的多。
3、使用底层模型不同:
新版本的redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4、运行环境不同:
redis目前官方只支持LINUX 上去行,从而省去了对于其它系统的支持,这样的话可以更好的把精力用于本系统 环境上的优化,虽然后来微软有一个小组为其写了补丁。但是没有放到主干上
memcache只能当做缓存,cache
redis的内容是可以落地的,就是说跟mongodb有些类似,然后redis也可以作为缓存,并且可以设置master-slave
 
 
 
 
 
 
 MongoDB和Redis都是NoSQL,采用结构型数据存储。二者在使用场景中,存在一定的区别,这也主要由于二者在内存映射的处理过程,持久化的处理方法不同。
 
 MongoDB建议集群部署,更多的考虑到集群方案,Redis更偏重于进程顺序写入,虽然支持集群,也仅限于主-从模式。
 
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值