Redis总结(上)

导读:本篇文章讲解 Redis总结(上),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

Redis 总结

1.Nosql

1.1Nosql概述

为什么要用Nosql

  1. 单机mysql的年代
    app———>dal————>mysql
  2. Memcached(缓存)+mysql+垂直拆分(读写分离)
    优化数据结构和索引–>文件缓存(IO)–>Memcached
  3. 分库分表+水平拆分+mysql集群
    本质:数据库(读,写)
    早些年Myisam :表锁,十分影响效率!高并发下就会出现严重的锁问题。
    转战Innodb :行锁
    慢慢就开始了分库分表来缓解压力。

1.2什么是Nosql

Nosql = Not Only Sql(不仅仅是sql)
泛指非关系型数据库

1.3Nosql特点

解耦!

  • 方便扩展 (数据之间没有关系,很好扩展)
  • 大数据量高性能!(Redis 一秒写8万次,读取11万次)
  • 数据类型是多样型的。(不需要实现设计数据库,随取随用)

传统的RDBMS和NoSql

 传统的 RDBMS
- 结构化组织
- SQL
- 数据和关系都存在单独的表中
- 操作数据,数据定义语言
- 严格的一致性
- 基础的事务
- .......
 NoSql
- 不仅仅是数据
-  没有固定的查询语言
-  键值对存储,列存储,文档储存,图形化存储
-  最终一致性
-  CAP定理BASE
-  高性能、高可用、高可扩展
-  .......

阿里巴巴框架演进
nosql 数据模型
KV键值对:
新浪:Redis
美团:Redis + Tair
阿里、百度:Redis + memecache
文档型数据库:
MongoDB
MonoDB是一个基于分布式文件存储的数据库,C++编写,主要用来处理大量的文档
MonoDB是一个介于关系型数据库和非关系型数据库中中间的产品 (MonoDB是非关系型数据库功能最丰富的,最想关系型数据库)
ConthDB
列存储:
HBase
分布式文件系统
图形化数据库:
他不是存图形的,放的是关系,比如:朋友圈社交网络、广告推荐!
Neo4J、InfoGrid
Nosql 四大分类
CAP
BASE

2.Redis入门

2.1Redis是什么

Redis(Remote Dictionary Server ),即远程字典服务
是一个开源的使用ANSI C语言编写,支持网络,可基于内存亦可持久化的日志型,key-value数据库,并提供多种语言的API

免费和开源,是当下最热门的NoSql技术之一,也被人们称之为架构话数据库。

2.2Redis能干什么

  • 内存存储,持久化,内存中的数据是断电及失,所以说持久化很重要。(RDB,AOF)
  • 效率高,可以用于告诉缓存
  • 发布订阅系统
  • 地图信息分析
  • 计时器,计数器。(数据浏览量)

2.3Redis特性

  • 持久化
  • 多样化数据库
  • 集群
  • 事务

3.安装Redis

Windows安装
windows :下载地址 redis下载

下载完成解压

image-20210312190659183

启动Redis服务器:

双击运行服务 redis-server.exe

image-20210312191028923

运行成功

再次运行redis客户端 启动 redis-cli.exe

127.0.0.16379> ping  ----> 测试是否连接成功
PONG 
127.0.0.16379> set name liyang  -----> 设置 key value
OK
127.0.0.16379> get name  ------> 用 key 去寻找 value
"liyang"

Linux安装
官网下载:地址下载地址

下载完成之后导入到 Liunx 的 opt 目录下面

执行 tar -zxvf redis... 进行解压

解压完成只要需要安装c++ 环境 yum -y install gcc-c++

安装完成执行 make

image-20210313130749997

执行完成之后在执行一遍

然后执行 make install

image-20210313130858601

redis 的默认路径在 usr/local/bin目录下面

mage-20210313131120947

移动 redis.config 到 本目录下

image-20210313131349900

redis默认不是后台启动,我们需要修改配置文件

找到这个修改为 yes

image-20210313131611230

启动redis 服务

image-20210313131826979

测试连接

image-20210313132042196

查看redis服务信息

image-20210313132339207

关闭redis

127.0.0.16379> shutdown   --->关闭redis
not connected> exit   ---> 退出

redis性能测试

序号 选项 描述 默认值
1 -h 指定服务器主机名 127.0.0.1
2 -p 指定服务器端口 6379
3 -s 指定服务器 socket
4 -c 指定并发连接数 50
5 -n 指定请求数 10000
6 -d 以字节的形式指定 SET/GET 值的数据大小 2
7 -k 1=keep alive 0=reconnect 1
8 -r SET/GET/INCR 使用随机 key, SADD 使用随机值
9 -P 通过管道传输 <numreq> 请求 1
10 -q 强制退出 redis。仅显示 query/sec 值
11 —csv 以 CSV 格式输出
12 -l 生成循环,永久执行测试
13 -t 仅运行以逗号分隔的测试命令列表。
14 -I Idle 模式。仅打开 N 个 idle 连接并等待。

测试 使用 redis-benchmark

测试 :100个并发连接, 100000 请求
命令:redis-benchmark -h 127.0.0.0 -p 6379 -c 100 -n 100000

====== PING_INLINE ======                                                   
  100000 requests completed in 2.31 seconds    ----> 对我们10w请求进行测试
  100 parallel clients    -----> 100个并发的客服端
  3 bytes payload    ----> 每次写入3个字节
  keep alive: 1   ---> 只有一台服务器来处理这些请求,单机性能
  host configuration "save"3600 1 300 100 60 10000
  host configuration "appendonly": no
  multi-thread: no
====== SET ======                                                   
  100000 requests completed in 2.31 seconds
  100 parallel clients
  3 bytes payload
  keep alive: 1
  host configuration "save"3600 1 300 100 60 10000
  host configuration "appendonly": no
  multi-thread: no
