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缓存数据的流程是:

  1. 数据查询首先进行缓存查询。

  2. 如果数据存在则直接返回缓存数据。

  3. 如果数据不存在,就对数据库进行查询,并把查询到的数据放进缓存。

  4. 如果数据库查询数据为空,则不放进缓存。

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)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/86018.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/86018.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/86018.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机网络学习笔记:TCP可靠传输实现、超时重传时间选择

文章目录 一、TCP可靠传输实现二、TCP超时重传时间选择 一、TCP可靠传输实现 TCP可靠传输的实现&#xff0c;主要基于发送方和接收方的滑动窗口&#xff0c;以及确认机制&#xff1a; 发送方在未收到确认&#xff08;ACK&#xff09;前&#xff0c;可以将序号落在发送窗口内的…

Perl 正则表达式

Perl 正则表达式 引言 Perl 正则表达式&#xff08;Regular Expressions&#xff09;是Perl编程语言中一个强大且灵活的工具&#xff0c;用于字符串处理和模式匹配。正则表达式在文本处理、数据验证、搜索和替换等任务中发挥着至关重要的作用。本文将深入探讨Perl正则表达式的…

Security: RSA: 1024 bit 长度已经变得不安全了

文章目录 参考推荐限制RHEL相关配置man crypto-policies包含的应用使用方法是配置文件include参考 https://csrc.nist.gov/pubs/sp/800/57/pt1/r2/final https://www.linuxquestions.org/questions/linux-security-4/1024-bit-dsa-vs-2048-bit-rsa-4175439131/ https://csrc.n…

第一课:大白话中的机器学习

各位看官好啊!今天咱们来聊一个听起来高大上但实际上特别接地气的玩意儿——机器学习。别被这名字吓到,它其实就是教电脑像人类一样学习知识的一套方法。想象一下你教你家狗子坐下、握手的过程,机器学习差不多就是这么回事,只不过"学生"换成了电脑。 一、啥是机…

实现 el-table 中键盘方向键导航功能vue2+vue3(类似 Excel)

实现 el-table 中键盘方向键导航功能vue2vue3&#xff08;类似 Excel&#xff09; 功能需求 在 Element UI 的 el-table 表格中实现以下功能&#xff1a; 使用键盘上下左右键在可编辑的 el-input/el-select 之间移动焦点焦点移动时自动定位到对应单元格支持光标位置自动调整…

MyBatis:从入门到进阶

&#x1f4cc; 摘要 在 Java 后端开发中&#xff0c;MyBatis 是一个非常流行且灵活的持久层框架。它不像 Hibernate 那样完全封装 SQL&#xff0c;而是提供了对 SQL 的精细控制能力&#xff0c;同时又具备 ORM&#xff08;对象关系映射&#xff09;的功能。 本文将带你从 MyB…

leetcode51.N皇后:回溯算法与冲突检测的核心逻辑

一、题目深度解析与N皇后问题本质 题目描述 n皇后问题研究的是如何将n个皇后放置在nn的棋盘上&#xff0c;并且使皇后彼此之间不能相互攻击。给定一个整数n&#xff0c;返回所有不同的n皇后问题的解决方案。每一种解法包含一个明确的n皇后问题的棋子放置方案&#xff0c;该方…

算法-每日一题(DAY9)杨辉三角

1.题目链接&#xff1a; 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 2.题目描述&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRo…

【MATLAB代码】制导方法介绍与例程——追踪法,适用于二维平面,目标是移动的|附完整源代码

追踪法(追踪导引法)是一种常见的导弹导引方式,其基本原理是保持导弹的速度矢量始终指向目标。在追踪法中,导弹的加速度可以表示为指向目标的加速度。 本文给出二维平面下,移动目标的追踪法导引的介绍、公式与matlab例程 订阅专栏后,可以直接查看完整源代码 文章目录 运行…

小白的进阶之路系列之十八----人工智能从初步到精通pytorch综合运用的讲解第十一部分

