本博客为尚硅谷课程笔记,课程来源:【尚硅谷】Redis 6 入门到精通 超详细 教程_哔哩哔哩_bilibili
本博客参考内容:
https://blog.csdn.net/weixin_47872288/article/details/118410080
https://zhangc233.github.io/2021/05/02/Redis/#HyperLogLog

Not Only SQL,非关系型数据库
NoSQL有什么用:
NoSQL数据库特点:
适用于:
不适用于场景:
NoSQL优点:
常见的NoSQL数据库

redis特性:
下载网址:Redis,只支持Linux版本,下载后在Ubuntu下解压,切入到对应文件夹下
首先需要gcc运行环境
sudo apt install gcc
gcc --version //查看gcc版本
安装Redis:
make
sudo make install
判断是否安装成功:

安装目录:/usr/local/bin
查看默认安装目录:
redis-benchmark:性能测试工具
redis-check-aof:修复有问题的 aof文件
redis-check-dump:修复有问题的dump.rdb文件
redis-sentinel:Redis集群使用
redis-server:Redis服务器启动命令
redis-cli:客户端,操作入口
(不推荐)
打开了就不问关闭该终端
cd /usr/local/bin
redis-server

把终端断掉了后台还在运行redis
cd redis-6.2.6 //切入Redis的文件夹
cp redis.conf etc/redis.conf //拷贝一份redis.conf
cd /etc/
gedit redis.conf
//查找daemo 修改后面的no->yes
redis-server /etc/redis.conf //后台启动redis服务器端

查看是否在运行:


退出方法:
exit或关闭后台redis-cli shutdown或关闭进程号 kill -9 进程号
总结:以后这样登录redis:/usr/local/bin/redis-cli

参考博客:
https://blog.csdn.net/Sophia_0331/article/details/107779165
https://blog.csdn.net/zdyueguanyun/article/details/83449912

解决方法:
config set stop-writes-on-bgsave-error no
登录redis:/usr/local/bin/redis-cli
Redis端口:6379
Redis默认0号数据库
Redis是单线程+多路IO复用

数据的操作:
set key valuekeys *exists key,存在返回1,否则返回0del keyunlink key ,选择非阻塞删除type keyexpire key time,time以秒为单位ttl key,-1表示永不过期,-2表示已过期zdb@zdb-virtual-machine:~$ /usr/local/bin/redis-cli
127.0.0.1:6379> keys *
(empty array)
//插入数据
127.0.0.1:6379> set k1 lucy
OK
127.0.0.1:6379> set k2 mary
OK
127.0.0.1:6379> set k3 jack
OK
//查询数据
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> exists k1
(integer) 1
127.0.0.1:6379> exists k4
(integer) 0
127.0.0.1:6379> type k1
string
//删除数据
127.0.0.1:6379> del k3
(integer) 1
127.0.0.1:6379> unlink k2
(integer) 1
//设置定时器
127.0.0.1:6379> expire k1 10
(integer) 1
127.0.0.1:6379> ttl k1
(integer) 4
127.0.0.1:6379> ttl k1
(integer) -2
库的操作:
选择库:select 库号,默认库为0号
查看当前数据库的key数量:dbsize
清空当前库:flushdb
清空所有库:flushall
127.0.0.1:6379> select 1
OK
127.0.0.1:6379[1]> select 0
OK
127.0.0.1:6379> dbsize
(integer) 0
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> flushdb
OK
关于string的介绍:
常用命令:
获取值:get key
在值尾部追加元素:append key add_value
获取值的长度:strlen key
当key不存在,才存入key-value对:setnx key value
value增1:incr key
value减1:decr key
value增一个常数:incrby key 步长
value减一个常数:decr key 步长
127.0.0.1:6379> set k1 v100
OK
127.0.0.1:6379> set k2 v200
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
127.0.0.1:6379> get k1
"v100"
127.0.0.1:6379> set k1 v1100
OK
127.0.0.1:6379> get k1
"v1100"
127.0.0.1:6379> append k1 bac
(integer) 8
127.0.0.1:6379> get k1
"v1100bac"
127.0.0.1:6379> strlen k1
(integer) 8
127.0.0.1:6379> setnx k1 v300
(integer) 0
127.0.0.1:6379> setnx k3 v300
(integer) 1
127.0.0.1:6379> set k4 500
OK
127.0.0.1:6379> incr k4
(integer) 501
127.0.0.1:6379> get k4
"501"
127.0.0.1:6379> decr k4
(integer) 500
127.0.0.1:6379> incrby k4 10
(integer) 510
127.0.0.1:6379> decrby k4 20
(integer) 490
Redis的incr是原子性操作,java中不是原子性操作