Latency by percentile distribution:
0.000% <= 0.935 milliseconds (cumulative count 1)
50.000% <= 1.599 milliseconds (cumulative count 50402)
75.000% <= 1.895 milliseconds (cumulative count 75422)
87.500% <= 2.039 milliseconds (cumulative count 87552)
93.750% <= 2.143 milliseconds (cumulative count 93953)
96.875% <= 2.487 milliseconds (cumulative count 96893)
98.438% <= 3.607 milliseconds (cumulative count 98439)
99.219% <= 6.535 milliseconds (cumulative count 99219)
99.609% <= 12.039 milliseconds (cumulative count 99613)
99.805% <= 12.583 milliseconds (cumulative count 99805)
99.902% <= 13.031 milliseconds (cumulative count 99903)
99.951% <= 13.479 milliseconds (cumulative count 99952)
99.976% <= 13.775 milliseconds (cumulative count 99976)
99.988% <= 13.927 milliseconds (cumulative count 99988)
99.994% <= 14.007 milliseconds (cumulative count 99994)
99.997% <= 14.039 milliseconds (cumulative count 99997)
99.998% <= 14.071 milliseconds (cumulative count 99999)
99.999% <= 14.087 milliseconds (cumulative count 100000)
100.000% <= 14.087 milliseconds (cumulative count 100000)

4.基础知识

在这里插入图片描述

4.1Redis默认数据库

redis默认有16个数据库,默认使用第0个

  • select 2 更换数据库
  • dbsize 查看数据库大小
  • keys* 查看数据库所有的key
  • flushdb 清空当前数据库
  • flushall 清空所有库
[root@VM-0-5-centos changanconfig]# redis-cli -p 6379
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> select 2   ---->  更换数据库
OK
127.0.0.1:6379[2]> dbsize  -----> 查看数据库大小
(integer) 0
127.0.0.1:6379[2]>

4.2Redis数据类型

五种基本数据类型

  • Redis-key
  • String
  • List
  • Set
  • Hash
  • Zset

Redis-key

keys* 查看当前库所有的key

exists name 判断namekey 是否存在

move name 1 移除 name

expire name 10 设置name 10秒钟之后过期

ttl name 查看过期时间

type name 查看当前 key 的类型

String

append 追加字符串

127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"changan"
127.0.0.1:6379> append name love    
(integer) 11
127.0.0.1:6379> get name
"changanlove"
127.0.0.1:6379> exists name
(integer) 1

incr views 给 views 加1

decr views 给 views 减1

incrby views 给 views 加10

decrby views 给 views 减10

127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views
(integer) 1
127.0.0.1:6379> decr views
(integer) 0
127.0.0.1:6379> incrby views 10
(integer) 10
127.0.0.1:6379> decrby views 10

getrange 范围查询数据

127.0.0.1:6379> getrange key1 0 3
"hell"
127.0.0.1:6379> getrange key1 0 -1
"hello,word"
127.0.0.1:6379> getrange key1 5 -1
",word"
127.0.0.1:6379> getrange key1 5 0
""
127.0.0.1:6379> getrange key1 1 -1
"ello,word"
127.0.0.1:6379> getrange key1 0 -1

setrange 范围修改

127.0.0.1:6379> setrange key1 1 xx
(integer) 10
127.0.0.1:6379> keys *
1) "key1"
127.0.0.1:6379> get key1
"hxxlo,word"

常在分布式锁使用
setex 设置过期时间
setnx 如果key不存在,创建key返回1,如果存在则创建失败,返回0

127.0.0.1:6379> setex key2 30 "hello"   ---- > 设置过期时间
OK
127.0.0.1:6379> ttl key2                ---- > 查看剩余时间
(integer) 28
127.0.0.1:6379> setnx mykey "redis"     ---- > 如果 mykey 不存在,创建 mykey 返回1 
(integer) 1
127.0.0.1:6379> keys *   
1) "key2"
2) "key1"
3) "mykey"
127.0.0.1:6379> ttl key2 
(integer) -2
127.0.0.1:6379> setnx mykey "MongDB"    ---- > 如果 mykey 存在,就创建失败 返回0
(integer) 0
127.0.0.1:6379> get mykey
"redis"

批量获取值和设置值
mset 批量设置

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k2"
3) "k1"

mget 同时获取多个值

127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"

msetnx 设置多个值 如果一个值设置失败,那么全部失败 (原子性)

127.0.0.1:6379> msetnx k1 v1 k5 v5
(integer) 0

getset 先获取在设置

127.0.0.1:6379> getset db redis   --> 不存在返回nil并创建
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db mongDb  --> 如果存在,返回当前的值,并设置新的值
"redis"
127.0.0.1:6379> get db
"mongDb"

应用场景

  • 计数器
  • 统计多单位数量
  • 粉丝数
  • 对象缓存存储

List

基本数据类型,列表

lpush 储存 《左存储》

rpush 储存 《右存储》

lrange 读取

127.0.0.1:6379> lpush list one  ---> 给左push
(integer) 1
127.0.0.1:6379> lpush list two
(integer) 2
127.0.0.1:6379> lpush list three
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> lrange list 0 1
1) "three"
2) "two"
#####################################################################
127.0.0.1:6379> rpush list yss
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "yss"

lpop : 左移除

rpop : 右移除

127.0.0.1:6379> lpop list ----> 移除list第一个元素
"three"
127.0.0.1:6379> rpop list ----> 移除list最后一个元素
"yss"
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"

lindex 通过下标获取值

127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> lindex list 1
"one"

llen 获取list的长度

127.0.0.1:6379> llen list
(integer) 4

lrem 删除 ‘精确匹配’

127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "asdfa"
4) "9889"
5) "9889"
127.0.0.1:6379> lrem list 1 asdfa  ----- > 删除 1个 asdfa
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "9889"
4) "9889"
127.0.0.1:6379> rpush list 9889
(integer) 4
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"
3) "9889"
4) "9889"
127.0.0.1:6379> lrem list 2 9889   ------ > 删除 29889
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "two"
2) "one"

ltrim 修剪

127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "hello1"
(integer) 2
127.0.0.1:6379> rpush mylist "hello2"
(integer) 3
127.0.0.1:6379> rpush mylist "hello3"
(integer) 4
127.0.0.1:6379> ltrim mylist 1 2   ----- > 通过下标截取指定长度
OK
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"

