0.1 新单词

expire 美 /ɪk'spaɪɚ/ 到期

range 美 /rendʒ/ 范围

idle美 /'aɪdl/ 闲置的

0.2 面试题:mysql和redis和memcached区别?

 mysqlredismemcached
类型 关系型 非关系型 非关系型
存储位置 磁盘 磁盘和内存 内存
存储过期 不支持 支持 支持
读写性能 非常高 非常高
存储结构 表来存储 支持list/set/string/zset/hash数据结构 普通键值对key-value

redis和memcached的系统点和不同点?

相同点:都是key-value Nosql,数据存储在内存中,读写效率高,都支持存储过期(存储过期:一个数据存储是为他设置过期时间,时间一到数据就没有. 道具,会员,优惠券,订单,红包等)

不同点: 1) redis支持持久化 2) redis支持存储类型更多

0.3 Redis的使用场景(面试题)

1.做缓存(重点)

2.统计数量(利用自增的特性),比如:微博评论转发,注册人数,浏览人数

3.实时攻防系统(利用自增的特性)

4.有效期应用(利用可以设置过期时间),比如:红包,优惠券,会员时间

5.自动去重(利用可以用set数据结构去重)

6.实现队列(quene FIFO) (利用redis支持list数据结构)

7.支持订阅发布

0.4 谈谈你对redis的理解,在项目中做了什么?

redis是非关系型数据库,它的数据一般是存放在内存当中,如果设置了持久化,可以存放在磁盘当中。

它的持久化方案有两种,RDB,这个是默认的,它是周期性的去备份数据库的数据,周期的时间的可以去设置,在redis.windows.conf配置文件当中,去设置save 操作多少次 在多少时间内,只要达到这个标准,RDB持久化方案就会去备份数据,还有一种是AOF,它是需要手动开启的,开启是在一个redis.windows.conf文件里面去设置一个appendonly,把false改成true就可以开启AOF持久化方案,AOF持久化方案,保存的是操作数据的日志。

redis支持多种数据结构,有String、list、set、zset、hash

redis支持很多应用场景,因为存储在内存,访问速度快,还可以设置过期时间,可以用来做缓存。因为它+1,-1操作方便,可以用来统计数量,比如:记录点赞数、排行统计、浏览量统计。因为它可以设置过期时间,可以把它用在和有效期相关的场景,比如:红包、优惠券、秒杀。因为redis可以用lpush、rpush,可以用list数据结构来实现队列。利用set数据结构可以去重的特点,可以用redis存放具有唯一性的数据,比如:存放某一博客的唯一ip地址信息。

redis内存达到极限的时候,会执行淘汰策略。redis的淘汰策略有:volatile-lru,在设置了过期时间的数据中,淘汰最近最少使用的数据。volatile-ttl,在设置了过期时间的数据中,淘汰最快过期的数据。volatile-radom,在设置了过期时间的数据中,随机淘汰数据。allkeys-lru,在所有数据中,淘汰最近最少使用的数据。allkeys-radom,在所有数据中随机淘汰。no-envication,这个是不淘汰的策略。

1.NoSQL

1.1 概念

SQL:它是关系型数据库的里面标准的查询语言

NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,它泛指非关系型的数据库,为了解决关系型数据的一些不足,处理超大规模和高并发的数据

1.2 NoSQL分类

redis和memcached是key-value的Nosql,主要用来做缓存的

1.3 Redis是什么

(1)Redis 是一个高性能的开源的、C语言写的Nosql(非关系型数据库),数据保存在内存或者磁盘中。

(2)Redis 是以key-value形式存储,和传统的关系型数据库不一样。不一定遵循传统数据库的一些基本要求,比如说,不遵循sql标准,事务,表结构等等,redis严格上不是一种数据库,应该是一种数据结构化存储方法的集合。--数组,list,set,map.....

1.3.1 Redis小结:

1.Redis:开源,高性能NoSQL数据库,数据可以存储在内存或者磁盘上

2.Redis主要key-value结构形式存储,Redis底层支持各种类型的数据存储结构,包括:list,set,map,string等