其他命令:
mset k1 v1 k2 v2...mget k1 k2 ...msetnx k1 v1 k2 v2 k3 v3:原子操作,要么全部成功,要么全部失败getrange key start_index end_index:get范围内的值,索引从0开始setrange key startindex val:将startindex位置上的值用val替代setex key time value:设置过期时间,同时设置值getset key value:返回旧值,同时设置新值127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3
OK
127.0.0.1:6379> keys *
1) "k3"
2) "k1"
3) "k2"
127.0.0.1:6379> mget k1 k2 k3
1) "v1"
2) "v2"
3) "v3"
//msetnx要么全部成功,要么全部失败
127.0.0.1:6379> msetnx k11 v11 k12 v12 k1 v11
(integer) 0
127.0.0.1:6379> msetnx k11 v11 k12 v12 k13 v13
(integer) 1
127.0.0.1:6379> keys *
1) "k1"
2) "k3"
3) "k12"
4) "k13"
5) "k2"
6) "k11"
127.0.0.1:6379> set name lucymary
OK
127.0.0.1:6379> getrange name 0 3
"lucy"
127.0.0.1:6379> setrange name 3 abc
(integer) 8
127.0.0.1:6379> get name
"lucabcry"
//设置定时器
127.0.0.1:6379> setex age 10 value30
OK
127.0.0.1:6379> ttl age
(integer) 4
127.0.0.1:6379> ttl age
(integer) -2
//给key设置新值
127.0.0.1:6379> getset name jack
"lucabcry"
127.0.0.1:6379> get name
"jack"
string的数据结构是简单的动态字符串

单键多值
多个value存储为list,底层为双向链表
常用命令:
lpush/rpush key value value...:从左或者右插入一个或者多个值(头插与尾插)
lpop/rpop key :从左或者右吐出一个或者多个值(值在键在,值都没,键都没)
rpoplpush key1 key2: 从key1列表右边吐出一个值,插入到key2的左边
lrange key start stop 按照索引下标获取元素(从左到右)
lrange key 0 -1: 获取所有值
lindex key index 按照索引下标获得元素
llen key 获取列表长度
linsert key before/after value newvalue 在value的前面插入一个新值
lrem key n value 从左边删除n个value值
lset key index value 在列表key中的下标index中修改值value
127.0.0.1:6379> lpush k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange k1 0 -1
1) "v3"
2) "v2"
3) "v1"
127.0.0.1:6379> rpush k2 v1 v2 v3
(integer) 3
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> lpop k1
"v3"
127.0.0.1:6379> lpush k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> rpush k2 v11 v12 v13
(integer) 3
127.0.0.1:6379> rpoplpush k1 k2
"v1"
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "v11"
3) "v12"
4) "v13"
//索引取值
127.0.0.1:6379> lindex k2
(error) ERR wrong number of arguments for 'lindex' command
127.0.0.1:6379> lindex k2 0
"v1"
127.0.0.1:6379> lindex k2 2
"v12"
//获取长度
127.0.0.1:6379> llen k2
(integer) 4
//指定位置插入值
127.0.0.1:6379> linsert k2 before "v11" "newv11"
(integer) 5
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "newv11"
3) "v11"
4) "v12"
5) "v13"
127.0.0.1:6379> linsert k2 before "v12" "newv11"
(integer) 6
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "newv11"
3) "v11"
4) "newv11"
5) "v12"
6) "v13"
127.0.0.1:6379> linsert k2 before "v13" "newv11"
(integer) 7
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "newv11"
3) "v11"
4) "newv11"
5) "v12"
6) "newv11"
7) "v13"
//删除指定值,且可以指定个数
127.0.0.1:6379> lrem k2 2 "newv11"
(integer) 2
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "v11"
3) "v12"
4) "newv11"
5) "v13"
//指定位置替换值
127.0.0.1:6379> lset k2 1 newnew
OK
127.0.0.1:6379> lrange k2 0 -1
1) "v1"
2) "newnew"
3) "v12"
4) "newv11"
5) "v13"

