当前位置: 首页 > news >正文

Redis极速上手开发手册【Redis全面复习】

文章目录

  • 什么是Redis
  • Redis的特点
  • Redis的应用场景
  • Redis安装部署
  • Redis基础命令
  • Redis多数据库特性
  • Redis数据类型
    • Redis数据类型之string
    • Redis数据类型之hash
    • Redis数据类型之list
    • Redis数据类型之set
    • Redis数据类型之sorted set
    • 案例:存储高一班的学员信息
  • Redis封装工具类技巧
    • 如何使用java代码操作redis
    • 单连接方式
    • 连接池方式
    • 案例:提取RedisUtils工具类
  • Redis高级特性
    • expire 生存时间
    • pipeline 管道
    • 案例:初始化10万条数据
    • info命令
    • Redis的持久化
      • Redis持久化之RDB
      • Redis持久化之AOF
    • Redis 的安全策略
      • 设置数据库密码
    • bind参数的应用
      • 命令重命名
    • 一个Redis实例最多能存放多少key?
    • Redis监控命令-monitor
  • Redis架构演进
    • 主从复制
    • Sentinel
    • 集群

什么是Redis

Redis是一种面向 “Key-Value” 数据类型的内存数据库,可以满足我们对海量数据的快速读写需求
注意:首先Redis是一种内存数据库,它的数据都是放在内存里面的,
然后Redis中存储的数据都是key-value类型的
其中redis中的key只能是字符串,value支持多种数据类型
常见的有 string、hash、list、set、sortedset 等

  1. 字符串 string
  2. 哈希 hash,类似于java中的hashmap
  3. 字符串列表 list
  4. 字符串集合 set 不重复,无序
  5. 有序集合sorted set ,不重复,有序

Redis的特点

接下来看一下Redis的一些特点
高性能:Redis读的速度是11W次/s,写的速度是8.1W次/s
原子性:保证数据的准确性
持久存储:支持两种方式的持久化,RDB和AOF,可以把内存中的数据持久化到磁盘中
支持主从:master-slave架构,可以实现负载均衡、高可用
支持集群:从3.0版本开始支持

注意:Redis是一个 单线程 的服务,作者之所以这么设计,主要是为了保证redis的快速,高效,如果涉及了多线程,就需要使用锁机制来解决并发问题,这样执行效率反而会打折扣。
注意:Redis是一个 NoSQL 数据库,NoSQL的全称是not only sql,不仅仅是SQL,泛指非关系型数据库,这种类型的数据库不支持SQL语法。

Redis的应用场景

主要应用在高并发和实时请求的场景,例如:新浪微博

hash:关注列表、粉丝列表

string:微博数,粉丝数(避免使用select count(*) from …)

Redis安装部署

首先下载redis
使用此链接下载,可以显示Redis目前所有的版本
http://download.redis.io/releases/
我们选择目前比较稳定的5.0.9版本。
将下载好的安装包上传到bigdata04机器的/data/soft目录下
1:解压

[root@bigdata04 soft]# tar -zxvf redis-5.0.9.tar.gz 

2:编译+安装

[root@bigdata04 soft]# cd redis-5.0.9
[root@bigdata04 redis-5.0.9]# make
[root@bigdata04 redis-5.0.9]# make install

只要不报错就说明编译安装成功。
注意:由于redis需要依赖于C语言环境,如果你安装的centos镜像是精简版,会缺失c语言的依赖,所以需要安装C语言环境才可以编译成功。
我们在这使用的centos镜像是完整版,里面是包含C语言环境的

3:修改redis.conf配置文件

[root@bigdata04 redis-5.0.9]# vi redis.conf
daemonize yes
logfile /data/soft/redis-5.0.9/log
bind 127.0.0.1 192.168.182.103
  • daemonize参数的值默认是no,表示在前台启动Redis,但是Redis是一个数据库,我们希望把它放到后台运行,所以将参数的值改为yes
  • logfile 参数的值默认为空,表示redis会将日志输出到/dev/null里面,也就是不保存了,建议在这设置一个日志路径记录redis的日志,便于后期排查问题。
  • bind 参数可以绑定指定ip,这样就可以通过这里指定的ip来访问redis服务了,可以在后面指定当前机器的本地回环地址(127.0.0.1)和内网地址(192.168.182.103),指定本地回环地址是为了能够在本机自己连自己比较方便。指定内网地址是为了能够让公司局域网内的其它服务器也能连到这个redis。 如果你这台机器有外网地址的话不建议在这配置,因为使用外网地址的话就不安全了,容易受到网络攻击。

4:启动redis

[root@bigdata04 redis-5.0.9]# redis-server redis.conf 

5:验证
注意:redis不是java程序,所以使用jps命令查不到,需要使用ps命令查看redis的进程

[root@bigdata04 redis-5.0.9]# ps -ef|grep redis
root 5828 1 0 16:12 ? 00:00:00 redis-server 127.0.0.1:6379

6:连接redis数据库

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379>

注意:使用redis-cli默认可以连接本地的redis
其实redis-cli后面省略了 -h 127.0.0.1 和 -p 6379

[root@bigdata04 redis-5.0.9]# redis-cli -h 127.0.0.1 -p 6379 

7:停止redis数据库
暴力一点的方式是使用kill命令直接杀进程
不过redis提供的有停止命令

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379> shutdown
not connected>

或者这样停止也是可以的

[root@bigdata04 redis-5.0.9]# redis-cli shutdown 

Redis基础命令

  • 获得符合规则的键:keys
    keys 后面可以指定正则表达式