rpoplpush 移除列表的最后一个元素 并移动到新的列表中

127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
3) "hello3"
127.0.0.1:6379> rpoplpush mylist myotherlist
"hello3"
127.0.0.1:6379> lrange mylist 0 -1
1) "hello1"
2) "hello2"
127.0.0.1:6379> lrange myotherlist 0 -1
1) "hello3"

lset 将列表中指定下标的值替换为另外一个

127.0.0.1:6379> exists list   --- >  判断是否有这个集合
(integer) 0
127.0.0.1:6379> lset list 0 item   ----- > 给list的第0个下标添加 item
(error) ERR no such key    ---> 报错,添加失败 没有这个list
127.0.0.1:6379> lpush list value1  ------ > 创建 list
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "value1"
127.0.0.1:6379> lset list 0 item   ----- > 再次用 lset 覆盖 刚创建那个list的第0个下标
OK
127.0.0.1:6379> lrange list 0 -1
1) "item"
127.0.0.1:6379> lset list 1 item  -----> 如果给list添加值 这个下标不存在那么就会报错
(error) ERR index out of range

linsert 将某一个具体的值插入列表某个元素的前后
参数before 左、前 after 右、后

127.0.0.1:6379> rpush mylist "hello"
(integer) 1
127.0.0.1:6379> rpush mylist "word"
(integer) 2
// before
127.0.0.1:6379> linsert mylist before "word" "other"  
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "word"
// after
127.0.0.1:6379> linsert mylist after "word" "king"
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "other"
3) "word"
4) "king"

小结

  • list实际是一个链表,before Node after,left ,right 都可以插入值
  • 如果key 不存在,创建新的链表
  • 如果key 存在,新增内容
  • 如果移除了所有的值,空链表,也代表不存在
  • 在两边插入或改动值,效率最高!中间元素,相对来说效率会第一点
  • 可以用来 消息排队! 消息队列(Lpush Rpop) 左进右出 ,栈(Lpush Lpop)左进左出

Set

sadd 给集合添加值

smembers 查看当前集合元素

sismember 查看当前集合是否有某个元素

scard 获取当前集合的个数

127.0.0.1:6379> sadd myset hello   ----> 给集合添加值
(integer) 1
127.0.0.1:6379> sadd myset changan  
(integer) 1
127.0.0.1:6379> sadd myset king
(integer) 1
127.0.0.1:6379> SMEMBERS myset    -----> 查看当前集合元素
1) "king"
2) "changan"
3) "hello"
127.0.0.1:6379> SISMEMBER myset hello   -----> 查看集合是否有hello  有的话返回1 没有就是0
(integer) 1
127.0.0.1:6379> SISMEMBER myset word
(integer) 0
127.0.0.1:6379> scard myset   ------> 获取当前集合的个数
(integer) 3
127.0.0.1:6379> srem myset hello   -----> 删除集合指定的值
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "king"
2) "changan"

SRANDMEMBER 随机从集合中筛选一个数据

127.0.0.1:6379> SRANDMEMBER myset
"king"
127.0.0.1:6379> SRANDMEMBER myset
"king"
127.0.0.1:6379> SRANDMEMBER myset
"king"
127.0.0.1:6379> SRANDMEMBER myset
"king"
127.0.0.1:6379> SRANDMEMBER myset
"changan"

spop 随机删除一个元素

127.0.0.1:6379> SMEMBERS myset
1) "king"
2) "changan"
127.0.0.1:6379> spop myset
"king"
127.0.0.1:6379> SMEMBERS myset
1) "changan"

smove将一个指定的值移动到另外一个set集合中

127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset word
(integer) 1
127.0.0.1:6379> sadd myset changanking
(integer) 1
127.0.0.1:6379> sadd myset king
(integer) 1
127.0.0.1:6379> sadd myset2 set2
(integer) 1
127.0.0.1:6379> smove myset myset2 changanking    
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "word"
2) "hello"
3) "changan"
4) "king"
127.0.0.1:6379> SMEMBERS myset2
1) "changanking"
2) "set2"

SDIFF 查看2个集合的差集

SINTER 查看2个集合的交集 共同好友就可以实现

SUNION 查看2个集合的

127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> SDIFF key1 key2
1) "a"
2) "b"
127.0.0.1:6379> SINTER key1 key2
1) "c"
127.0.0.1:6379> SUNION key1 key2
1) "c"
2) "b"
3) "a"
4) "d"
5) "e"

应用场景
微博 ,A用户将所有的关注的人放在一个set集合中,将他的粉丝也放在一个集合中

共同关注,共同爱好,二度好友,推荐好友!

Hash

Map集合,Key—Value

127.0.0.1:6379> hset map k changan   ---->  给map存一个k-v
(integer) 1
127.0.0.1:6379> hget map k           ---->  通过k取值
"changan"
127.0.0.1:6379> hmset map y king u anuyn  ---->  给map存多个值
OK 
127.0.0.1:6379> hmget map y u           ---->  获取map多个值
1) "king"
2) "anuyn"
127.0.0.1:6379> hgetall map              ------> 查看map所有的kv
1) "k"
2) "changan"
3) "y"
4) "king"
5) "u"
6) "anuyn"

hdel 删除指定的kv

127.0.0.1:6379> hdel map u     -----> 删除指定的 k
(integer) 1
127.0.0.1:6379> hgetall map
1) "k"
2) "changan"
3) "y"
4) "king"

hlen 查询集合有几组kv

127.0.0.1:6379> hlen map
(integer) 2
HEXISTS 查看集合的k是否存在

127.0.0.1:6379> HEXISTS map k
(integer) 1
127.0.0.1:6379> HEXISTS map u
(integer) 0
hkeys 查看所有的key

hvals 查看所有的value

127.0.0.1:6379> hkeys map

  1. “k”
  2. “y”
    127.0.0.1:6379> hvals map
  3. “changan”
  4. “king”
    HINCRBY 指定增量

hsetnx 创建一个集合 如果这个集合没有数据 就放入数据 返回1 如果有数据 那么返回0

