Redis 总结
1.Nosql
1.1Nosql概述
为什么要用Nosql
- 单机mysql的年代
app———>dal————>mysql - Memcached(缓存)+mysql+垂直拆分(读写分离)
优化数据结构和索引–>文件缓存(IO)–>Memcached - 分库分表+水平拆分+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下载
下载完成解压
启动Redis服务器:
双击运行服务 redis-server.exe
运行成功
再次运行redis客户端 启动 redis-cli.exe
127.0.0.1:6379> ping ----> 测试是否连接成功
PONG
127.0.0.1:6379> set name liyang -----> 设置 key value
OK
127.0.0.1:6379> get name ------> 用 key 去寻找 value
"liyang"
Linux安装
官网下载:地址下载地址
下载完成之后导入到 Liunx 的 opt 目录下面
执行 tar -zxvf redis...
进行解压
解压完成只要需要安装c++ 环境 yum -y install gcc-c++
安装完成执行 make
执行完成之后在执行一遍
然后执行 make install
redis 的默认路径在 usr/local/bin
目录下面
移动 redis.config 到 本目录下
redis默认不是后台启动,我们需要修改配置文件
找到这个修改为 yes
启动redis 服务
测试连接
查看redis服务信息
关闭redis
127.0.0.1:6379> 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 ------ > 删除 2个 9889
(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
- “k”
- “y”
127.0.0.1:6379> hvals map - “changan”
- “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的事务:
- 开启事务 (multi)
- 命令入队 ( )
- 执行命令 (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单位
这里包括一个或多个其他配置文件。这很有用,如果你
有一个标准的模板,去所有的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)
- 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
然后修改配置文件:
- 端口号
- .pid 名字
- log 文件名字
- dump.rdb 名字
一主二从
默认情况Redis每一个服务都是主节点
一般只配置从机
一主 (6310)二从 (6320,6330)
查看Redis当前库信息
6310
的信息
slaveof 127.0.0.1 6310
给 6320
认 6310
是老大
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
细节
主机可以写,从机不可以写只能读!主机中的所有数据都会被从机保存
主机可以读写:
从机只能读不能写不然会报错:
测试
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
[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 no
e 让自己变成主机!其他节点就可以手动连接,这个时候主机连接了 还想要 这个主机当老大 那么我们需要手动配置
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/111676.html