1.4 Redis的特点(优势):总7点,主要有4点

1.数据保存在内存,存取速度快,并发能力强

2.它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、 zset(sorted set --有序集合)和hash(哈希类型)。

5.Redis支持集群(主从同步)。数据可以主服务器向任意数量从的从服务器上同步,从服务器可以是关联其他从服务器的主服务器。

6.支持持久化,可以将数据保存在硬盘的文件中

注:以后用Redis主要是用来做缓存

1.5 Mysql、Memcached和Redis的比较(面试题 )

 mysqlredismemcached
类型 关系型 非关系型 非关系型
存储位置 磁盘 磁盘和内存 内存
存储过期 不支持 支持 支持
读写性能 非常高 非常高

Redis比Memcached的支持的数据存储类型更多

1.6 Redis的使用场景(面试题)

1.做缓存(重点)

2.计算器应用(利用自增的特性),比如:微博评论转发,注册人数,浏览人数

3.实时攻防系统(利用自增的特性)

4.有效期应用(利用可以设置过期时间),比如:红包,优惠券,会员时间

5.自动去重(利用可以用set数据结构去重)

6.实现队列(quene FIFO) (利用redis支持list数据结构)

7.支持订阅发布

2. Redis的使用

2.1 下载安装

2.1.1 Windows

下载Redis服务,Redis客户端

https://github.com/microsoftarchive/redis/releases

2.1.2 Linux下的安装和使用(略)

2.2 Redis使用

2.2.1 对value为string类型的常用操作

set key value //将字符串值value关联到key

get key //返回key关联的字符串值

mset key1 value1 key2 value2 //同时设置一个或多个 key-value 对

mget key1 key2 //返回所有(一个或多个)给定 key 的值

incr key //将 key 中储存的数字值增1(key不存在,则初始化为0,再加1)

decr key //将 key 中储存的数字值减1(key不存在,则初始化为0,再减1)

incrBy key //自增多少

decrBy key //自减多少

2.2.2 对key的常用操作

keys * //获取所有key列表

del key //删除key

expire key xx //设置key的过期时间(xx秒后过期)

ttl key //查看key的过期时间

flushall //清空整个redis服务器数据,所有的数据库全部清空

flushdb //清除当前库,redis中默认有16个数据库,名称分别为0,1,2,.....,15

select 库名 //选择数据库,比如:select 1:选择1数据库,默认是0数据库

2.2.3 对list集合的常用操作

list集合可以看成是一个左右排列的队列(列表)

lpush key value //将一个或多个值 value 插入到列表 key 的表头(最左边)

rpush key value //将一个或多个值 value 插入到列表 key 的表尾(最右边)

lpop key //移除并返回列表 key 的头(最左边)元素。

rpop key //移除并返回列表 key 的尾(最右边)元素。

lrange key start stop //返回列表 key 中指定区间内的元素,查询所有的stop为-1即可

lrem key count value //根据count值移除列表key中与参数 value 相等的元素count > 0 : 从表头开始向表尾搜索,移除与 value 相等的元素,数量为 count 。count < 0 : 从表尾开始向表头搜索,移除与 value 相等的元素,数量为 count 的绝对值。count = 0 : 移除表中所有与 value 相等的值。

lindex key index //返回列表 key 中,下标为 index 的元素

ltrim key start stop //对一个列表进行修剪,如ltrim w 0 1,即:把w集合中的0和1索引保留下来,其他删掉

注:

存放都是字符串,由redis组织成各种数据结构

rdis怎么实现栈(FILO)和队列(FIFO)???

list控制同一边进,同一边出就是栈

list控制一边进,另一边出就是队列.

2.2.4 对set集合的常用操作

set集合是一个无序的不含重复值的队列

sadd key member //将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略

srem key member //移除集合 key 中的一个或多个 member 元素,不存在的 member 元素会被忽略

smembers key //返回集合 key 中的所有成员。

2.2.5 对hash类型的常用操作

hash类型类似于php的数组