127.0.0.1:6379> hset myhash field3 5 —– >>> 指定增量
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 1 ——>>> 给数据加一
(integer) 6
127.0.0.1:6379> HINCRBY myhash field3 -1 ——>>>> 给数据减一
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello ——-> 创建一个集合 如果存在则不能设置 返回1
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world —->> 创建一个集合 如果存在则不能设置 返回0
(integer) 0
hash可以用于存储对象

127.0.0.1:6379> hset user:1 name changan
(integer) 1
127.0.0.1:6379> hget user:1 name
"changan"
127.0.0.1:6379> hset user:1 age 23
(integer) 1
127.0.0.1:6379> hget user:1 age
"23"

应用场景
hash 用来处理变更的数据 user name age ,尤其是用户信息之类,经常变动的信息! hash 更适合与对象的存储,String 适合字符串的存储!

Zset(有序集合)

在set的基础上加了一个值

api:

127.0.0.1:6379> zadd myset 1 one     -----> 创建一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three   ----->  创建2个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1   ------> 获取myset 里的数据
1) "one"
2) "two"
3) "three"

zrangebyscore : 从低到高 进行排序

zrevrange : 从高到低 进行排序

127.0.0.1:6379> zadd salary 5000 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 2500 xiaoming
(integer) 1
127.0.0.1:6379> zadd salary 500 zhangsan
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf   ---- > 通过集合salary 的 钱数排序 -inf 负无穷  +inf 正无穷
    从低到高
1) "zhangsan"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> zrevrange salary 0 -1
1) "xiaoming"
2) "zhangsan"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores  -->> 查询出来所有数据 WITHSCORES会返回元素和其分数
1) "zhangsan"
2) "500"
3) "xiaoming"
4) "2500"
5) "xiaohong"
6) "5000"
127.0.0.1:6379> zrangebyscore salary -inf 2500 withscores
1) "zhangsan"
2) "500"
3) "xiaoming"
4) "2500"

zrem 移除

127.0.0.1:6379> zrange salary 0 -1
1) "zhangsan"
2) "xiaoming"
3) "xiaohong"
127.0.0.1:6379> zrem salary xiaohong
(integer) 1

zcard 获取集合中的个数

127.0.0.1:6379> zcard salary
(integer) 2
zcount 获取指定区间的成员数量

127.0.0.1:6379> zadd myset 1 "hello" 2 "word" 3 "changan"
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2
127.0.0.1:6379> zcount myset 1 3
(integer) 3

使用场景
set 排序 存储班级成绩,工资排序

普通消息 1、重要消息 2 带权重进行判断

排行榜应用实现 取 Top N测试

4.3 三种特殊数据类型

geospatial 地理位置
Redis 的 Geo 可以去实现 推算2地之间的距离,推算地理位置信息 …… !

测试数据网站:http://www.toolzl.com/tools/gps.html
在这里插入图片描述

Geoadd 添加地理位置

2极地区无法直接添加,我们一般会下载城市数据,用Java程序导入

将指定的地理空间位置(纬度、经度、名称)添加到指定的key中

有效经度为-180至180度。
有效纬度为-85.05112878至85.05112878度。

127.0.0.1:6379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 106.50 29.53 chongqi 114.05 22.52 shenzhen
(integer) 2
127.0.0.1:6379> geoadd china:city 120.16 30.24 hangzhou 108.96 34.26 xian 
(integer) 2

geopos 查询地理位置

127.0.0.1:6379> geopos china:city beijing
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
127.0.0.1:6379> geopos china:city xian
1) 1) "108.96000176668167114"
   2) "34.25999964418929977"

geodist 返回两个给定位置之间的距离

如果两个位置之间的其中一个不存在, 那么命令返回空值。

指定单位的参数 unit 必须是以下单位的其中一个:

  • m 表示单位为米。
  • km 表示单位为千米。
  • mi 表示单位为英里。
  • ft 表示单位为英尺。
127.0.0.1:6379> geodist china:city beijing xian km   北京到西安的直线距离
"910.0565"
127.0.0.1:6379> geodist china:city beijing shanghai km  北京带上海的直线距离
"1067.3788"

附近的人

半径搜索

127.0.0.1:6379> georadius china:city 110 30 1000 km  以 110,30的地理坐标 查询 1000km 内的城市
1) "chongqi"
2) "xian"
3) "shenzhen"
4) "hangzhou"
127.0.0.1:6379> georadius china:city 110 30 500 km 以 110,30的地理坐标 查询 500km 内的城市
1) "chongqi"
2) "xian"
127.0.0.1:6379> georadius china:city 110 30 500 km withdist   到中心的直线距离
1) 1) "chongqi"
   2) "341.9374"
2) 1) "xian"
   2) "483.8340"
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord   经纬度
1) 1) "chongqi"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"
2) 1) "xian"
   2) 1) "108.96000176668167114"
      2) "34.25999964418929977"
127.0.0.1:6379> georadius china:city 110 30 500 km withcoord count 1  查询指定数量的
1) 1) "chongqi"
   2) 1) "106.49999767541885376"
      2) "29.52999957900659211"

GEORADIUSBYMEMBER

找出位于指定元素周围的其他元素

127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"
127.0.0.1:6379> GEORADIUSBYMEMBER china:city beijing 500 km
1) "beijing"

删除、查看

127.0.0.1:6379> zrange china:city 0 -1   查看所有
1) "chongqi"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"
6) "beijing"
127.0.0.1:6379> zrem china:city beijing  删除
(integer) 1
127.0.0.1:6379> zrange china:city 0 -1
1) "chongqi"
2) "xian"
3) "shenzhen"
4) "hangzhou"
5) "shanghai"

Hyperloglog 基数统计
什么是基数!

A{ 1、3、5、7、8、7 }

B{ 1、3、5、7、8 }

基数 (不重复的元素)= 5,可以接收误差!

简介

pfadd :添加数据

pfcount :查询数据

pfmerge :合并数据