127.0.0.1:6379> keys *
(empty list or set)
127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> keys *
1)"a"
127.0.0.1:6379> keys a*
1) "a"
127.0.0.1:6379> keys a+
(empty list or set)

注意:在生产环境下建议禁用keys命令,因为这个命令会查询过滤redis中的所有数据,可能会造成服务阻塞,影响redis执行效率。

如果有类似的查询需求建议使用scan。scan命令用于迭代当前数据库中的key集合。它支持增量式迭代,每次执行只会返回少量元素,所以它可以用于生产环境,而不会出现像keys 命令那样可能会阻塞服务器的问题。SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。
当SCAN命令的游标参数被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。

向redis中初始化一批数据

127.0.0.1:6379> set a1 1
OK
127.0.0.1:6379> set a2 1
OK
127.0.0.1:6379> set a3 1
OK
127.0.0.1:6379> set a4 1
OK
127.0.0.1:6379> set a5 1
OK
127.0.0.1:6379> set a6 1
OK
127.0.0.1:6379> set a7 1
OK
127.0.0.1:6379> set a8 1
OK
127.0.0.1:6379> set a9 1
OK
127.0.0.1:6379> set a10 1
OK

使用scan迭代数据,后面游标参数指定为0,表示从头开始迭代key

127.0.0.1:6379> scan 0
1) "3"
2) 1) "a9"
2) "a3"
3) "a1"
4) "a10"
5) "a8"
6) "a5"
7) "a4"
8) "a"
9) "a7"
10) "a6"

SCAN 命令的返回值是一个包含两个元素的数组,
第一个元素是用于进行下一次迭代的新游标,而第二个元素则是一个数组, 这个数组中包含了所有被迭代出来的元素。
默认情况下scan返回10条数据
所以这样执行效果也是一样的

注意,游标的值并不等于返回的数据量。

  • 判断键是否存在:exists
127.0.0.1:6379> exists a
(integer) 1
127.0.0.1:6379> exists b
(integer) 0
  • 删除键:del
127.0.0.1:6379> del a
(integer) 1
  • 获得键值的类型:type

返回值可能是这五种类型(string,hash,list,set,zset)

127.0.0.1:6379> set a 1
OK
127.0.0.1:6379> type a
string

这个命令可以帮我们快速识别某一个key中存储的数据是什么类型的,因为针对存储了不同类型值的
key,操作的命令是不一样的。

  • 帮助命令:help

  • 退出客户端:quit/exit

ctrl+c 也可以退出redis-cli客户端

Redis多数据库特性

Redis默认支持 16 个数据库,通过 databases 参数控制的
这个参数在redis.conf配置文件中

[root@bigdata04 redis-5.0.9]# cat redis.conf | grep databases
# Set the number of databases. The default database is DB 0, you can select
# dbid is a number between 0 and 'databases'-1
databases 16
# Compress string objects using LZF when dump .rdb databases?

每个数据库对外都是以一个从0开始的递增数字命名,不支持自定义
Redis默认选择的是0号数据库,可以通过 select 命令切换

127.0.0.1:6379> select 0
OK
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 2
OK
127.0.0.1:6379[2]> select 15
OK
127.0.0.1:6379[15]> select 16
(error) ERR DB index is out of range

一般在工作中会使用2~3个数据库,可以根据业务类型来分库,不同业务的数据存到不同的库里面。
还有一种用法是,一个库作为测试库,一个库作为正式库。
如果没有特殊需求,一般使用0号数据库就可以了,这个库使用起来比较方便,默认就是0号库,不需要使用select切换。具体在工作中怎么用都行,只要理解它的特性就可以了。

但是有一点需要注意:多个数据库之间并不是完全隔离的,如果使用flushall命令,则会清空redis中所有数据库内的数据。

并且我们在redis中使用多个库,并不能提高redis的存储能力,因为默认这16个库共用redis的内存存储空间,如果想要提高redis的存储能力,需要给我们的服务器增加内存才可以

127.0.0.1:6379[15]> set x 1
OK
127.0.0.1:6379[15]> flushall
OK
127.0.0.1:6379[15]> keys *
(empty list or set)
127.0.0.1:6379[15]> select 0
OK
127.0.0.1:6379> keys *
(empty list or 

如果只想清空当前数据库中的数据,可以使用 flushdb

127.0.0.1:6379> select 15
OK
127.0.0.1:6379[15]> set a 1
OK
127.0.0.1:6379[15]> keys *
1) "a"
127.0.0.1:6379[15]> flushdb
OK

Redis数据类型

Redis数据类型之string

字符串类型是redis中最基本的数据类型,它能存储任何形式的内容,包含二进制数据,甚至是一张图片一个字符串类型的值存储的最大容量是1GB,一般情况下我们存储的单条数据肯定是达不到的这个限值的,所以大家不用担心string类型比较适合存储类型单一的数据。

针对string类型主要有下面这些常见命令

image.png

  • 添加数据 set

  • 查询数据 get

  • 一次添加多条数据

127.0.0.1:6379> mset str1 a1 str2 a2

一次查询多条数据

127.0.0.1:6379> mget str1 str2
1) "a1"
2) "a2"
  • 递增指定数值(整数类型)