底层是字典,通过哈希表实现
自动排重且为无序的
常用命令:
sadd key value value... 将一个或者多个member元素加入集合key中,已经存在的member元素被忽略smembers key 取出该集合的所有值sismember key value 判断该集合key是否含有改值scard key 返回该集合的元素个数srem key value value 删除集合中的某个元素spop key 随机从集合中取出一个元素srandmember key n 随即从该集合中取出n个值,不会从集合中删除smove <一个集合a><一个集合b>value 将一个集合a的某个value移动到另一个集合bsinter key1 key2 返回两个集合的交集元素sunion key1 key2 返回两个集合的并集元素sdiff key1 key2 返回两个集合的差集元素(key1有的,key2没有)127.0.0.1:6379> sadd k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> smembers k1
1) "v2"
2) "v3"
3) "v1"
//判断set中是否有值
127.0.0.1:6379> sismember k1 v1
(integer) 1
127.0.0.1:6379> sismember k1 v4
(integer) 0
//返回集合中元素个数
127.0.0.1:6379> scard k1
(integer) 3
//删除元素
127.0.0.1:6379> srem k1 v1 v2
(integer) 2
127.0.0.1:6379> smembers k1
1) "v3"
127.0.0.1:6379> sadd k2 v1 v2 v3 v4
(integer) 4
//随机删除元素
127.0.0.1:6379> spop k2
"v1"
127.0.0.1:6379> spop k2
"v4"
127.0.0.1:6379> spop k2
"v3"
127.0.0.1:6379> flushdb
OK
127.0.0.1:6379> sadd k2 v1 v2 v3 v4
(integer) 4
127.0.0.1:6379> srandmember k2 2 //随机取值
1) "v2"
2) "v3"
127.0.0.1:6379> srandmember k2 2
1) "v1"
2) "v3"
127.0.0.1:6379> sadd k1 v1 v2 v3
(integer) 3
127.0.0.1:6379> sadd k2 v3 v4 v5
(integer) 3
//将k1中的v3移入到k2中
127.0.0.1:6379> smove k1 k2 v3
(integer) 1
127.0.0.1:6379> smembers k1
1) "v2"
2) "v1"
127.0.0.1:6379> smembers k2
1) "v5"
2) "v3"
3) "v4"
127.0.0.1:6379> sadd k3 v3 v4 v5 v7
(integer) 4
127.0.0.1:6379> sinter k2 k3 //交集
1) "v5"
2) "v3"
3) "v4"
127.0.0.1:6379> sunion k2 k3 //并集
1) "v7"
2) "v3"
3) "v4"
4) "v5"
127.0.0.1:6379> sdiff k3 k2 //差集
1) "v7"
hash是键值对集合,是一个string类型的field和value的映射表,hash特别适合用于存储对象。
常用命令:
hset key field value: 给key集合中的filed键赋值valuehget key1 field :集合field取出valuehmset key1 field1 value1 field2 value2 :批量设置hash的值hexists key1 field: 查看哈希表key中,给定域field是否存在hkeys key :列出该hash集合的所有fieldhvals key :列出该hash集合的所有valuehincrby key field increment: 为哈希表key中的域field的值加上增量1 -1hsetnx key field value :将哈希表key中的域field的值设置为value,当且仅当域field不存在
127.0.0.1:6379> hset user:1001 id 1 //插入数据:键 域 值
(integer) 1
127.0.0.1:6379> hset user:1001 name zhangsan
(integer) 1
127.0.0.1:6379> hget user:1001 id
"1"
127.0.0.1:6379> hget user:1001 name
"zhangsan"
//一次性插入
127.0.0.1:6379> hmset user:1002 id 2 name lisi age 30
OK
//判断是否存在域
127.0.0.1:6379> hexists user:1002 id
(integer) 1
127.0.0.1:6379> hexists user:1002 gender
(integer) 0
//获取所有域
127.0.0.1:6379> hkeys user:1002
1) "id"
2) "name"
3) "age"
//获取所有值
127.0.0.1:6379> hvals user:1002
1) "2"
2) "lisi"
3) "30"
127.0.0.1:6379> hincrby user:1002 age 2
(integer) 32
127.0.0.1:6379> hsetnx user:1002 age 40
(integer) 0
127.0.0.1:6379> hsetnx user:1002 gender 1
(integer) 1
hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。
有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合
常用命令:
zadd key score1 value1 score2 value2 :将一个或多个member元素及其score值加入到有序key中zrange key start stop (withscores) :返回有序集key,下标在start与stop之间的元素,带withscores,可以让分数一起和值返回到结果集。zrangebyscore key min max(withscores): 返回有序集key,所有score值介于min和max之间(包括等于min或max)的成员。有序集成员按score的值递增次序排列zrevrangebyscore key max min (withscores):同上,改为从大到小排列zincrby key increment value :为元素的score加上增量zrem key value :删除该集合下,指定值的元素zcount key min max :统计该集合,分数区间内的元素个数zrank key value :返回该值在集合中的排名,从0开始127.0.0.1:6379> zadd topn 200 java 300 c++ 400 mysql 500 php
(integer) 4
127.0.0.1:6379> zrange topn 0 -1
1) "java"
2) "c++"
3) "mysql"
4) "php"
127.0.0.1:6379> zrange topn 0 -1 withscores
1) "java"
2) "200"
3) "c++"
4) "300"
5) "mysql"
6) "400"
7) "php"
8) "500"
127.0.0.1:6379> zrangebyscore topn 300 500
1) "c++"
2) "mysql"
3) "php"
127.0.0.1:6379> zrangebyscore topn 300 500 withscores
1) "c++"
2) "300"
3) "mysql"
4) "400"
5) "php"
6) "500"
127.0.0.1:6379> zrevrangebyscore topn 500 300
1) "php"
2) "mysql"
3) "c++"
127.0.0.1:6379> zincrby topn 50 java
"250"
127.0.0.1:6379> zcount topn 200 300
(integer) 2
127.0.0.1:6379> zrank topn java
(integer) 0
127.0.0.1:6379> zrank topn mysql
(integer) 2
127.0.0.1:6379> zrange topn 0 -1 withscores
1) "java"
2) "250"
3) "c++"
4) "300"
5) "mysql"
6) "400"
7) "php"
8) "500"
zset底层使用了两个数据结构:
先打开配置文件:sudo gedit /etc/redis.conf