127.0.0.1:6379> pfadd mykey a b c d e f g h i j k
(integer) 1
127.0.0.1:6379> pfcount mykey
(integer) 11
127.0.0.1:6379> pfadd mykey2 b c d t y o p
(integer) 1
127.0.0.1:6379> pfcount mykey2
(integer) 7
127.0.0.1:6379> pfmerge mykey3 mykey mykey2
OK
127.0.0.1:6379> pfcount mykey3
(integer) 14

Bitmaps(位图) 位存储

只要是2位数的 数据结构就可以用

如:登录、未登录 活跃、不活跃

设置或者清空key的value(字符串)在offset处的bit值。

那个位置的bit要么被设置,要么被清空,这个由value(只能是0或者1)来决定。当key不存在的时候,就创建一个新的字符串value

测试

测试打卡记录 在2021年4月15日没有打卡等

setbit 存值

getbit 取值

bitcount 查询

127.0.0.1:6379> setbit sign 20210415 0 
(integer) 0
127.0.0.1:6379> setbit sign 20210416 1
(integer) 0
127.0.0.1:6379> setbit sign 20210414 0
(integer) 0
127.0.0.1:6379> setbit sign 20210413 1
(integer) 0
127.0.0.1:6379> setbit sign 20210412 1
(integer) 0
127.0.0.1:6379> setbit sign 20210417 1
(integer) 0
127.0.0.1:6379> getbit sign 20210416
(integer) 1
127.0.0.1:6379> getbit sign 20210415
(integer) 0
127.0.0.1:6379> bitcount sign
(integer) 4

5.事务

Redis事务本质:一组命令的集合!
一个事务中所有的命令都会被序列化,在事务执行过程中,会按照顺序执行!
一次性,序列性,非它性

  • Redis事务没有隔离级别的概念
  • Redis单条命令是保存原子性的,但是事务不保证原子性
  • 所有的命令在事务中,并没有直接执行!只有发起执行命令的时候才会执行!

Redis的事务

  1. 开启事务 (multi)
  2. 命令入队 ( )
  3. 执行命令 (exec)

测试:

127.0.0.1:6379> multi     // > 开启事务
OK
127.0.0.1:6379(TX)> set k1 1    // 命令入队
QUEUED
127.0.0.1:6379(TX)> set k1 2
QUEUED
127.0.0.1:6379(TX)> set k1 3
QUEUED
127.0.0.1:6379(TX)> set k2 2
QUEUED
127.0.0.1:6379(TX)> set k3 4
QUEUED
127.0.0.1:6379(TX)> set k4 6
QUEUED
127.0.0.1:6379(TX)> get k4
QUEUED
127.0.0.1:6379(TX)> set k7 9
QUEUED
127.0.0.1:6379(TX)> exec      //  执行事务
1) OK
2) OK
3) OK
4) OK
5) OK
6) OK
7) "6"
8) OK

放弃事务:

127.0.0.1:6379> multi    // 开启事务
OK
127.0.0.1:6379(TX)> set key7 7
QUEUED
127.0.0.1:6379(TX)> discard    // 取消事务
OK
127.0.0.1:6379> get key7
(nil)

编译型异常: 命令错误

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set k1 2
QUEUED
127.0.0.1:6379(TX)> set k2 4
QUEUED
127.0.0.1:6379(TX)> set k4 5
QUEUED
127.0.0.1:6379(TX)> getset k7 8
QUEUED
127.0.0.1:6379(TX)> getset k9       //错误语法
(error) ERR wrong number of arguments for 'getset' command
127.0.0.1:6379(TX)> set k8 9
QUEUED
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors. 
    /*提示语法错误,所有命令都不执行 **/
127.0.0.1:6379> get k4
(nil)

运行时异常:如果命令中存在错误,不会影响其他命令执行

127.0.0.1:6379> set k1 7
OK
127.0.0.1:6379> set k2 "j9"
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> incr k2    // 会执行失败
QUEUED
127.0.0.1:6379(TX)> set k3 3
QUEUED
127.0.0.1:6379(TX)> set k4 5
QUEUED
127.0.0.1:6379(TX)> get k4
QUEUED
127.0.0.1:6379(TX)> exec
1) (error) ERR value is not an integer or out of range    
    // 虽然第一条命令执行失败了后面的命令会继续执行
2) OK
3) OK
4) "5"
127.0.0.1:6379> get k3
"3"
127.0.0.1:6379> get k4
"5"

监控

悲观锁
认为什么时候都会出现问题,无论做什么都会加锁

乐观锁

  • 认为什么时候都不会出现问题,所以不会上锁,可以更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 获取version
  • 更新的时候比较version

数据测试;
单线程

127.0.0.1:6379> set money 100    // 设置金钱是100
OK
127.0.0.1:6379> set out 0        // 设置金钱是0
OK
127.0.0.1:6379> watch money      // 给money上锁
OK
127.0.0.1:6379> multi     // 开启事务
OK
127.0.0.1:6379(TX)> decrby money 20    // money金钱减 20
QUEUED
127.0.0.1:6379(TX)> incrby out 20      // out 加 220
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 80
2) (integer) 20

多线程
使用watch来当做Redis的乐观锁

// 线程 1 
127.0.0.1:6379> watch money      // 开启监控
OK
127.0.0.1:6379> multi            // 开启事务
OK
127.0.0.1:6379(TX)> decrby money 10    // 金币减10
QUEUED
127.0.0.1:6379(TX)> incrby out 10      // 金币加10
QUEUED
    // 线程 2
    127.0.0.1:6379> incrby money 1000   // 线程2 给这个用户 充值 1000
    (integer) 1080
// 线程 1    
127.0.0.1:6379(TX)> exec  // 线程 1 继续执行 然后就会执行失败
(nil)

如果修改失败获取最新的值即可

解决办法:

127.0.0.1:6379> unwatch    // 放弃旧的锁
OK
127.0.0.1:6379> watch money   // 加新锁
OK
127.0.0.1:6379> multi    // 开启事务
OK
127.0.0.1:6379(TX)> decrby money 100
QUEUED
127.0.0.1:6379(TX)> incrby out 100
QUEUED
127.0.0.1:6379(TX)> exec
1) (integer) 1000
2) (integer) 120

6.Jedis

什么是Jedis