hset key name value //添加一个name=>value键值对到key这个hash类型,如:hset map age 18

hget key name //获取hash类型的name键对应的值,如:hget map age

hmset key name1 key1 name2 key2 //批量添加name=>value键值对到key这个hash类型,如:hmset map age 28 sex man

hmget key name1 name2 //批量获取hash类型的键对应的值,如:hmget map age sex

hkeys //返回哈希表 key 中的所有键

hvals //返回哈希表 key 中的所有值

hgetall key //返回哈希表 key 中,所有的键和值

我们将user:1(name:zhangsan,age:18,sex:nv)的信息保存在hash表.

2.2.6 事务(了解)

multi //标记一个事务块的开始。

exec //执行所有事务块内的命令。

discard //取消事务,放弃执行事务块内的所有命令。

注:Redis的事务在执行exec指令时,才批量执行操作,没有回滚操作

2.2.6 订阅/发布(了解)

subscribe channel [channel ...] //订阅给定的一个或多个频道的信息。如:subscribe CCTV1

publish channel message //将信息 message 发布到指定的频道 channel 。如:publish CCTV1 “This is my”

2.2.7 设置密码(了解)

1.通过命令动态调整密码

config set 命令可以动态地调整 Redis 服务器的配置而无须重启,重启后失效

config set requirepass 123456 //将密码设置为123456

config set requirepass "" //清除密码

auth 123456 //输入密码进行认证

2.通过配置文件设置密码

在配置文件redis.widows.conf中增加一行代码

requirepass 123456

3.java代码操作Redis

3.1 jedis简单操作

    //字符串基本操作
   @Test
   public void testRedis() throws Exception{
       Jedis jedis = new Jedis("127.0.0.1",6379,1000);
       jedis.auth("123");
       jedis.set("name", "张三");
       System.out.println(jedis.get("name"));
       jedis.close();
  }

3.2 连接池的配置

使用连接池的好处:可以设置最大连接数,不用频繁的操作数据库

使用连接池简单访问Redis的流程:

1.创建连接池配置对象

2.配置

忙时:最大连接数

闲时,最大连接数

最大等待时间

获取连接时检查配置

3.通过连接池配置对象,创建连接池

4.通过连接池后去连接

5.执行操作

6.关闭连接、摧毁连接池

    //连接池操作
   @Test
   public void testPool01() throws Exception{
       //创建连接池的配置对象
       JedisPoolConfig config = new JedisPoolConfig();
       config.setMaxIdle(2);//设置最大连接数
       config.setMaxTotal(10);//设置最大总的连接池
       config.setMaxWaitMillis(1000);//最大的等待时间 超时的作用

       //创建连接池对象
       JedisPool pool = new JedisPool(config, "127.0.0.1", 6379, 1000, "123");
       //得到jedis对象,就可以操作数据
       Jedis jedis = pool.getResource();
       System.out.println("==============String操作===============");
       //增加
       jedis.set("name", "王先生");
       System.out.println(jedis.get("name"));
       //修改
       jedis.set("name", "李先生");
       System.out.println(jedis.get("name"));
       //删除
       jedis.del("name");
       System.out.println(jedis.get("name"));
       //查询所有的key
       System.out.println(jedis.keys("*"));
       System.out.println("==============list操作===============");
       jedis.rpush("nums","1","2","3","4","5","6","7");
       List<String> nums = jedis.lrange("nums", 0, -1);
       for (String num : nums) {
           System.out.println(num);
      }
       jedis.del("nums");
       System.out.println("==============set操作===============");
       jedis.sadd("ages","7","6","5","4","3","2","1");
       Set<String> ages = jedis.smembers("ages");
       for (String age : ages) {
           System.out.println(age);
      }
       jedis.del("ages");
       System.out.println("==============hash操作===============");
       jedis.hset("wordsHash", "第一个","a");
       System.out.println(jedis.hget("wordsHash", "第一个"));
       jedis.close();
       pool.destroy();
  }
    @Test
   public void testRedisPool02() throws Exception{
       //创建连接池的配置对象
       JedisPoolConfig config = new JedisPoolConfig();
       config.setMaxIdle(2);//设置最大连接数
       config.setMaxTotal(10);//设置最大总的连接池
       config.setMaxWaitMillis(1000);//最大的等待时间 超时的作用

       //创建连接池对象
       JedisPool pool = new JedisPool(config, "127.0.0.1", 6379, 1000, "123");
       //得到jedis对象,就可以操作数据
       Jedis jedis = pool.getResource();

       //操作之前清空当前数据库
       //数字排序
       jedis.flushDB();
       jedis.lpush("nums","1","4","6","5","8","5");
       SortingParams sortingParams = new SortingParams();
       sortingParams.desc();//降序
       List<String> nums = jedis.sort("nums", sortingParams);
       System.out.println(nums);
       jedis.close();
       pool.destroy();
  }
    //弱类型事务 -- 了解
   @Test
   public void testRedisTransaction() throws Exception{
       //创建连接池的配置对象
       JedisPoolConfig config = new JedisPoolConfig();
       config.setMaxIdle(2);//设置最大连接数
       config.setMaxTotal(10);//设置最大总的连接池
       config.setMaxWaitMillis(1000);//最大的等待时间 超时的作用

       //创建连接池对象
       JedisPool pool = new JedisPool(config, "127.0.0.1", 6379, 1000, "123");
       //得到jedis对象,就可以操作数据
       Jedis jedis = pool.getResource();

       jedis.flushDB();
       jedis.set("username","小明" );
       jedis.set("password","123" );
       Transaction transaction = jedis.multi();//开启事务
       transaction.incr("username");//自增+1
       transaction.incr("password");//自增+1
       transaction.exec();//关闭事务
       System.out.println(jedis.get("username"));
       System.out.println(jedis.get("password"));
       jedis.close();
       pool.destroy();
  }