从零开始的NLP:使用序列到序列网络和注意力机制进行翻译 我们将编写自己的类和函数来预处理数据以完成我们的 NLP 建模任务。 在这个项目中,我们将训练一个神经网络将法语翻译成英语。 [KEY: > input, = target, < output]> il est en train de peindre un table…

SSL安全证书:数字时代的网络安全基石

SSL安全证书&#xff1a;数字时代的网络安全基石 在当今数字化浪潮中&#xff0c;网络通信安全已成为个人、企业和组织不可忽视的核心议题。SSL&#xff08;Secure Sockets Layer&#xff0c;安全套接层&#xff09;安全证书作为保障数据传输安全的关键技术&#xff0c;通过加…

LLM-201: OpenHands与LLM交互链路分析

一、核心交互链路架构 #mermaid-svg-ZBqCSQk1PPDkIXNx {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-icon{fill:#552222;}#mermaid-svg-ZBqCSQk1PPDkIXNx .error-text{fill:#552222;strok…

【项目】仿muduo库one thread one loop式并发服务器SERVER模块(下)

&#x1f4da; 博主的专栏 &#x1f427; Linux | &#x1f5a5;️ C | &#x1f4ca; 数据结构 | &#x1f4a1;C 算法 | &#x1f152; C 语言 | &#x1f310; 计算机网络 |&#x1f5c3;️ mysql 项目文章&#xff1a; 仿muduo库one thread one loop式并发服务器…

数据库索引结构 B 树、B + 树与哈希索引在不同数据查询场景下的适用性分析

一、数据库索引结构B树 树概述 树是一种多路平衡查找树&#xff0c;广泛应用于数据库和文件系统中。B树的节点可以存储多个数据元素&#xff0c;并且保持树的平衡&#xff0c;以提高查询效率。 适用性分析 在数据量较大&#xff0c;范围查找较多的场景下&#xff0c;B树的查询效…

Linux进程间通信——信号

1.信号的介绍 信号( Signal )是 Unix, 类Unix以及其他POSIX兼容的操作系统中进程间通信的一种有限制的手段。 1&#xff09;信号是在软件层面上对中断机制的一种模拟&#xff0c;是一种异步通信方式。2&#xff09;信号可以直接进行用户空间进程和内核进程之间的交互&#xff…

Bytemd@Bytemd/react详解(编辑器实现基础AST、插件、跨框架)

ByteMD Markdown编辑器详细解释&修改编辑器默认样式&#xff08;高度300px) AST树详解 [ByteMD 插件系统详解(https://blog.csdn.net/m0_55049655/article/details/148811248?spm1001.2014.3001.5501) Sevelet编写的Bytemd如何适配到React中 ⚡️1️⃣ 背景概述 Byte…

《Redis》事务

文章目录 Redis中的原子性Redis的事物和MySQL事务的区别Redis实现事务什么场景下&#xff0c;会使用事务? Redis事务相关命令watch命令的实现原理 总结 Redis中的原子性 Redis的原子性不同于MySQL的原子性。 Redis的事物和MySQL事务的区别 但是注意体会Redis的事务和MySQL…

Elasticsearch Kibana (一)

一、官方文档 elasticsearch官网&#xff1a;elasticsearch官网 elasticsearch源码&#xff1a;elasticsearch源码 ik分词器&#xff1a; ik分词器 ik分词器下载&#xff1a;ik分词器下载 elasticsearch 版本选择&#xff1a;elasticsearch 版本选择 官方推荐Elasticsearch和j…

[linux] Ubuntu 24软件下载和安装汇总(自用)

经常重装系统&#xff0c;备份下&#xff0c;有用的也可以参考。 安装图形界面 apt install ubuntu-desktop systemctl set-default graphical.target reboot 安装chrome wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb sudo apt insta…

分布变化的模仿学习算法

与传统监督学习不同,直接模仿学习在不同时刻所面临的数据分布可能不同.试设计一个考虑不同时刻数据分布变化的模仿学习算法 import numpy as np import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader, TensorDataset from…