redis
一、redis的作用和使用场景
redis是一个内存级的高速缓存数据库。(对比磁盘IO)
使用场景:1、并发访问量大的 2、数据量小 3、修改不频繁
项目中:1、验证码 2、登录成功用户信息 3、首页(模块数据 轮播图,商品分类,热点模块,推荐模块) 4、购物车(商品信息)
二、redis支持的数据类型有哪些?
目前支持10种,常用的有5种:String、list、set、zset、hash(map)、stream
三、redis的常用命令
通用命令
每种数据类型各自的命令
string类型
设置过期时间1、set k1 v1 ex 1002、setex k1 100 v23、set k1 v1 expire k1 100
list类型 (有序,可以重复)
1.94.230.82:6381> lpush addressList hangzhou zhengzhou guangzhou
(integer) 3
1.94.230.82:6381> llen addressList
(integer) 3
1.94.230.82:6381> lrange addressList 0 -1
1) "guangzhou"
2) "zhengzhou"
3) "hangzhou"
set类型(无序、不可重复)
1.94.230.82:6381> sadd subjects java c java
(integer) 2
1.94.230.82:6381> sadd subjects c
(integer) 0
1.94.230.82:6381> sadd subjects mysql
(integer) 1
1.94.230.82:6381> smembers subjects
1) "mysql"
2) "java"
3) "c"
1.94.230.82:6381> sadd subjects py
(integer) 1
1.94.230.82:6381> smembers subjects
1) "mysql"
2) "java"
3) "py"
4) "c"
hash类型(map类型 : 存储map名 key value 存储对象:对象名 属性名 属性值)
1.94.230.82:6381> hset user id 111
(integer) 1
1.94.230.82:6381> hset user name zhangsan
(integer) 1
1.94.230.82:6381> hset user age 20
(integer) 1
1.94.230.82:6381> hset user age 22
(integer) 0
1.94.230.82:6381> hget user id
"111"
1.94.230.82:6381> hget user name
"zhangsan"
1.94.230.82:6381> hget user age
"22"
1.94.230.82:6381> hdel user name
(integer) 1
1.94.230.82:6381> hkeys user
1) "id"
2) "age"
1.94.230.82:6381> hvals user
1) "111"
2) "22"
zset 有序的set集合 有序,不能重复 (给每一个value值,添加一个数值,通过数值保持有序)
1.94.230.82:6381> zadd sbs 1 java 2 c 3 py
(integer) 3
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
1.94.230.82:6381> zadd sbs 10 html
(integer) 1
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
4) "html"
1.94.230.82:6381> zadd sbs 5 c#
(integer) 1
1.94.230.82:6381> zrange sbs 0 -1
1) "java"
2) "c"
3) "py"
4) "c#"
5) "html"
四、redis的持久化机制
rdb:默认 快照模式
定时同步(1min 10000、5min 10、15min 1)
可能造成最后一次同步之后的数据丢失
性能高(新建一个进程 执行数据同步操作,不影响主进程)
dump.rdb 本地磁盘文件(实时数据)
恢复速度快
aof:日志追加模式 日志文件大
rdb文件 全量
追加命令 到 aof日志文件
恢复慢 rdb+aof 逐个命令执行,恢复
更安全,丢失的数据更少
同步机制(no(30s) always everySec)
五、数据的删除策略
定时删除 定时器删除(根据设置的过期时间)
定期删除 根据配置文件参数hz值,60/hz 循环检测各个仓库删除(抽取w个值进行检测,根据过期key的百分比 25% 循环删除)
惰性删除 过期后不立即删除。(使用时判断,过期删除)
六、数据的淘汰策略
volatile- lru lfu ttl random
allkeys- lru lfu random
no 放弃驱逐
七、事务机制
multi exec discard watch unwatch
事务的特点:
是否满足原子性: 不满足
八、锁机制
乐观锁: watch unwatch
悲观锁:setnx 分布式锁 setnx(key,value) 1 执行代码 ---- del key
九、发布订阅机制
publish 频道 message
subscribe 频道
十、一主二从(高可用)
实现读写分离、主从复制、主机执行读写,从机执行读取。
主从切换
手动切换: slaveof no one slaveof ip port
自动切换: 哨兵模式
哨兵
哨兵的作用是监控 redis系统的运行状况,他的功能如下:
监控主从数据库是否正常运行
master出现故障时,自动将slave转化为master
多哨兵配置的时候,哨兵之间也会自动监控
多个哨兵可以监控同一个redis
哨兵工作机制
./redis-sentinel sentinel.conf
哨兵进程启动时会读取配置文件的内容,通过sentinel monitor master-name ip port quorum查找到master的ip端口。一个哨兵可以监控多个master数据库,只需要提供多个该配置项即可。
配置文件还定义了与监控相关的参数,比如master多长时间无响应即即判定位为下线。
哨兵启动后,会与要监控的master建立俩条连接:
一条连接用来订阅master的sentinel:hello频道与获取其他监控该master的哨兵节点信息
另一条连接定期向master发送INFO等命令获取master本身的信息
与master建立连接后,哨兵会执行三个操作,这三个操作的发送频率都可以在配置文件中配置:
定期向master和slave发送INFO命令
定期向master和slave的sentinel:hello频道发送自己的信息
定期向master、slave和其他哨兵发送PING命令
这三个操作的意义非常重大,发送INFO命令可以获取当前数据库的相关信息从而实现新节点的自动发现。所以说哨兵只需要配置master数据库信息就可以自动发现其slave信息。获取到slave信息后,哨兵也会与slave建立俩条连接执行监控。通过INFO命令,哨兵可以获取主从数据库的最新信息,并进行相应的操作,比如角色变更等。
接下来哨兵向主从数据库的sentinel:hello频道发送信息与同样监控这些数据库的哨兵共享自己的信息,发送内容为哨兵的ip端口、运行id、配置版本、master名字、master的ip端口还有master的配置版本。这些信息有以下用处:
其他哨兵可以通过该信息判断发送者是否是新发现的哨兵,如果是的话会创建一个到该哨兵的连接用于发送PING命令。
其他哨兵通过该信息可以判断master的版本,如果该版本高于直接记录的版本,将会更新
当实现了自动发现slave和其他哨兵节点后,哨兵就可以通过定期发送PING命令定时监控这些数据库和节点有没有停止服务。发送频率可以配置,但是最长间隔时间为1s,可以通过sentinel down-after-milliseconds mymaster 600设置。
如果被ping的数据库或者节点超时未回复,哨兵认为其主观下线。如果下线的是master,哨兵会向其他哨兵点发送命令询问他们是否也认为该master主观下线,如果达到一定数目(即配置文件中的quorum)投票,哨兵会认为该master已经客观下线,并选举领头的哨兵节点对主从系统发起故障恢复。
如上文所说,哨兵认为master客观下线后,故障恢复的操作需要由选举的领头哨兵执行,选举采用Raft算法:
发现master下线的哨兵节点(我们称他为A)向每个哨兵发送命令,要求对方选自己为领头哨兵
如果目标哨兵节点没有选过其他人,则会同意选举A为领头哨兵
如果有超过一半的哨兵同意选举A为领头,则A当选
如果有多个哨兵节点同时参选领头,此时有可能存在一轮投票无竞选者胜出,此时每个参选的节点等待一个随机时间后再次发起参选请求,进行下一轮投票精选,直至选举出领头哨兵
选出领头哨兵后,领头者开始对进行故障恢复,从出现故障的master的从数据库中挑选一个来当选新的master,选择规则如下:
所有在线的slave中选择优先级最高的,优先级可以通过slave-priority配置
如果有多个最高优先级的slave,则选取复制偏移量最大(即复制越完整)的当选
如果以上条件都一样,选取id最小的slave
挑选出需要继任的slave后,领头哨兵向该数据库发送命令使其升格为master,然后再向其他slave发送命令接受新的master,最后更新数据。将已经停止的旧的master更新为新的master的从数据库,使其恢复服务后以slave的身份继续运行。
十一、集群模式(高可用)
3主6从
创建redis目录和配置文件 由于这里需要配置6个redis实例的配置文件,所以在这里,可以先创建一个模板配置文件,之后使用代码批量替换的方式来创建每个redis的配置文件。
创建模板文件
创建目录
mkdir -p /data/docker_redis/
编写redis_cluster.conf.template文件
vi redis_cluster.conf.template
port ${PORT}
requirepass 1234
masterauth 1234
protected-mode no
daemonize no
appendonly yes
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
cluster-announce-ip 82.157.9.251
cluster-announce-port ${PORT}
cluster-announce-bus-port 1${PORT}
在这里需要讲解2个参数 cluster-announce-port:此端口为redis提供服务端口,用于应用客户端连接 cluster-announce-bus-port:此端口用于redis集群进行故障检测、配置更新、故障转移授权和内部通讯使用,不用于应用客户端连接使用。
创建6个redis实例的数据目录,配置文件目录和配置文件
for port in `seq 8001 8006`; do \mkdir -p /data/redis_data/${port}/conf \&& PORT=${port} envsubst < /data/docker_redis/redis_cluster.conf.template > /data/redis_data/${port}/conf/redis.conf \&& mkdir -p /data/redis_data/${port}/data;\
done
批量创建容器 在这里使用for循环批量创建redis容器,代码如下所示
for port in $(seq 8001 8006); do \docker run -id -p ${port}:${port} -p 1${port}:1${port} --restart always --name redis-${port} \-v /data/redis_data/${port}/conf/redis.conf:/usr/local/etc/redis/redis.conf \-v /data/redis_data/${port}/data:/data \redis:7.0.2 redis-server /usr/local/etc/redis/redis.conf; \
done
开放防火墙端口:(云服务器端口也要开放)
sudo firewall-cmd --permanent --add-port=8001-8006/tcp
sudo firewall-cmd --permanent --add-port=18001-18006/tcp
启动容器:
for port in $(seq 8001 8006); do \docker start redis-${port} ;\
done
在这里使用-v参数,让容器的redis配置参数和数据全部使用宿主机的文件目录。这样做的好处是,保证redis的数据不丢失。
查看刚刚创建的redis容器
[root@mysql data]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f4c971ce2d84 redis:7.0.2-buster "docker-entrypoint.s鈥 6 seconds ago Up 5 seconds 0.0.0.0:8006->8006/tcp, 6379/tcp, 0.0.0.0:18006->18006/tcp redis-8006
1b5a8b0a1c93 redis:7.0.2-buster "docker-entrypoint.s鈥 7 seconds ago Up 6 seconds 0.0.0.0:8005->8005/tcp, 6379/tcp, 0.0.0.0:18005->18005/tcp redis-8005
35d8fe01fc71 redis:7.0.2-buster "docker-entrypoint.s鈥 7 seconds ago Up 6 seconds 0.0.0.0:8004->8004/tcp, 6379/tcp, 0.0.0.0:18004->18004/tcp redis-8004
408e5302378a redis:7.0.2-buster "docker-entrypoint.s鈥 8 seconds ago Up 7 seconds 0.0.0.0:8003->8003/tcp, 6379/tcp, 0.0.0.0:18003->18003/tcp redis-8003
c1c23c543233 redis:7.0.2-buster "docker-entrypoint.s鈥 8 seconds ago Up 7 seconds 0.0.0.0:8002->8002/tcp, 6379/tcp, 0.0.0.0:18002->18002/tcp redis-8002
c752fab6c6b8 redis:7.0.2-buster "docker-entrypoint.s鈥 9 seconds ago Up 8 seconds 0.0.0.0:8001->8001/tcp, 6379/tcp, 0.0.0.0:18001->18001/tcp redis-8001
创建redis-cluster集群 6个redis容器创建好之后,选择其中的一个容器进入,进行redis-cluster集群创建
[root@mysql bin]# docker exec -it redis-8001 /bin/bash
root@f4c971ce2d84:~# redis-cli -a 1234 --cluster create 82.157.9.251:8001 82.157.9.251:8002 82.157.9.251:8003 82.157.9.251:8004 82.157.9.251:8005 82.157.9.251:8006 --cluster-replicas 1
回车后显示:
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 82.157.9.251:8005 to 82.157.9.251:8001
Adding replica 82.157.9.251:8006 to 82.157.9.251:8002
Adding replica 82.157.9.251:8004 to 82.157.9.251:8003
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004replicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005replicates 0956927ee74737d5ff91a1885e77f94d531dab76
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006replicates d6321788b2717b4142390c158ba70ca758f70964
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 82.157.9.251:8001)
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master1 additional replica(s)
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004slots: (0 slots) slavereplicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006slots: (0 slots) slavereplicates d6321788b2717b4142390c158ba70ca758f70964
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005slots: (0 slots) slavereplicates 0956927ee74737d5ff91a1885e77f94d531dab76
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
上述命令执行之后,redis-cluster集群就搭建好了
在主机上测试:
模仿某一节点故障:
在cmd窗口:
重启:docker start redis-8001
下面是整个redis-cluster集群的架构图
redis-cluster集群状态检查 检查redis-cluster集群状态
root@f4c971ce2d84:~# redis-cli -a 1234 --cluster check 1.94.230.82:8001
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8001 (c9e549f4...) -> 0 keys | 5461 slots | 1 slaves.
82.157.9.251:8002 (0956927e...) -> 0 keys | 5462 slots | 1 slaves.
82.157.9.251:8003 (d6321788...) -> 0 keys | 5461 slots | 1 slaves.
[OK] 0 keys in 3 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 82.157.9.251:8001)
M: c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001slots:[0-5460] (5461 slots) master1 additional replica(s)
M: 0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002slots:[5461-10922] (5462 slots) master1 additional replica(s)
S: 96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004slots: (0 slots) slavereplicates c9e549f4d04d4466d2550d1e027412304099b1f2
S: aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006slots: (0 slots) slavereplicates d6321788b2717b4142390c158ba70ca758f70964
S: 8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005slots: (0 slots) slavereplicates 0956927ee74737d5ff91a1885e77f94d531dab76
M: d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003slots:[10923-16383] (5461 slots) master1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
检查redis集群节点信息
root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8001
82.157.9.251:8001> cluster nodes
0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002@18002 master - 0 1603265855374 2 connected 5461-10922
96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004@18004 slave c9e549f4d04d4466d2550d1e027412304099b1f2 0 1603265856080 4 connected
aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006@18006 slave d6321788b2717b4142390c158ba70ca758f70964 0 1603265855575 6 connected
8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005@18005 slave 0956927ee74737d5ff91a1885e77f94d531dab76 0 1603265855575 5 connected
d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003@18003 master - 0 1603265856382 3 connected 10923-16383
c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001@18001 myself,master - 0 1603265855000 1 connected 0-5460
在这里可以很清晰明了的看到有3个master节点和3个slave节点的IP地址和端口信息。
redis-cluster连接测试
redis-cluster搭建好之后,随意连接一个redis节点,无论是主节点还是从节点都可以,在这里选择连接一个从节点。
82.157.9.251:8001> cluster nodes
0956927ee74737d5ff91a1885e77f94d531dab76 82.157.9.251:8002@18002 master - 0 1603265855374 2 connected 5461-10922
96d2cb55f163ecc13a714ba01d90348c1c3ad02f 82.157.9.251:8004@18004 slave c9e549f4d04d4466d2550d1e027412304099b1f2 0 1603265856080 4 connected
aa7c2f6173904973f041b35efc5200359188eb0f 82.157.9.251:8006@18006 slave d6321788b2717b4142390c158ba70ca758f70964 0 1603265855575 6 connected
8a771c26a95e82d9a6818e372d7c0226937670ac 82.157.9.251:8005@18005 slave 0956927ee74737d5ff91a1885e77f94d531dab76 0 1603265855575 5 connected
d6321788b2717b4142390c158ba70ca758f70964 82.157.9.251:8003@18003 master - 0 1603265856382 3 connected 10923-16383
c9e549f4d04d4466d2550d1e027412304099b1f2 82.157.9.251:8001@18001 myself,master - 0 1603265855000 1 connected 0-5460
root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8004
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8004>
82.157.9.251:8004> set 5 test5
-> Redirected to slot [9974] located at 82.157.9.251:8002
82.157.9.251:8002>
1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.
当在slave节点写入数据时,redis-cluster将你的写请求重定向到另一个master节点了.
root@f4c971ce2d84:~# redis-cli -c -a 1234 -h 82.157.9.251 -p 8006
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
82.157.9.251:8006>
82.157.9.251:8006> get 5
-> Redirected to slot [9974] located at 82.157.9.251:8002
"test5"
82.157.9.251:8002>
十二、重点题
redis和java结合
redis雪崩、穿透、击穿
1. redis缓存使用流程
使用Redis缓存数据的流程是:
-
数据查询首先进行缓存查询。
-
如果数据存在则直接返回缓存数据。
-
如果数据不存在,就对数据库进行查询,并把查询到的数据放进缓存。
-
如果数据库查询数据为空,则不放进缓存。
2. 缓存穿透
2.1. 概念
缓存穿透是指查询缓存和数据库中都不存在的数据。比如id为-1的数据。
2.2. 解决方案
-
缓存空值:当第一次请求时,数据不存在 Redis 也不存在数据库的时候,设置一个缺省值(比如:None)。当后续再次进行查询则直接返回空值或者缺省值。
//伪代码 public object GetProductListNew(String key) {//首先查询redis数据String value = redis.get(key);//如果redis中没有数据if(value == null){//查询数据库中的数据String dbValue = db.get();//如果数据库中的数据为null,则设置默认值if (dbValue == null) {dbValue = "none";}//将数据存储到redisredis.set(key,dbValue,50000);//返回return dbvalue;}}else{//第二次查询数据时,redis有数据,就直接返回return value;} }
-
布隆过滤器:在数据写入数据库的同时将这个 ID 同步到到布隆过滤器中,当请求的 id 不存在布隆过滤器中则说明该请求查询的数据一定没有在数据库中保存,就不要去数据库查询了。
<dependencies> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>23.0</version> </dependency> </dependencies>
//伪代码 public class BloomFilterTest {private static final int capacity = 1000000;private static final int key = 999998;private static BloomFilter<Integer> bloomFilter = BloomFilter.create(Funnels.integerFunnel(), capacity);static {for (int i = 0; i < capacity; i++) {bloomFilter.put(i);}}
public static void main(String[] args) {/*返回计算机最精确的时间,单位微妙*/long start = System.nanoTime();if (bloomFilter.mightContain(key)) {System.out.println("成功过滤到" + key);}long end = System.nanoTime();System.out.println("布隆过滤器消耗时间:" + (end - start));int sum = 0;for (int i = capacity + 20000; i < capacity + 30000; i++) {if (bloomFilter.mightContain(i)) {sum = sum + 1;}}System.out.println("错判率为:" + sum);} }
3. 缓存雪崩
3.1. 概念
是指在某一个时间段,redis服务器故障或者redis缓存的数据集中全部过期失效或者大量key过期失效,在缓存集中失效的这个时间段对数据的访问查询,都落到了数据库上,对于数据库而言,就会产生周期性的压力。
3.2. 解决方案
事前:
redis服务器设置高可用(一主二从或者集群3主3从)
-
随机设置key失效时间,避免大量key集体失效。
-
不设置过期时间(不推荐)。
-
用加锁或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写。
-
跑定时任务,在缓存失效前刷进新的缓存。
事中:
可以考略多种缓存机制,比如redis缓存+其他缓存机制 spring cache +mysql
事后:
redis崩溃、mysql崩溃,系统崩溃
解决方案:快速恢复系统(重启mysql、重启redis服务 快速恢复数据到内存中 rdb aof机制 、重启java服务)
4. 缓存击穿
4.1. 概念
指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。
4.2. 解决方案
-
预先把热门数据提前存入 Redis 中,并设热门数据的过期时间超大值。
-
使用分布式锁,当发现缓存失效的时候,不是立即从数据库加载数据。而是先获取分布式锁,获取锁成功才执行数据库查询和写数据到缓存的操作,获取锁失败,则说明当前有线程在执行数据库查询操作,当前线程睡眠一段时间在重试。这样只让一个请求去数据库读取数据。
//伪代码 public String get(key) {String value = redis.get(key);if (value == null) { //代表缓存值过期//设置3min的超时,防止del操作失败的时候,下次缓存过期一直不能load dbif (redis.setnx(key_mutex, 1, 3 * 60) == 1) { //代表设置成功value = db.get(key);redis.set(key, value, expire_secs);redis.del(key_mutex);} else { //这个时候代表同时候的其他线程已经load db并回设到缓存了,这时候重试获取缓存值即可sleep(50);get(key); //重试}} else {return value; }}
十三、springboot项目和redis的整合
1、spring-boot-starter-data-redis
2、配置redis的连接信息(host、port、password、database)
3、使用redisTemplate模版工具类
4、常见方法
redisTemplate.opsForValue.set(key,value);
redisTemplate.opsForValue.get(key)