4. 持久化的机制

Redis可以支持内存存储或者磁盘存储

如果要完成磁盘存储,必须了解一些持久化机制

Redis 提供了两种不同级别的持久化方式:RDB和AOF,可以通过修改redis.windows.conf来进行配置.

4.1 RDB模式

RDB 持久化可以在指定的时间间隔内生成数据集的时间点快照,默认开启该模式.

默认开启该配置:redis.windows.conf配置

save(sec) (key change) 在sec秒之后,如果发现有key改变次数达到配置,就会进行同步

缺点:数据它有丢失,它是有时间节点,在这个节点内突然断电,就不能同步到磁盘

4.2 AOF:追加模式

AOF 持久化记录服务器执行的所有写操作命令,并在服务器启动时,通过重新执行这些命令来还原数据集,默认关闭该模式。

默认没有开启配置,需要redis.windows.conf里面进行配置

如何开启aof模式:

appendonly yes //yes 开启,no 关闭

如果有写的命令操作,就会把数据同步到aof里面,如果断电之后,再次启动,加载该文件,执行命令,在数据写到库里面

4.3 小结

redis是怎么保存数据?

redis为了考虑效率,保存数据在内容中.并且考虑数据安全性,还做数据持久化,如果满足保存策略,就会把内存的数据保存到数据rdb文件,还来不及保存那部分数据存放到aof更新日志中。在加载时,把两个数据做一个并集。

5.淘汰策略

5.1 redis的淘汰策略

淘汰一些数据,达到redis数据都是有效的。选择合适的淘汰策略进行淘汰。

volatile-lru(设置了过期时间中的数据,最近最少使用的被淘汰):从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

volatile-ttl(设置了过期时间中的数据,过期时间最近的被淘汰):从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

volatile-random(设置了过期时间中的数据,随机淘汰):从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

allkeys-lru(全部数据中,最近最少使用被淘汰):从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

allkeys-random(全部数据中,随机淘汰):从数据集(server.db[i].dict)中任意选择数据淘汰

no-enviction(不淘汰):禁止驱逐数据(不淘汰:一般都是热点数据,永不淘汰)

redis 确定驱逐某个键值对后,会删除这个数据,并将这个数据变更消息发布到本地(AOF 持久化)和从机(主从连接)。

 