//1. 注释掉这一行
#bind 127.0.0.1 -::1
//2. 保护模式改成no
protected-mode no
//3. 后台启动改成yes
daemonize yes


添加密码:

什么是发布订阅:
发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。




127.0.0.1:6379> setbit users:20210101 1 1
(integer) 0
127.0.0.1:6379> setbit users:20210101 6 1
(integer) 0
127.0.0.1:6379> setbit users:20210101 11 1
(integer) 0
127.0.0.1:6379> setbit users:20210101 15 1
(integer) 0
127.0.0.1:6379> setbit users:20210101 19 1
(integer) 0
127.0.0.1:6379> getbit users:20210101 0
(integer) 0
127.0.0.1:6379> getbit users:20210101 1
(integer) 1
127.0.0.1:6379> bitcount users:20210101
(integer) 5
取交集(按位与):
2020-11-04日访问网站的userid=1,2,5,9
2020-11-03日访问网站的userid=0.1.4.9
127.0.0.1:6379> setbit unique:users:20201104 1 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 2 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 5 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201104 9 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 0 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 1 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 4 1
(integer) 0
127.0.0.1:6379> setbit unique:users:20201103 9 1
(integer) 0
127.0.0.1:6379> bitop and unqiue:users:and:20201104_03 setbit unique:users:20201103 setbit unique:users:20201104
(integer) 2
127.0.0.1:6379> pfadd program "java"
(integer) 1
127.0.0.1:6379> pfadd program "php"
(integer) 1
127.0.0.1:6379> pfadd program "java" //重复元素不添加
(integer) 0
127.0.0.1:6379> pfadd program "java" "c++" "mysql"
(integer) 1
127.0.0.1:6379> pfcount program
(integer) 4
127.0.0.1:6379> pfadd k1 "a" "b"
(integer) 1
127.0.0.1:6379> pfcount k1
(integer) 2
127.0.0.1:6379> pfadd k2 "1" "11" "111"
(integer) 1
127.0.0.1:6379> pfcount k2
(integer) 3
//合并
127.0.0.1:6379> pfmerge kres k1 k2
OK
127.0.0.1:6379> pfcount kres
(integer) 5
提供经纬度设置,查询范围,距离查询等
两极无法直接添加,有效的经度从-180到180度;有效的纬度从-85.05112878到85.05112878度
//插入数据
127.0.0.1:6379> geoadd china:city 141.47 31.23 shanghai
(integer) 1
127.0.0.1:6379> geoadd china:city 103.50 29.63 chongqing 114.05 22.52 shenzhen 116.38 39.90 beijing
(integer) 3
127.0.0.1:6379> geopos china:city shanghai
1) 1) "141.47000044584274292"
2) "31.22999903975783553"
//获取两城市之间的距离
127.0.0.1:6379> geodist china:city beijing shanghai km
"2455.6228"
127.0.0.1:6379> geodist china:city beijing chongqing km
"1636.7270"
//获取指定经纬度一定范围内的城市
127.0.0.1:6379> georadius china:city 110 30 1000 km
1) "chongqing"
2) "shenzhen"
Redis事务是一个单独的隔离操作,事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。
Redis事务的主要作用就是串联多个命令防止别的命令插队。
mUlti,exec,discard

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set key1 value1
QUEUED
127.0.0.1:6379(TX)> set key2 value2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set a1 v1
QUEUED
127.0.0.1:6379(TX)> set a2 v2
QUEUED
127.0.0.1:6379(TX)> discard
OK
情况一:组队的时候有一个命令出错,执行时整个的所有队列都会被取消

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set b1 v1
QUEUED
127.0.0.1:6379(TX)> set b2 v2
QUEUED
127.0.0.1:6379(TX)> set b3
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379(TX)> exec
(error) EXECABORT Transaction discarded because of previous errors.
情况二:组队的时候没有失败,执行的时候有一个命令失败,其他的命令都会执行,不会回滚。