Jedis是Redis 推荐使用的Java开发工具!使用Java操作中间件!
测试
1.导入依赖

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.5.2</version>
</dependency>
<!-- fastjson-->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>

2、编码测试
连接数据库

public static void main(String[] args) {
        Jedis jedis = new Jedis("XXXXXXX",6379); // ip地址及端口号
        jedis.auth("---"); //redis 密码
        System.out.println(jedis.ping());
}

本地访问 直接 Jedis jedis = new Jedis("127.0.0.1",6379);
事务:

RedisApi api = new RedisApi();
Jedis jedis = api.connection();
jedis.flushDB();
JSONObject jsonObject = new JSONObject();
jsonObject.put("hello""word");
jsonObject.put("name""changan");
Transaction multi = jedis.multi();
String toString = jsonObject.toJSONString();
try {
    multi.set("user1",toString);        //注意事务执行的话要用事务 multi.set 而不是jedis.set
    multi.set("user2",toString);
    // int i = 1/0;
    multi.exec();
}catch (Exception e){
    multi.discard();
    e.printStackTrace();
}finally {
    System.out.println(jedis.get("user1"));
    System.out.println(jedis.get("user2"));
}

断开连接

jedis.close()

7.SpringBoot整合

说明:在SpringBoot2.x 之后 Jedis 被替换成为了 lettuce
区别:

  • Jedis : 采用直连方式 、是不安全的,要避免安全隐患要采用 Jedis的pool连接池管理! 像BIO
  • lettuce : 采用netty 实例可以在多个进程共享、不存在线程不安全问题 像NIO**

整合

1.添加依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

2.配置Redis

spring:
  redis:
    host: 服务器地址
    port: 6379
    password: redis密码

3.测试

@Resource
private RedisTemplate redisTemplate;
@Test
void contextLoads() {
    RedisConnection connection = Objects.requireNonNull(redisTemplate.getConnectionFactory()).getConnection();
    System.out.println(connection.ping());    // 测试链接是否成功
    redisTemplate.opsForValue().set("key""changan");   //  操纵字符串 set 一个值
    Object key = redisTemplate.opsForValue().get("key");  // 获取值
    System.out.println(key);
}
  • redisTemplate.opsForValue() 操作字符串
  • redisTemplate.opsForList() 操作list
connection.close();    // 关闭链接
connection.flushAll(); // 清空所有数据库的所有 key
connection.flushDb();  // 清空

测试:

@Test
public void UserTest() throws JsonProcessingException {
    RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
    connection.flushDb();
    User user = new User("长安"23);
    String s = new ObjectMapper().writeValueAsString(user);   // 转化为Json 数据
    redisTemplate.opsForValue().set("user",s);
    System.out.println(redisTemplate.opsForValue().get("user"));
}
// 输出结果  {"name":"长安","age":23}

如果我们直接传对象没有序列化 ,会报错

@Test
public void UserTest() throws JsonProcessingException {
    RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();
    connection.flushDb();
    User user = new User("长安"23);
    redisTemplate.opsForValue().set("user",user);
    System.out.println(redisTemplate.opsForValue().get("user"));
}
//Cannot serialize; nested exception is org.springframework.core.serializer.support.SerializationFailedException: Failed to serialize object using DefaultSerializer; nested exception is java.lang.IllegalArgumentException: DefaultSerializer requires a Serializable payload but received an object of type [com.changan.model.User]

如果要传递对象要序列化

public class User implements Serializable {
    private String name;
    private int age;
}
// 结果  User(name=长安, age=23)

编写一个自己的 Redis 序列化
详情请看:自定义redis序列化和工具类

8.Redis.config详解

8.1单位

在这里插入图片描述
包含 INCLUDES

在这里插入图片描述

这里包括一个或多个其他配置文件。这很有用,如果你
有一个标准的模板,去所有的Redis服务器,但也需要
自定义一些服务器设置。包括文件可以包括
其他文件,所以明智地使用这个。
注意选项“include”不会被命令“CONFIG REWRITE”重写
从admin或Redis哨兵。因为Redis总是使用最后处理的
line作为配置指令的值,你最好放包含
在这个文件的开头,以避免在运行时覆盖配置更改。
如果你有兴趣使用include覆盖配置
options,最好使用include作为最后一行。
include /path/to/local.conf
include /path/to/other.conf

8.2网络 NETWORK

在这里插入图片描述
bind 0.0.0.0 对所有人开放 可以指定单个或多个ip
指定多个ip 访问 ip 用空格 隔开
在这里插入图片描述
protected-mode yes 开启受保护模式

prot 6379 默认端口号

8.3通用 GENERAL

daemonize yes 以守护进程的方式运行,默认是 no 我们需要自己设置为yes

pidfile /www/server/redis/redis.pid 如果是守护进程方式运行,我们需要指定一个pid文件

# Specify the server verbosity level.
# This can be one of:
# debug (a lot of information, useful for development/testing)
# verbose (many rarely useful info, but not a mess like the debug level)
# notice (moderately verbose, what you want in production probably)
# warning (only very important / critical messages are logged)
loglevel notice
#指定服务器详细级别。
#这个可以是:
# debug(大量信息,对开发/测试有用)
# verbose(很多很少有用的信息,但不像调试级别那样混乱)
# notice(有点冗长,可能是在生产中需要的内容)
# warning(只记录非常重要/关键的消息)

logfile "/www/server/redis/redis.log" 日志的文件位置

# Set the number of databases. The default database is DB 0, you can select
# a different one on a per-connection basis using SELECT <dbid> where
# dbid is a number between 0 and 'databases'-1
databases 16
#设置数据库个数。默认数据库为“DB 0”,可选择
#在每个连接上使用SELECT where
# dbid是一个介于0和'databases'-1之间的数字

databases 默认的数据库数量 16 个

# By default Redis shows an ASCII art logo only when started to log to the
# standard output and if the standard output is a TTY. Basically this means
# that normally a logo is displayed only in interactive sessions.
#
# However it is possible to force the pre-4.0 behavior and always show a
# ASCII art logo in startup logs by setting the following option to yes.
always-show-logo yes