127.0.0.1:6379> incrby num 2
(integer) 3
127.0.0.1:6379> get num
"3"
127.0.0.1:6379> incrby num 2.1
(error) ERR value is not an integer or out of range[注意:增量数值只支持integer
  • 递减指定数值(整数类型)

  • 获取指定key的value长度

127.0.0.1:6379> get str
"a"
127.0.0.1:6379> strlen str
(integer) 1

Redis数据类型之hash

hash类型的值存储了字段和字段值的映射,字段和字段值只能是字符串,不支持其他数据类型。
hash类型的值至多存储 2的32次方-1 个字段,一般情况下我们也达不到这个极限。
hash类型比较适合存储对象,因为对象里面是有一些属性和值的,我们就可以把这些属性和值存储到这个hash类型里面

针对hash类型主要有下面这些常见命令:

image.png

  • 添加数据 hget
127.0.0.1:6379> hset user:1 name zs
(integer) 1
  • 查询数据 hget
127.0.0.1:6379> hget user:1 name
"zs"
  • 向一个hash中同时添加多个k-v hmset
127.0.0.1:6379> hmset user:2 name lisi age 18
OK
  • 查询一个hash数据中多个k的值 hmget
127.0.0.1:6379> hmget user:2 name age
1) "lisi"
2) "18"
  • 查询一个hash数据中的所有k-v hgetall
127.0.0.1:6379> hgetall user:2
1) "name"
2) "lisi"
3) "age"
4) "18"
  • 判断一个hash数据中是否存在指定k hexists
127.0.0.1:6379> hexists user:2 name
(integer) 1
127.0.0.1:6379> hexists user:2 city
(integer) 0

Redis数据类型之list

list是一个有序的字符串列表,列表内部是使用双向链表(linked list)实现的。
list列表类型的值最多可以存储 2的32次方-1 个元素,一般我们也达不到这个限值。
list类型比较适合作为队列使用,使用lpush+rpop可以实现先进先出的队列

针对list类型主要有下面这些常见命令:

image.png

  • 添加元素(左侧添加) lpush
127.0.0.1:6379> lpush list1 a
(integer) 1
127.0.0.1:6379> lpush list1 b
(integer) 2
  • 取出元素(左侧取元素) lpop
127.0.0.1:6379> lpop list1
"b"
127.0.0.1:6379> lpop list1
"a"
127.0.0.1:6379> lpop list1
(nil)
  • 添加元素(右侧添加) rpush
127.0.0.1:6379> rpush list2 x
(integer) 1
127.0.0.1:6379> rpush list2 y
(integer) 2
  • 取出元素(右侧取元素) rpop
127.0.0.1:6379> rpop list2
"y"
127.0.0.1:6379> rpop list2
"x"
  • 列表长度 llen
127.0.0.1:6379> lpush list3 a b c d
(integer) 4
127.0.0.1:6379> llen list3
(integer) 4
  • 获取列表中的元素 lrange
127.0.0.1:6379> lrange list3 0 -1
1) "d"
2) "c"
3) "b"
4) "a"
  • 查询指定角标元素 lindex
127.0.0.1:6379> lindex list3 1
"c"
  • 修改指定角标元素 lset
127.0.0.1:6379> lset list3 1 m
OK
127.0.0.1:6379> lrange list3 0 -1
1) "d"
2) "m"
3) "b"
4) "a"

Redis数据类型之set

set是一个集合
set集合中的元素都是不重复的,无序的
set集合类型的值最多可以存储 2的32次方-1个 元素
set集合比较适合用在去重的场景下,因为它里面的元素是都不重复的
针对set类型主要有下面这些常见命令:

image.png

  • 向集合中添加元素 sadd
127.0.0.1:6379> sadd set1 a
(integer) 1
127.0.0.1:6379> sadd set1 b
(integer) 1
  • 获取集合中所有元素 smembers
127.0.0.1:6379> smembers set1
1) "b"
2) "a"

Redis数据类型之sorted set

有序集合,在集合类型的基础上为集合中的每个元素都关联了一个分数,根据分数进行排序,这样就实现了有序。
sorted set比较适合用在获取TopN的场景,因为它里面的数据是有序的
针对sorted set类型主要有下面这些常见命令:

image.png

  • 向集合中添加元素 zadd
127.0.0.1:6379> zadd zset1 5 a
(integer) 1
127.0.0.1:6379> zadd zset1 3 b
(integer) 1
127.0.0.1:6379> zadd zset1 4 c
(integer) 1
  • 查询集合中指定元素的分值 zscore
127.0.0.1:6379> zscore zset1 a
"5"
  • 根据角标获取集合中的元素(按照正序) zrange
127.0.0.1:6379> zrange zset1 0 -1
1) "b"
2) "c"
3) "a"

注意:
1:+inf(正无穷) -inf(负无穷),在给集合中的元素设置分值的时候可以使用这两个特殊数值。
2:set命令:如果key持有其它类型值,set会覆盖旧值,无视类型

案例:存储高一班的学员信息

需求:将学员的姓名、年龄、性别、住址信息保存到Redis中
分析一下:
在这里我们可以把学生认为是一个对象,学生对象具备了多个属性信息,姓名,年龄,性别,住址信息所以针对学生信息非常适合使用hash类型进行存储。
我们可以给学生生成一个编号拼接到key里面,姓名、年龄、性别、住址信息存储到hash类型的value中。

注意:这里面针对key的命名,stu是student的简写,尽量不要写太多字符,否则会额外占用内存空间的,后面的:1,表示这个学生的编号是1,后期如果我们想获取所有学员的key,就可以使用
这个规则进行过滤了。

127.0.0.1:6379> hmset stu:1 name xiaoming age 18 sex 0 address beijing
OK
127.0.0.1:6379> hgetall stu:1
1) "name"
2) "xiaoming"
3) "age"
4) "18"
5) "sex"
6) "0"
7) "address"
8) "beijing"
127.0.0.1:6379> hget user:1 age
"18"

Redis封装工具类技巧