127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> set c1 v1
QUEUED
127.0.0.1:6379(TX)> incr c1
QUEUED
127.0.0.1:6379(TX)> set c2 v2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) (error) ERR value is not an integer or out of range
3) OK

每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
抢票就是典型的乐观锁场景。


单独的隔离操作
没有隔离级别的概念
不保证原子性
Redis提供了2个不同形式的持久化方式
RDB:在指定的时间间隔内将内存中的数据集快照写入磁盘中,Snapshot快照,它恢复时是将快照文件直接读到内存里。
备份是如何执行的?
读时共享,写时复制。


AOF是什么?
Append Only File,以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录),只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis重启的话就根据日志文件将写指令从前到后执行一次以完成数据的恢复工作。
AOF默认不开启,RDB默认开启
appendonly no改为yes开启
如果同时开启AOF和RDB,系统默认取AOF的数据。
redis-check-aof --fix appendonly.aof可以修复aof文件
同步频率设置:
appendfsync always:始终同步,每次redis的写入都会立刻记入日志;性能较差但数据完整性比较好
annendfsync everysec:每秒同步,每秒写入日志一次,如果宕机,本秒的数据可能丢失。
appendfsync np:redis不主动进行同步,把同步时机交给操作系统
rewrite压缩
什么时候重写:
Redis会记录上次重写时的AOF大小,默认配置是当AOF文件大小是上次rewrite后大小的一倍且文件大于64M时触发
重写虽然可以节约大量磁盘空间,减少恢复时间。但是每次重写还是有一定的负担的,因此设定Redis要满足一定条件才会进行重写。
auto-aof-rewrite-percentage:设置重写的基准值,文件达到100%时开始重写(文件是原来重写后文件的2倍时触发)
auto-aof-rewrite-min-size:设置重写的基准值,最小文件64MB。达到这个值开始重写
AOF持久化流程:
客户端的请求写命令会被append追加到AOF缓冲区中
AOF缓冲区根据AOF持久化策略[always, everysec, no]将操作sync同步到磁盘的AOF文件中
AOF文件大小超过重写策略或手动重写时,会对AOF文件rewrite重写,压缩AOF文件容器
Redis服务重启时,会重新load加载AOF文件的写操作达到数据恢复的目的。
优点:
缺点:

哪个好?
官方推荐两个都启动。如果对数据不敏感,可以单独选RDB;不建议单独用AOF,因为可能会出现bug。如果只是做纯内存缓存,可以都不用。
一般是一主多从
是什么?
能干什么?

怎么搭建一主多从?
【尚硅谷】Redis 6 入门到精通 超详细 教程_哔哩哔哩_bilibili
info replication可以看信息
slaveof IP 端口9可以设置从服务器
redis-server redis.conf启动服务器端
redis-cli -p 端口 启动客户端
ps -ef | grep redis:查看redis进程