always-show-logo yes 是否显示log 默认为开启

8.4快照 SNAPSHOTTING

在这里插入图片描述
持久化数据 因为 Redis是内存数据库 如果断电等因素 会失去数据 所以我们需要在一定时间里 持久化数据

// 在 900s 内 有 1个key进行了操作 那么将会持久化一下
save 900 1
// 在 300s 内 有 10个key进行了操作 那么将会持久化一下
save 300 10
// 在 60s 内 有 1w个key进行了操作 那么将会持久化一下
save 60 10000

在这里插入图片描述
stop-writes-on-bgsave-error yes 持久化 出错了是否继续工作 默认继续

# Compress string objects using LZF when dump .rdb databases?
# For default that's set to 'yes' as it's almost always a win.
# If you want to save some CPU in the saving child set it to 'no' but
# the dataset will likely be bigger if you have compressible values or keys.
rdbcompression yes

rdbcompression yes 是否压缩 rdb文件
默认压缩 压缩会消耗cpu资源

# Since version 5 of RDB a CRC64 checksum is placed at the end of the file.
# This makes the format more resistant to corruption but there is a performance
# hit to pay (around 10%) when saving and loading RDB files, so you can disable it
# for maximum performances.
#
# RDB files created with checksum disabled have a checksum of zero that will
# tell the loading code to skip the check.
rdbchecksum yes

rdbchecksum yes 保存 rdb 文件时进行错误的校验

# The working directory.
#
# The DB will be written inside this directory, with the filename specified
# above using the 'dbfilename' configuration directive.
#
# The Append Only File will also be created inside this directory.
#
# Note that you must specify a directory here, not a file name.
dir /www/server/redis/

rdb 文件保存的目录

复制 REPLICATION

8.5安全 SECURITY

# Require clients to issue AUTH <PASSWORD> before processing any other
# commands.  This might be useful in environments in which you do not trust
# others with access to the host running redis-server.
#
# This should stay commented out for backward compatibility and because most
# people do not need auth (e.g. they run their own servers).
#
# Warning: since Redis is pretty fast an outside user can try up to
# 150k passwords per second against a good box. This means that you should
# use a very strong password otherwise it will be very easy to break.
#
# requirepass foobared

requirepass xxxxx 设置redis 登录密码

#要求客户端在处理任何其他密码之前发出AUTH
#命令。这在您不信任的环境中可能很有用
#其他可以访问运行redis-server的主机。
#这个应该被注释掉,以便向后兼容,因为大多数
#人们不需要认证(例如,他们运行自己的服务器)
#警告:由于Redis是相当快的外部用户可以尝试
# 150k密码每秒对一个好的盒子。这意味着你应该这么做
#使用一个非常强的密码,否则它会很容易被破解

8.6限制 CLIENTS

maxclients 10000 默认有 1w 个用户可以同时连接redis 服务器

maxmemory <bytes> redis 配置最大的内存容量

maxmemory-policy noeviction 内存到达上限的处理策略 6种

  • volatile-lru:只对设置了过期时间的key进行LRU(默认值)
  • allkeys-lru : 删除lru算法的key
  • volatile-random:随机删除即将过期key
  • allkeys-random:随机删除
  • volatile-ttl : 删除即将过期的
  • noeviction : 永不过期,返回错误

aof配置 APPEND ONLY MODE

基本配置
appendonly no 默认不开启 默认使用rdb持久化方式

appendfilename "appendonly.aof" 持久化文件的名字

# appendfsync always    // 每修改一个key都会执行 sync,消耗性能
appendfsync everysec    // 每一秒执行一次 sync,可能会丢失这1s的数据
# appendfsync no        // 不执行 sync,这个时候操作系统会自己同步数据速度是最快的

9.Redis持久化

因为Redis是内存数据库,如果不把数据保存到磁盘中,那么如果机器出现断电等,数据就会丢失,

所以Redis提供了持久化功能

RDB

RDB (Redis DataBase)

什么是RDB
在这里插入图片描述
就是在指定时间里把内存的数据存储到磁盘中

Rdb 默认保存的文件叫做 dump.rdb
在这里插入图片描述
触发机制
在这里插入图片描述

  • save 的规则满足的情况下,会自动触发rdb规则
  • 执行flushdb 命令,也会触发rdb文件规则
  • 退出Redis ,也会产生rdb文件

备份就会生成一个 dump.rdb文件
如何恢复rdb文件

  • 只需要将rdb文件放到Redis启动目录下就可以,Redis启动的时候自动检查dump.rdb回复其数据
  • 可以用 config get dir 查询我们需要将文件放在那个目录下

优点:
适合大规模数据恢复
对数据的完成性数据不高的可以使用

缺点
需要一定的时间间隔进行操作,如果在最后一次操作的时候宕机了,那么最后修改的数据就没有了。
fork一条进程的时候会占用一定的内存控件

AOF

AOF(Append Only File)

Aof是什么
将我们的所有命令记录下来,恢复的时候就把这个文件全部在执行一遍
在这里插入图片描述
以日志的形式记录每一个写的操作,将Redis执行过程的所有命令指令记录下来(读操作不记录),只许追加文件但不可以改写文件,Redis启动之初会读取文件重新构建数据。
aof保存的文件是appendonly.aof
在这里插入图片描述
默认是没有开启的 我们需要的话需要手动开启 把 appendonly no 改为 appendonly yes

如果Aof文件受损了Redis启动不起来 我们可以通过 redis-check-aof --fix 来修复aof文件
在这里插入图片描述
优点

  • 每一次修改都同步,文件的完整性会更加好
  • 每秒同步一次,可能会丢失一秒的数据
  • 从来不同步,效率最高

缺点

  • 相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢
  • aof运行效率也比rdb慢,所以Redis默认的配置就是rdb持久化

10.Redis发布与订阅

Redis发布订阅(pub/sub)是一种消息通信模式:发送者发送消息,订阅者接受消息———微信,微博的关注系统
Redis客户端可以订阅任意数量的频道
订阅/发布消息图

  • 消息发布者
  • 频道
  • 消息订阅者