如何使用java代码操作redis

我们需要借助于第三方jar包jedis来操作
首先在idea中创建maven项目 db_redis
在pom.xml文件中添加jedis依赖

<dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.3.0</version>
</dependency>

注意:jedis的版本号和redis的版本号不是一一对应的。

单连接方式

接下来使用单连接的方式操作redis
代码如下:

package com.imooc.redis;
import redis.clients.jedis.Jedis;
/**
* 单连接方式操作redis
*/
public class RedisSingle {
/**
* 注意:此代码能够正常执行的前提是
* 1:redis所在服务器的防火墙需要关闭
* 2:redis.conf中的bind参数需要指定192.168.182.103
* @param args
*/
public static void main(String[] args) {
//获取jedis连接Jedis jedis = new Jedis("192.168.182.103",6379);//向redis中添加数据,key=imooc,value=hello bigdata!jedis.set("jedis","hello bigdata!");//从redis中查询key=imooc的value的值String value = jedis.get("jedis");System.out.println(value);//关闭jedis连接jedis.close();}
}

代码执行效果如下:
hello bigdata!
此时到redis中确认一下:

127.0.0.1:6379> keys *
1) "jedis"
127.0.0.1:6379> get imooc
"hello bigdata!"

在这你会发现,我们前面讲的那些在redis-cli中使用的命令,和jedis中提供的函数名称是一一对应
的。切换到代码中来使用也是可以直接上手的。

连接池方式

接下来使用连接池的方式操作redis
代码如下:

package com.imooc.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 连接池的方式操作redis
*/
public class RedisPool {
public static void main(String[] args) {//创建连接池配置对象JedisPoolConfig poolConfig = new JedisPoolConfig();//连接池中最大空闲连接数poolConfig.setMaxIdle(10);//连接池中创建的最大连接数poolConfig.setMaxTotal(100);//创建连接的超时时间poolConfig.setMaxWaitMillis(2000);//表示从连接池中获取连接的时候会先测试一下连接是否可用,这样可以保证取出的连poolConfig.setTestOnBorrow(true);//获取jedis连接池JedisPool jedisPool = new JedisPool(poolConfig, "192.168.182.103", 63//从jedis连接池中取出一个连接Jedis jedis = jedisPool.getResource();String value = jedis.get("jedis");System.out.println(value);//注意:此处的close方法有两层含义//1:如果jedis是直接创建的单连接,此时表示直接关闭这个连接//2:如果jedis是从连接池中获取的连接,此时会把这个连接返回给连接池jedis.close();//关闭jedis连接池jedisPool.close();}
}

执行结果:
hello bigdata!

案例:提取RedisUtils工具类

基于redis连接池的方式提取RedisUtils工具类

package com.imooc.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* 基于redis连接池提取redis工具类
*/
public class RedisUtils {
//私有化构造函数,禁止newprivate RedisUtils(){}private static JedisPool jedisPool = null;//获取连接public static synchronized Jedis getJedis(){if(jedisPool==null){JedisPoolConfig poolConfig = new JedisPoolConfig();poolConfig.setMaxIdle(10);poolConfig.setMaxTotal(100);poolConfig.setMaxWaitMillis(2000);poolConfig.setTestOnBorrow(true);jedisPool = new JedisPool(poolConfig, "192.168.182.103", 6379);}return jedisPool.getResource();}//向连接池返回连接public static void returnResource(Jedis jedis){jedis.close();}
}

使用工具类代码

package com.imooc.redis;
import redis.clients.jedis.Jedis;public class TestRedisUtils {
public static void main(String[] args) {//获取连接Jedis jedis = RedisUtils.getJedis();String value = jedis.get("jedis");System.out.println(value);//向连接池返回连接RedisUtils.returnResource(jedis);}
}

Redis高级特性

expire 生存时间

Redis中可以使用expire命令设置一个键的生存时间,到时间后Redis会自动删除它。

它的一个典型应用场景是:手机验证码
我们平时在登录或者注册的时候,手机会接收到一个验证码,上面会提示验证码的过期时间,过了这个时间之后这个验证码就不能用了。

expire支持以下操作

image.png

  • 设置key的过期时间
127.0.0.1:6379> set abc 123
OK
127.0.0.1:6379> expire abc 200
(integer) 1
  • 获取key的剩余有效时间
127.0.0.1:6379> ttl abc
(integer) 192
  • 取消key的过期时间
127.0.0.1:6379> persist abc
(integer) 1

此时再查看这个key的剩余有效时间,返回的值是-1,-1表示这个key是一个永久存在的key

127.0.0.1:6379> ttl abc
(integer) -1
  • 还可以通过expireat指定key在指定时间点过期

总结一下:
当key永久存在的时候,执行ttl返回的是-1,
当key被设置了过期时间之后,执行ttl返回的就是这个key剩余的有效时间
当key已经被删除了,不存在的时候,执行ttl返回的是-2

pipeline 管道

针对批量操作数据或者批量初始化数据的时候使用,效率高
Redis的pipeline功能在命令行中没有实现,在Java客户端(jedis)中是可以使用的
它的原理是这样的

image.png

不使用管道的时候,我们每执行一条命令都需要和redis服务器交互一次
使用管道之后,可以实现一次提交一批命令,这一批命令只需要和redis服务器交互一次,所以就提高了性能。这个功能就类似于mysql中的batch批处理。

案例:初始化10万条数据

需求:使用普通方式一条一条添加和使用管道批量初始化进行对比分析
代码如下:

package com.imooc.redis;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline;
/**
* pipeline(管道)的使用
*/
public class PipelineOp {
public static void main(String[] args) {//1:不使用管道Jedis jedis = RedisUtils.getJedis();long start_time = System.currentTimeMillis();for(int i=0;i<100000;i++){jedis.set("a"+i,"a"+i);}long end_time = System.currentTimeMillis();System.out.println("不使用管道,耗时:"+(end_time-start_time));//2:使用管道Pipeline pipelined = jedis.pipelined();start_time = System.currentTimeMillis();for(int i=0;i<100000;i++){pipelined.set("b"+i,"b"+i);}pipelined.sync();end_time = System.currentTimeMillis();System.out.println("使用管道,耗时:"+(end_time-start_time));RedisUtils.returnResource(jedis);}
}

结果如下

不使用管道,耗时:40887
使用管道,耗时:180

在代码执行的过程中,我们可以使用info命令观察数据库中的数据条数

127.0.0.1:6379> info
# Keyspace
db0:keys=200000,expires=1,avg_ttl=389945

针对海量数据的初始化,管道可以显著提高初始化性能。

info命令

这里面参数比较多
在这我们主要关注几个重点的参数

# Redis 服务器版本
redis_version:5.0.9
# Redis服务的可执行
executable:/data/soft/redis-5.0.9/redis-server
# 启动Redis时使用的配置文件路径
config_file:/data/soft/redis-5.0.9/redis.conf
# 已连接客户端的数量
connected_clients:1
# Redis目前存储数据使用的内容
used_memory_human:15.01M
# Redis可以使用的内存总量,和服务器的内存有关
total_system_memory_human:1.78G
# db0表示0号数据库,keys:表示0号数据库的key总量,expires:表示0号数据库失效被删除的
db0:keys=200001,expires=1,avg_ttl=389945

Redis的持久化

Redis持久化简单理解就是把内存中的数据持久化到磁盘中 可以保证Reids重启之后还能恢复之前的数据

Redis支持两种持久化,可以 单独使用 或者 组合使用
RDB 和 AOF
RDB是Redis默认的持久化机制

Redis持久化之RDB

RDB持久化是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据执行快照操作并存储到硬盘上,默认存储在 dump.rdb 文件中

[root@bigdata04 redis-5.0.9]# ll
....
-rw-r--r--. 1 root root 2955661 Jan 17 12:12 dump.rdb

Redis什么时候会执行快照?

Redis执行快照的时机是由以下参数控制的,这些参数是在redis.conf文件中的

save 900 1
save 300 10
save 60 10000

save 900 1 表示900秒内至少一个key被更改则进行快照
这里面的三个时机哪个先满足都会执行快照操作。
RDB的优点:由于存储的有数据快照文件,恢复数据很方便
RDB的缺点:会丢失最后一次快照以后更改的所有数据,因为两次快照之间是由一个时间差的,这一段时间之内修改的数据可能会丢。

Redis持久化之AOF

AOF持久化是通过日志文件的方式,默认情况下没有开启,可以通过 appendonly 参数开启

[root@bigdata04 redis-5.0.9]# vi redis.conf
....
appendonly yes
....

AOF日志文件的保存位置和RDB文件相同,都是dir参数设置的,默认的文件名是 appendonly.aof
注意:dir参数的值为. 表示当前目录,也就是说我们在哪个目录下启动redis,rdb快照文件和aof
日志文件就产生在哪个目录下。
可以试验一下,换一个目录启动redis,发下redis中的数据是空的。关闭之后,重新在之前的目录启动redis,数据又回来了。
AOF方式只会记录用户的写命令,添加、修改、删除之类的命令,查询命令不会记录,因为查询命令不会影响数据的内容。
那redis什么时候会把用户的写命令同步到aof文件中呢?

# appendfsync always
appendfsync everysec
# appendfsync no

默认是每秒钟执行一次同步操作。appendfsync everysec
也可以实现每执行一次写操作就执行一次同步操作,appendfsync always,但是这样效率会有低。或者使用appendfsync no,表示不主动进行同步,由操作系统来做,30秒执行一次。
如果大家对数据的丢失确实是0容忍的话,可以使用always。
不过一般情况下,redis中存储的都是一些缓存数据,就算丢了也没关系,程序还会继续往里面写新数据,不会造成多大影响。

Redis 的安全策略

设置数据库密码

默认情况下访问redis只要网络能通就可以直接访问,这样其实是有一些不安全的,不过我们一般会限制只能在内网访问,这样其实问题也不大。
redis针对这个问题,也支持给数据库设置密码,在redis.conf中配置

[root@bigdata04 redis-5.0.9]# vi redis.conf
....
requirepass admin
....

重启redis服务

[root@bigdata04 redis-5.0.9]# redis-cli shutdown
[root@bigdata04 redis-5.0.9]# redis-server redis.conf

重新连接redis

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379> get imooc
(error) NOAUTH Authentication required.
127.0.0.1:6379> auth admin
OK
127.0.0.1:6379>get jedis

在代码层面,以后在使用的时候时候就需要使用auth方法先校验权限了。

package com.imooc.redis;
import redis.clients.jedis.Jedis;
/**
* 单连接方式操作redis
*/
public class RedisSingle {
/**
* 注意:此代码能够正常执行的前提是
* 1:redis所在服务器的防火墙需要关闭
* 2:redis.conf中的bind参数需要指定192.168.182.103
* @param args
*/
public static void main(String[] args) {//获取jedis连接Jedis jedis = new Jedis("192.168.182.103",6379);//使用密码jedis.auth("admin");//向redis中添加数据,key=imooc,value=hello bigdata!jedis.set("jedis","hello bigdata!");//从redis中查询key=imooc的value的值String value = jedis.get("jedis");System.out.println(value);//关闭jedis连接jedis.close();}
}

注意:在实际工作中一般不会设置密码,因为我们在这设置的密码是明文的,其实意义也不大,针对别有用心的人,你这样设置是没有意义的。
所以在实际工作中我们一般只需要控制好redis服务器的访问权限就可以了,redis服务器的访问权限其实就是使用bind参数来设置的。
所以再把刚才设置的密码取消掉,直接把对应的配置注释掉即可

bind参数的应用

在实际工作中,我们的服务器至少会有3个ip地址
127.0.0.1 这个是本机回环地址
192.168.182.103 这个是本机的内网地址
还有一个是外网地址
我们一般会使用bind绑定内网ip,这样其实就限制了redis服务器的访问范围,不会暴露在外网,只需要运维同学做好网络的访问限制就可以了,此时我们就可以认为redis是安全的了

命令重命名

前面讲过一个命令是 flushall ,这个命令是很危险的,它可以把redis中的所有数据全部清空
所以在实际工作中一般需要将这个命令给禁用掉,防止误操作。
在redis.conf配置文件中进行设置

[root@bigdata04 redis-5.0.9]# vi redis.conf
....
rename-command flushall ""
....

这样修改之后,就把flushall命令给禁用掉了
重启redis服务

[root@bigdata04 redis-5.0.9]# redis-cli shutdown
[root@bigdata04 redis-5.0.9]# redis-server redis.conf

重新连接redis

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379> flushall
(error) ERR unknown command `flushall`, with args beginning with:
127.0.0.1:6379>

此时会提示未知命令。

一个Redis实例最多能存放多少key?

一个Redis实例最多能存放多少key?
有没有限制?
Redis本身是不会限制存储多少key的,但是Redis是基于内存的,它的存储极限是系统中的可用内存值,如果内存存满了,那就无法再存储key了。

Redis监控命令-monitor

这个 monitor 命令是一把双刃剑。
在实际工作中要慎用。
先演示一下:

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379> monitor
OK

执行代码 RedisSingle.java 中的代码,然后会发现monitor监控到我们对redis的所有操作

[root@bigdata04 redis-5.0.9]# redis-cli
127.0.0.1:6379> monitor
OK
1768628815.007443 [0 192.168.182.1:60633] "SET" "jedis" "hello bigdata!"
1768628815.007797 [0 192.168.182.1:60633] "GET" "jedis"

monitor可以监控我们对redis的所有操作,如果在线上的服务器上打开了这个功能,这里面就会频繁打印出来我们对redis数据库的所有操作,这样会影响redis的性能,所以说要慎用。
但是在某些特殊的场景下面它是很有用的
之前在工作中我遇到过一个很奇怪的问题,redis中的一个key总是会莫名其妙的消失。
我的一个程序会定时向redis中写入一个key,但是我发现这个key刚写进去,然后一会就没了,很奇怪,当时我仔细排查了我的代码,里面既没有设置失效时间,也没有使用删除功能。
所以这个key不是我的代码删的,肯定是有其它的代码会删除这个key,但是到底是哪的代码?
这个时候就不好排查了,我们的业务机有几十台,根本无从下手。
这个时候我突然想到了monitor这个命令,虽然开启monitor会影响redis的性能,但是这个时候需要排查问题,使用一会也是可以接受的。
所以就打开了monitor,打开之后屏幕上就打印出来很多命令,这样根本就看不清,没办法追踪,数据太多了。所以又想到了这个办法,结合grep命令来操作,这样就可以过滤出来对指定key的所有操作了。

[root@bigdata04 redis-5.0.9]# redis-cli monitor | grep key
1768629282.484868 [0 192.168.182.1:52364] "del" "key"

通过这条数据我们可以分析出来到底是哪台机器上的程序删除了这个key。然后再排查这台机器上都有哪些程序,对应的去排查代码,这样就快多了,最终发现是有一个代码里面会定时删除这个key。
这个就是monitor的典型应用。

Redis架构演进

现在我们使用的Redis是单机的,单机的Redis存在单点故障的问题,
所以Redis提供了主从复制的方案

主从复制

Redis的复制功能支持多个数据库之间的数据同步。
通过Redis的复制功能可以很好的实现数据库的 读写分离,提高服务器的负载能力。
主数据库(Master)主要进行写操作,而从数据库(Slave)负责读操作。个主数据库可以有多个从数据库,而一个从数据库只能有一个主数据库

image.png

这个就是redis的主从复制架构
master节点,是主数据库,负责写操作,下面的3个slave节点是从数据库,负责读操作。
当我们把数据写入到master节点之后,master节点会把数据同步给下面的3个从节点。
这就是Redis的主从复制架构。这种架构其实存在一个问题,如果主节点挂了,从节点是无法自动切换为主节点的。所以这个时候只能读数据,不能写数据。这样肯定还是存在单点故障的。所以redis在这个架构的基础上又提供了sentinel 哨兵机制。

Sentinel

这个sentinel哨兵机制提供了三个功能

  1. 监控:Sentinel实时监控主服务器和从服务器运行状态
  2. 提醒:当被监控的某个Redis服务器出现问题时,Sentinel 可以向系统管理员发送通知, 也可以通过API向其它程序发送通知
  3. 自动故障转移:当一个主服务器不能正常工作时,Sentinel可以将一个从服务器升级为主服务器, 并对其它从服务器进行配置,让它们使用新的主服务器。

看下面这个图:
image.png

上面这两个sentine1和sentinel2就是使用redis启动的哨兵服务。
他们两个可以监控下面的这个主从架构的redis,当发现master宕机之后,会把slave切换为。master。
这里面涉及两个概念,大家需要注意一下一个是主观下线状态,一个是客观下线状态

主观下线状态表示是单个sentinel实例对节点做出的下线判断
客观下线状态表示是多个sentinel实例对主节点做出的下线判断

注意:针对主节点,它具有主观下线状态和客观下线状态,在这个架构里面,如果sentinel1
认为master节点挂了,那么会给它标记为主观下线状态,此时,并不会进行故障转移,有可能是sentinel1误判了,当sentinel2也认为master节点挂了,那么此时会给master标记为客观下线状态,因为这个时候不是一个人认为它挂了,当被标记为客观下线状态之后,此时就会进行故障转移了,slave节点就会变成master节点了。针对从节点而言,只有主观下线状态,就算是误判也没有什么影响。这就是Redis中的sentinel哨兵机制。

sentinel哨兵机制虽然解决了主从节点故障自动转移的问题,但是还存在一个问题,针对这种架构,不管你使用多少台机器,redis的最终存储能力还是和单台机器有关的。如果我们想存储海量数据的话,这种架构理论上是实现不了的。基于此,Redis提供了集群这种架构。

集群

Redis集群是一个无中心的分布式Redis存储架构,可以在多个节点之间数据共享,解决了Redis高可用、可扩展等问题。
一个Redis集群包含 16384 个哈希槽(hash slot),数据库中的每个数据都属于这16384个哈希槽中的一个集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽,集群中的每一个节点负责维护一部分哈希槽。
集群中的每个节点都有1个至N个复制品,其中一个是主节点其余的是从节点,如果主节点下线了,集群就会把这个主节点的一个从节点设置为新的主节点,继续工作。

注意:如果某一个主节点和它所有的从节点都下线的话,集群就会停止工作了

image.png

里面红色的表示是5个master节点,此时redis集群的存储能力就是这5个master节点内存的总和。
针对每一个master节点,外面都有两个从节点,master节点宕机之后,对应的slave节点会自动切换为master节点,保证集群的稳定性和可用性。

如果master1和slave2、slave10这三个节点都宕机了,那么此时集群就无法使用了。
针对Redis集群而言,它是一个无中心节点的分布式存储架构。
我们在操作集群的时候,可以连接到集群的任意一个节点去操作,都是可以的,在使用的时候不用管数据到底存储在哪个节点上面,这个是redis底层去处理的,我们只需要连接到任意一台机器去操作即可。集群架构里面已经包含了主从架构和sentinel的功能,不需要单独配置了。

相关文章:

Redis极速上手开发手册【Redis全面复习】

文章目录 什么是RedisRedis的特点Redis的应用场景Redis安装部署Redis基础命令Redis多数据库特性Redis数据类型Redis数据类型之stringRedis数据类型之hashRedis数据类型之listRedis数据类型之setRedis数据类型之sorted set案例&#xff1a;存储高一班的学员信息 Redis封装工具类…...

[动态规划] (十四) 简单多状态 LeetCode LCR 091.粉刷房子

[动态规划] (十四) 简单多状态 LeetCode LCR 091.粉刷房子 文章目录 [动态规划] (十四) 简单多状态 LeetCode LCR 091.粉刷房子题目解析解题思路状态表示状态转移方程初始化和填表顺序返回值 代码实现总结 LCR 091. 粉刷房子 题目解析 (1) 一排房子&#xff0c;共有n个 (2) 染…...

【VSS版本控制工具】

VSS版本控制工具 1 安装 VSS2 服务器端配置3 新建用户4 客户端配置Vss2005Vs20055 客户端详细操作 1 安装 VSS 第一步&#xff1a;将VisualSourceSafe2005安装包解压。 第二步&#xff1a;找到setup.exe双击运行。 第三步&#xff1a;在弹出的界面复选框中选中Iaccepttheterms…...

数据持久化技术(Python)的使用

传统数据库连接方式&#xff1a;mysql&#xff08;PyMySQL&#xff09;ORM 模型&#xff1a;SQLAlchemy MyBatis、 Hibernate PyMySQL 安装&#xff1a; pip install pymysql简单使用 利用 pymysql.connect 建立数据库连接并执行 SQL 命令&#xff08;需要提前搭建好数据库…...

第23章(上)_索引原理之索引与约束

文章目录 索引索引分类主键选择索引的代价 约束外键约束约束与索引的区别 索引使用场景不要使用索引的场景总结 索引 索引的概念&#xff1a;索引是一种有序的存储结构。索引按照单个或多个列的值进行排序。 索引的目的&#xff1a;提升搜索效率。 索引分类 按照数据结构分为…...

金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件

文章目录 金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件背景说明业务需求格式BOS配置 金蝶云星空BOS设计器中基础资料字段属性“过滤”设置获取当前界面的基础资料值作为查询条件 背景说明 序列号档案是基础资料&#xff0c;资料里…...

OFDM深入学习及MATLAB仿真

文章目录 前言一、OFDM 基本原理及概念1、OFDM 简介2、子载波3、符号4、子载波间隔与符号长度之间的关系 二、涉及的技术1、保护间隔2、交织3、信道编码4、扩频5、导频6、RF&#xff08;射频&#xff09;调制7、信道估计 三、变量间的关系四、IEEE 802.11a WLAN PHY 层标准五、…...

软件测试简历原来是写了这些才让面试官已读不回

前言&#xff1a; 马上就到了面试跳槽涨薪好时候了&#xff0c;最近看很多的小伙伴已经开始投简历了&#xff0c;一天投了几十次几百次&#xff0c;面试官已读不会&#xff0c;面试的机会都没有更别说后面的事情的&#xff0c;这是为什么呢&#xff1f; 很大一部分的原因是的…...

ESP32网络开发实例-Web服务器RGB LED调光

Web服务器RGB LED调光 文章目录 Web服务器RGB LED调光1、RGB LED介绍3、软件准备4、硬件准备4、代码实现在本文中,我们将创建一个 RGB LED 控制器网络服务器。 Web 服务器将显示用于设置 RGB LED 颜色的色谱。 颜色将主要分为三种:红色、绿色和蓝色。 用户将从光谱中选择一种…...

C# TCP Server服务端多线程监听RFID读卡器客户端上传的读卡数据

本示例使用设备介绍&#xff1a;液显WIFI无线网络HTTP协议RFID云读卡器可编程实时可控开关TTS语-淘宝网 (taobao.com) using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using Sy…...

【electron】【附排查清单】记录一次逆向过程中,fetch无法请求http的疑难杂症(net::ERR_BLOCKED_BY_CLIENT)

▒ 目录 ▒ &#x1f6eb; 导读需求开发环境 1️⃣ Adblock等插件拦截2️⃣ 【失败】Content-Security-Policy启动服务器json-serverhtml中的meta字段 3️⃣ 【失败】https vs httpwebPreferences & allowRunningInsecureContent disable-features 4️⃣ 【失败】检测fetch…...

【JS】scrollTop+scrollHeight+clientTop+clientHeight+offsetTop+offsetHeight

scrollTop、scrollHeight、clientTop、clientHeight、offsetTop以及offsetHeight 1. scrollTop 与 scrollHeight 1.1 scrollTop scrollTop 是这六个属性中唯一一个可写的属性。 Element.scrollTop 属性可以获取或设置一个元素的内容垂直滚动的像素数。 一个元素的 scrollT…...

Go语言函数用法

文章目录 Go语言函数用法 Go语言函数用法 函数在Go语言中有多种用法&#xff0c;它们是组织和模块化代码、提高代码的可维护性和可重用性的关键部分。以下是函数的一些常见用法&#xff1a; 封装代码&#xff1a;函数允许将一组相关的代码块封装到一个独立的单元中&#xff0c…...

3.5、Linux:命令行git的使用

个人主页&#xff1a;Lei宝啊 愿所有美好如期而遇 在Linux Centos7.6下安装git yum -y install git 注册一个gitee账号 进去注册就好&#xff0c;记住自己的用户名和密码。 创建一个仓库 点击复制&#xff0c;接着就可以在Linux上使用了 git clone git clone 刚才复制的地…...

基于servlet+jsp+mysql网上书店系统

基于servletjspmysql网上书店系统 一、系统介绍二、功能展示四、其它1.其他系统实现五.获取源码 一、系统介绍 项目类型&#xff1a;Java web项目 项目名称&#xff1a;基于servletjspmysql网上书店系统 项目架构&#xff1a;B/S架构 开发语言&#xff1a;Java语言 前端技…...

自用工具类整理

自动生成数据 uuid&雪花id private static Long workerId 1L; private static Long datacenterId 1L; private static Snowflake snowflake IdUtil.createSnowflake(workerId, datacenterId);public static String getId(String idType) {if (idType.equals("uui…...

jenkins2

jenkins插件管理安装&#xff1a;docker-build jenkins安装了docker 配置docke builder 添加 unix:///var/run/docker.sock rootubuntu20:~# usermod -G docker jenkins 修改docker中service文件添加 -H tcp://0.0.0.0:2376 jenkins中系统管理中 tcp://localhost:2376...

YOLOv5独家改进:分层特征融合策略MSBlock | 南开大学提出YOLO-MS |超越YOLOv8与RTMDet,即插即用打破性能瓶颈

💡💡💡本文独家改进:分层特征融合策略MSBlock,不同Kernel-Size卷积在不同尺度提升特征提取能力,最终引入到YOLOv5,做到二次创新 1)MSBlock使用;2)和C3结合使用 推荐指数:5颗星 MSBlock | 亲测在多个数据集能够实现大幅涨点,小目标检测效果也不错 💡💡…...

HTTP 协议详解-上(Fiddler 抓包演示)

文章目录 HTTP 协议HTTP 协议的工作过程HTTP 请求 (Request)认识URL关于 URL encode认识 "方法" (method)GET 方法POST 方法其他方法请求 "报头" (header)请求 "正文" (body) HTTP 响应详解状态码响应 "报头" (header) HTTP 协议 HTT…...

龙迅LT8911EXB功能概述 MIPICSI/DSI TO EDP

LT8911EXB 描述&#xff1a; Lontium LT8911EXB是MIPIDSI/CSI到eDP转换器&#xff0c;单端口MIPI接收器有1个时钟通道和4个数据通道&#xff0c;每个数据通道最大运行2.0Gbps&#xff0c;最大输入带宽为8.0Gbps。转换器解码输入MIPI RGB16/18/24/30/36bpp、YUV422 16/20/24bp…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

三维GIS开发cesium智慧地铁教程(5)Cesium相机控制

一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点&#xff1a; 路径验证&#xff1a;确保相对路径.…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN&#xff0c;根据VPN原理&#xff0c;打通两个内网必然需要借助一个公共中继节点&#xff0c;ktconnect工具巧妙的利用k8s原生的portforward能力&#xff0c;简化了建立连接的过程&#xff0c;apiserver间接起到了中继节…...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)

文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...