主机能读能写,从机只能读

从服务器挂掉后,重启变成了主服务器
该重新设置为从服务器,能看到挂掉那段时间主服务器添加的数据
主服务器挂掉后,从服务器还是从服务器,也知道主服务器挂掉了
主服务器重新启动后,还是主服务器,数据不丢失
当从服务器连接上主服务器之后,从服务器向主服务器发送进行数据同步的消息。
主服务器接到从服务器发送过来的同步消息,把主服务器数据进行持久化,rdb文件,把rdb文件发送给从服务器,从服务器拿到rdb进行读取。
每次主服务器进行写操作之后,和从服务器进行数据同步。(主服务器主动做的)
全量复制/增量复制

salveof no one将从机变为主机
非自动
反客为主的自动版

主要是为了监控主机宕机之后,从机可以立马变为主机,就和上面的反客为主一样,但不用手动设置。
能够后台监控主机是否故障,如果故障了根据投票数自动将从库转换为主库。
容量不够,redis如何进行扩容?
并发写操作,redis如何进行分摊?


什么是集群?
创建redis集群:【尚硅谷】Redis 6 入门到精通 超详细 教程_哔哩哔哩_bilibili



key对应的数据存在,但在redis中过期,此时若有大量并发请求过来,这些请求发现缓存过期一般都会从后端DB加载数据并回设到缓存,这个时候大并发的请求可能会瞬间把后端DB压垮
也就是一个key过期,一直访问数据库

解决方案:
key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题。
(1)预先设置热门数据:在redis高峰访问之前,把一些热门数据提前存入到redis里面,加大这些热门数据key的时长
(2)实时调整:现场监控哪些数据热门,实时调整key的过期时长
(3)使用锁:先判断值是否为空再让他进来与否
总结如下:

解决方案:
(1)构建多级缓存架构:nginx缓存 + redis缓存 +其他缓存(ehcache等)
(2)使用锁或队列:用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。不适用高并发情况
(3)设置过期标志更新缓存:记录缓存数据是否过期(设置提前量),如果过期会触发通知另外的线程在后台去更新实际key的缓存。
(4)将缓存失效时间分散开:比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。
总结如下:
由于分布式系统多线程、多进程并且分布在不同机器上,这将使原单机部署情况下的并发控制锁策略失效,单纯的Java API并不能提供分布式锁的能力。为了解决这个问题就需要一种跨JVM的互斥机制来控制共享资源的访问
也就是在这个机器上了锁,另外一个机器也要可以识别到这个锁,也就是共享锁,都是同一把锁
解决方案如下:
设置锁:setnx
释放锁:del
设置key的过期时间自动释放:exprie
zdb@zdb-virtual-machine:~$ redis-server /etc/redis.conf
zdb@zdb-virtual-machine:~$ /usr/local/bin/redis-cli
127.0.0.1:6379> setnx users 10
(integer) 1
127.0.0.1:6379> setnx users 20
(integer) 0
127.0.0.1:6379> del users
(integer) 1
127.0.0.1:6379> setnx users 10
(integer) 1
127.0.0.1:6379> expire users 10
(integer) 1
127.0.0.1:6379> ttl users
(integer) 4
127.0.0.1:6379> ttl users
(integer) -2
//即上锁又设置过期时间
127.0.0.1:6379> set users 10 nx ex 12
OK
127.0.0.1:6379> ttl users
(integer) 3
127.0.0.1:6379> ttl users
(integer) -2




权限控制
acl list命令展现用户权限列表acl cat,查看添加权限指令类别acl whoami命令查看当前用户acl set user命令创建和编辑用户ACL127.0.0.1:6379> acl list
1) "user default on nopass ~* &* +@all"
127.0.0.1:6379> acl cat
1) "keyspace"
2) "read"
3) "write"
4) "set"
5) "sortedset"
6) "list"
7) "hash"
8) "string"
9) "bitmap"
10) "hyperloglog"
11) "geo"
12) "stream"
13) "pubsub"
14) "admin"
15) "fast"
16) "slow"
17) "blocking"
18) "dangerous"
19) "connection"
20) "transaction"
21) "scripting"
127.0.0.1:6379> acl whoami
"default"
单线程+IO多路复用
redis是单线程

多线程IO默认是不开启的,需要在配置文件中设置
io-threads-do-reads yes
io-therads 4