在这里插入图片描述
下图是频道 channel1 , 以及订阅这个频道的三个客户端 ——- cilent2,cilent5 和 cilent1 之间的关系
在这里插入图片描述
当有消息通过Publish 命令发送给频道 channel1 时,这个消息就会被它发送给订阅它的三个客户端
在这里插入图片描述

命令

redis发布订阅常用命令:

序号 命令及描述
1 PSUBSCRIBE pattern [pattern …] 订阅一个或多个符合给定模式的频道。
2 PUBSUB subcommand [argument [argument …]] 查看订阅与发布系统状态。
3 PUBLISH channel message 将信息发送到指定的频道。
4 PUNSUBSCRIBE [pattern [pattern …]] 退订所有给定模式的频道。
5 SUBSCRIBE channel channel …] 订阅给定的一个或多个频道的信息。
6 UNSUBSCRIBE [channel [channel …]] 指退订给定的频道。

订阅消息:

127.0.0.1:6379> subscribe king     // 订阅一个频道
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "king"
3) (integer) 1
    // 等待推送的信息
1) "message"   // 消息
2) "king"      // 来自于那个频道
3) "hello,yss"  // 来自哪个频道的内容
1) "message"
2) "king"
3) "\xe6\x88\x91\xe7\x88\xb1\xe4\xbd\xa0"

推送信息:

127.0.0.1:6379> publish king "hello,yss"  // 发布信息到指定的频道
(integer) 1
127.0.0.1:6379> publish king "我爱你"
(integer) 1

11.Redis主从复制

概念

一般来说,要将Redis用于工程项目中,只是用一台Redis是玩玩不能的,原因如下:
1.从结构上,单个Redis服务器会发生单点故障,并且一台服务器需要处理的请求负载压力较大
2.从容量上,单个Redis服务器内存容量有限就算一台Redis服务器内存容量为256.也不能将所有的内存用作Redis,储存内存一般来说,单台Redis最大使用内存不应该超过20G

电商网站上的商品,一般都是一次上传,无数次浏览的,说专业点也就是“多读少写”。对于这种场景,我们可以使如下这种架构主从复制,指将一台Redis的数据,复制他的Redis’服务,前者称为主节点master/leade,后者称为从节点slave/follower;数据的复制时单向的,只能由主节点到从节点。master以写为主,slave以读为主。

认情况下,每台Redis服务器都是主节点:且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点
主从复制的作用主要包括:

  • 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式
  • 故障恢复:放主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余
  • 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其时在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量
  • 高可用(集群)基石:除了上述作用以为,主从复制还是哨兵和集群能够实施的基础,因此说主从复制时Redis高可用的基础

环境配置

只配置从库,不配置主库

查看当前库的信息

127.0.0.1:6379> info replication
# Replication
role:master   // 角色
connected_slaves:0  // 连接的丛机 
master_failover_state:no-failover
master_replid:c52bb664e09e9e76e9c995fdd15215578e38250f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

在这里插入图片描述
复制3个Redis.conf

然后修改配置文件:

  • 端口号
  • .pid 名字
  • log 文件名字
  • dump.rdb 名字

配置成功
启动3个redis
在这里插入图片描述

一主二从

默认情况Redis每一个服务都是主节点

一般只配置从机

一主 (6310)二从 (6320,6330)

查看Redis当前库信息

6310的信息

在这里插入图片描述
6320的信息
在这里插入图片描述
6330的信息
在这里插入图片描述
配置
命令

slaveof 127.0.0.1 6310

63206310 是老大

6320的信息
在这里插入图片描述
同样给 6330 配置一下

6310的信息

127.0.0.1:6310> info replication
# Replication
role:master     // 主机标识
connected_slaves:1   // 他有一个从机
slave0:ip=127.0.0.1  // 从机地址
,port=6320  // 从机端口
,state=online // 从机状态 
,offset=252,lag=1
master_failover_state:no-failover
master_replid:1c382c2d63dcacaabab6ce01942c24c1b1d3fbb1
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:252
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:252

2个都配置完成
在这里插入图片描述

细节

主机可以写,从机不可以写只能读!主机中的所有数据都会被从机保存
主机可以读写:

在这里插入图片描述
从机只能读不能写不然会报错:
在这里插入图片描述
测试
1.主机宕机了 从机的状态

127.0.0.1:6310> SHUTDOWN
not connected> exit
[root@King bin]# redis-cli -p 6310
Could not connect to Redis at 127.0.0.1:6310: Connection refused
not connected> ping
Could not connect to Redis at 127.0.0.1:6310: Connection refused

主机关闭
在这里插入图片描述
在这里插入图片描述
主机宕机不会影响从机的读取操作
2、主机重新工作

[root@King bin]# redis-server KingConfig/redis-10.conf
[root@King bin]# redis-cli -p 6310
127.0.0.1:6310> ping
PONG
127.0.0.1:6310> set k2 v2
OK
127.0.0.1:6310> get k2
"v2"

从机状态
在这里插入图片描述
也可以查询值

127.0.0.1:6320> get k2
"v2"

测试从机断开 :如果从机是使用命令连接的主机 那么从机断开之后 重新连接 他就会变为自己的主机,这样是取不到主机更新数据,但是可以取到以前的数据,我们重新让它成为从机 那么他还是可以读取到数据

主从复制原理

Slave启动成功连接到 master 后会发送一个sync命令

Master接到命令,启动后台的存盘进程,同时收集所有接收到的用于修改数据集命令,在后台进程执行完毕之后, master将传送整个数据文件到 slave,井完成一次完全同步

全量复制:而 slave服务在接收到数据库文件数据后,将其存盘井加载到内存中

增量复制:Master继续将新的所有收集到的修改命令依次传给 slave,完成同步

但是只要是重新连接 master,一次完全同步(全量复制)将被自动执行

主机宕机

如果主机宕机了,从机想要变成主机 我们可以通过命令 slaveof no noe 让自己变成主机!其他节点就可以手动连接,这个时候主机连接了 还想要 这个主机当老大 那么我们需要手动配置

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/111676.html

(0)

相关推荐

半码博客——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!