1.redis-cluster:redis集群

0.1 新单词

Sentinel 美 /'sɛntɪnl/ 哨兵

cluster美 /'klʌstɚ/ 集群

0.3 集群和分布式的区别?

相同点:都可以解决高并发,都需要多台服务器

不同点:

集群是指:多个服务器实现相同的业务功能。

分布式是指:多个服务器去拆分同一个业务功能。

0.4 使用集群的好处?

1.解决单点故障问题 2.处理高并发 3.处理大量数据(解决存储问题)

0.4 使用分布式的好处?

1.方便维护 2.解决高并发,单点故障问题 3.便于扩容

0.5 什么是主从复制、读写分离、主从同步?

主从复制(主备切换)是指:主服务器宕机了,从服务器顶上。

读写分离是指:主服务器专门用来写操作,从服务器专门用来读操作。

主从同步是指:主服务器把读来的数据同步到从服务器。

主从复制的缺点:容错困难,不支持自动恢复

0.6 什么是哨兵模式?

哨兵模式是指:每个哨兵进程去ping主服务器,如果在设置的时间内没有响应,那么就标记为主观下线,如果达到设定的个数的哨兵进程都标记了主服务器为主观下线,那么就把主服务器标记为客观下线。

优缺点:解决了主从复制的容错问题,也支持自动恢复功能。缺点:不方便扩容。

0.7 什么是redis-Cluster模式?

容错机制:选举过程是集群中所有master参与,如果半数以上master节点与故障节点通信超过(cluster-node-timeout),认为该节点故障,自动触发故障转移操作. 故障节点对应的从节点自动升级为主节点

优缺点:解决了哨兵模式的

0.8 怎么实现redis-Cluster模式?

1.准备6个redis服务器(79行改端口,707行改) 707 721 581 yes 715->更改号

1.redis集群

1.1 集群概念

集群就是 很多服务器组成的一个网络。指的是将多台服务器集中在一起,实现同一业务。

1.1.2 分布式

分布式是指将不同的业务分布在不同的地方. web应用和数据库服务分开.

1.2 集群优化

1)两大关键特性

集群提供了以下两个关键特性:

1、可扩展性:(简单来说就是随时可以增加新的服务器)

集群的性能不限于单一的服务实体,新的服务实体可以动态地加入到集群,从而增强集群的性能。动态添加服务器

2、高可用性:(简单来说就是主服务器挂了,集群要有能力找可以正常使用额服务器继续提供服务器)

集群通过服务实体冗余使客户端免于轻易遇到out of service的警告。在集群中,同样的服务可以由多个服务实体提供。如果一个服务实体失败了,另一个服务实体会接管失败的服务实体。集群提供的从一个出错的服务实体恢复到另一个服务实体的功能增强了应用的可用性

2)两大能力

为了具有可扩展性和高可用性特点,集群的必须具备以下两大能力:

1、负载均衡--负载均衡能把任务比较均衡地分布到集群环境下的计算和网络资源。

2、错误恢复--由于某种原因,执行某个任务的资源出现故障,另一服务实体中执行同一任务的资源接着完成任务。这种由于一个实体中的资源不能工作,另一个实体中的资源透明的继续完成任务的过程叫错误恢复。

 

负载均衡和错误恢复都要求各服务实体中有执行同一任务的资源存在,而且对于同一任务的各个资源来说,执行任务所需的信息视图(信息上下文)必须是一样的

1.3 分布式和集群相同点和不同点?(面试题)

相同点:

都是可以处理高并发,而且都需要多台服务器协同.一般在一个系统中同时存在分布式和集群.

不同点:

分布式:不同服务处理不同的业务,集群:不同服务处理同一个业务

1.4 Redis集群方案选择

1.4.1 为什么redis要做集群

1) 防止单点故障

2) 处理高并发-太多请求一台服务器搞不定

3) 处理大量数据-太多内存数据一台服务器搞不定

1.4.2 方案1 主从模式

主从复制的优缺点:

优点:处理高并发,支持主从同步,主机会自动将数据同步到从机,可以进行读写分离

缺点:主机或者从机宕机会有部分数据丢失

1.4.3 方案2 哨兵模式

1.监控主服务器和从服务器是否正常运行。

2.主服务器出现故障时自动将从服务器转换为主服务器。

哨兵模式的优缺点:

优点:

哨兵模式是基于主从模式的,所有主从的优点,哨兵模式都具有。

主从可以自动切换,系统更健壮,可用性更高。

缺点:

Redis较难支持在线扩容,在集群容量达到上限时在线扩容会变得很复杂

1.4.4 方案3 Redis-Cluster集群(采纳)

Redis-Cluster采用无中心结构

特点:

1.所有的redis节点彼此互联(PING-PONG机制)

2.节点的fail是通过集群中超过半数的节点检测失效时才生效。

3.客户端与redis节点直连,不需要中间代理层.客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可。

4.在redis的每一个节点上,都有两个东西,一个是插槽(slot),它的的取值范围是:0-16383。还有一个就是cluster,可以理解为是一个集群管理的插件。

总结(简单来说):

1.redis-cluster可以理解为哨兵模式的升级版本,通过槽的概念解决数据分布式存储

2.也有主从结构,解决一个槽挂了,从填充上去决绝单点故障

1.5 redis集群实现流程

1 .准备6个redis服务器 (以分别命名为 6379-6384例)(3主3从)

(2) 修改配置

port 6379

cluster-enabled yes

cluster-config-file nodes-6379.conf

cluster-node-timeout 15000

appendonly yes

(3) 每个redis服务 写一个startup.bat启动文件

如:6379的文件内容(6380的文件把6379改为6380)

title redis-6379
redis-server.exe redis.windows.conf

(4)安装ruby环境

傻瓜式安装:rubyinstaller-2.6.3-1-x64.exe

(5)安装Redis的Ruby驱动

a)解压 :rubygems-3.0.6

b)到Ruby文件目录,cmd后, 然后命令行执行:ruby setup.rb

(6)通过驱动安装的redis(需要联网)

a)进入6379的目录

b)cmd中,执行gem install redis命令

(7) 创建集群

a)启动 6379-6384服务

b)拷贝redis-trib.rb文件到6379的文件目录

c)cmd下,执行命令:redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384

d)执行命令后,询问的时候,需要输入:yes

1.6 集群环境搭建测试

    Set<HostAndPort> nodes = new HashSet();
       nodes.add(new HostAndPort("127.0.0.1", 6379));
       nodes.add(new HostAndPort("127.0.0.1", 6380));
       nodes.add(new HostAndPort("127.0.0.1", 6381));
       nodes.add(new HostAndPort("127.0.0.1", 6382));
       nodes.add(new HostAndPort("127.0.0.1", 6383));
       nodes.add(new HostAndPort("127.0.0.1", 6384));
       JedisCluster cluster = new JedisCluster(nodes);

1.7 面试题

1)简单说一下你对分布式理解?

分布式是指将不同的业务分布在不同的地方. web应用和数据库服务分开

2)简单说一下你对集群理解?

集群就是 很多服务器组成的一个网络。指的是将多台服务器集中在一起,实现同一业务

3)说一下分布式和集群联系和区别

相同点:

都是处理高并发,而且都需要多台服务器协同.一般在一个系统中同时存在分布式和集群.

不同点:

分布式:不同服务处理不同的业务,集群:不同服务处理同一个业务

4)redis集群方式有哪些?

5)简单说一下redis-cluster里面槽?

槽是存放数据,存放是要通过key计算槽位,选择对应的服务器来存储,获取也是同样的算法.

默认16384个槽位要均匀分布到主节点上面

为了槽里面数据安全要对主节点进行1-N从节点备份

6)简单说一下redis-cluster里面选举投票机制

所有主节点都参与投票,默认半数以上挂点,启动容错机制,提升从节点为主节点.

7)怎么通过命令连接redis集群 :redis-cli -c -h -p

8)怎么通过jedis连接集群