目录标题)

  • 一、主从复制原理(读写分离)
    • 1、配置一主二从集群
    • 2、测试读写分离
    • 3、服务器宕机后
  • 二、主从复制——薪火相传(链式的)
  • 三、反客为主 (主服务器宕机后从服务器变为主服务器)
  • 四、哨兵模式(升级版反客为主)
    • 1、创建sentinel.conf文件
    • 2、启动哨兵
    • 3、然后通过docker stop 关闭主reids
    • 4、主机挂掉后如何选举主机呢?
  • 五、搭建redis集群
    • 1、修改redis.conf文件
    • 2、修改redis的默认端口号
    • 3、运行redis后nodes-6379.conf 会在工作目录生成
    • 4、将节点合成集群
      • 使用docker安装redis,在运行容器时指定的安装目录为:
    • 5、连接redis集群
    • 6、集群中如何分配节点(那些节点成为主节点,那些节点为从节点,从节点怎么认主)
    • 7、如何存储key(负载均衡)
    • 8、redis集群常见操作
    • 9、redis集群存在的一些问题
    • 10、故障恢复
    • 11、jedis使用redis集群
  • 六、redis应用问题
    • 1、缓存穿透——访问不存在的key
    • 2、缓存击穿——某个热门的key过期了
    • 3、缓存雪崩——访问到大量过期的key
  • 七、分布式锁
    • 1、redis如何实现
    • 2、jedis实现
      • 2.1、不使用lua脚本(在进行if判断时可能会被自动过期指令打断)
      • 2.2、使用lua脚本(保证了判断与执行的原子性)

redis1(入门)

一、主从复制原理(读写分离)

原理:第一次同步数据由从服务器发起,当主服务器接收到从服务器要求同数据的请求后,将dump.rdb文件发送给从服务器。之后主服务器每次写操作后,由主服务器发起同步请求。

1、配置一主二从集群

  1. 创建文件夹:
# 6379
[root@iz2zedg4ylq9iqtwm11wecz redis6379]# pwd
/my/redises/redis6379
[root@iz2zedg4ylq9iqtwm11wecz redis6379]# ls
conf  data#6380
[root@iz2zedg4ylq9iqtwm11wecz redis6380]# pwd
/my/redises/redis6380
[root@iz2zedg4ylq9iqtwm11wecz redis6380]# ls
conf  data
[root@iz2zedg4ylq9iqtwm11wecz redis6380]# #6381
[root@iz2zedg4ylq9iqtwm11wecz redis6381]# pwd
/my/redises/redis6381
[root@iz2zedg4ylq9iqtwm11wecz redis6381]# ls
conf  data
[root@iz2zedg4ylq9iqtwm11wecz redis6381]# 
  1. 复制redis.conf

将redis.conf分别复制到三个目录中,并将redis.conf其中的端口号修改为6379、6380、6381

[root@iz2zedg4ylq9iqtwm11wecz conf]# pwd
/my/redises/redis6379/conf
[root@iz2zedg4ylq9iqtwm11wecz conf]# cp /my/redis/conf/redis.conf ./
  1. 使用docker开启三个reids容器
#6379
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker run --name redis6379 -p 6379:6379 --net host -v /my/redises/redis6379/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /my/redises/redis6379/data/:/data -d redis redis-server /usr/local/etc/redis/redis.conf
3c3d9c85cc22ca483eda0da1ead04e7dd58fd0b74438ad4529855f7cd284bb5a
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker ps -a
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS
3c3d9c85cc22        redis               "docker-entrypoint..."   26 seconds ago      Exited (0) 25 sec
dfabf4da2bdd        nginx               "/docker-entrypoin..."   2 months ago        Exited (255) 7 we
598fef497cec        redis               "docker-entrypoint..."   2 months ago        Exited (0) 11 min
78c4a571ae3b        mysql:5.7           "docker-entrypoint..."   2 months ago        Exited (255) 7 we
[root@iz2zedg4ylq9iqtwm11wecz ~]# #6380
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker run --name redis6380 -p 6380:6380 --net host -v /my/redises/redis6380/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /my/redises/redis6380/data/:/data -d redis redis-server /usr/local/etc/redis/redis.conf
996d60edaa59d7485920a355e25a362a7b51e0c38e8cd13e92b7b72a68c1b74d#6381
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker run --name redis6381 -p 6381:6381 --net host -v /my/redises/redis6381/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /my/redises/redis6381/data/:/data -d redis redis-server /usr/local/etc/redis/redis.conf
aab7ed4ad32f6f4944aa95dda085e958a0d342302fa8c73f5886e52734f2e40c
  1. 通过docker start 容器名 启动三个redis容器
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker start redis6379
redis6379
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker start redis6380
redis6380
[root@iz2zedg4ylq9iqtwm11wecz ~]# docker start redis6381
redis6381
[root@iz2zedg4ylq9iqtwm11wecz ~]#
  1. 进入容器
docker exec -it redis6379 /bin/bash
docker exec -it redis6380 /bin/bash
docker exec -it redis6381 /bin/bash
  1. 通过slaveof ip port 将这个redis所在的主机变为从机

注意:修改了redis的端口号后,在打开redis-cli时需要指定对应的端口号,比如redis-cli -p 6380

# 6380( 这里显示6379是因为dockaer端口映射的原理,这台主机外界需要通过6380这个端口进行访问)
127.0.0.1:6379> slaveof 39.96.52.225 6379
OK
# 6381
127.0.0.1:6379> slaveof 39.96.52.225 6379
OK
  1. 通过命令info replication 查看redis的信息
127.0.0.1:6379> info replication
# Replication
role:master
connected_slaves:2
slave0:ip=39.96.52.225,port=6379,state=online,offset=70,lag=0
slave1:ip=39.96.52.225,port=6379,state=online,offset=70,lag=1
master_failover_state:no-failover
master_replid:57e856a00e5642b200b23c9872fa7f0cad475381
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:70
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:70
127.0.0.1:6379>

注意:如果失败,原因如下:
1、没有开放端口,包括阿里云
2、redis.conf配置里面没有关闭保护模式和只允许本机访问

2、测试读写分离

注意主机redis能进行读和写,但是从机redis只能就行读,不能写

# 在主机设置一个key,在两个从机中也能获取到响应的key# 6379
127.0.0.1:6379> hset user id 1 name lihua age 18
(integer) 3# 6380
127.0.0.1:6379> hgetall user
1) "id"
2) "1"
3) "name"
4) "lihua"
5) "age"
6) "18"# 6381
127.0.0.1:6379> hgetall user
1) "id"
2) "1"
3) "name"
4) "lihua"
5) "age"
6) "18"

尝试在从机写一些key

127.0.0.1:6379> set 1 1
(error) READONLY You can't write against a read only replica.

3、服务器宕机后

  1. 当从机宕机后,再次启动时
    从服务器不会直接成为主服务器的从服务器,需要再次对从服务器进行加入(slaveof ip port)操作。加入后会从主服务器中从头到尾重新同步数据,并再次成为主服务器的从服务器。
  2. 当主服务器宕机后。
    当主服务器恢复后从服务器还是从服务器。但是主服务器宕机期间,从服务器还是只能有读操作,没有写操作。

二、主从复制——薪火相传(链式的)


薪火相传也就是,从服务器也能有从服务器。从服务器也可以通过slaveof ip port 添加从服务器

三、反客为主 (主服务器宕机后从服务器变为主服务器)

可以通过命令slaveof no one 将从服务器变为主服务器
注意:
执行slaveof on one命令后,从服务器会变为主服务器。但是这个服务器不在是之前主服务器的从服务器。也就是说这个服务器,将变成主服务器,但是此时它是没有任何的从服务器,也没有成为任何主机的从服务器。

四、哨兵模式(升级版反客为主)

1、创建sentinel.conf文件

在redis容器中创建sentinel.conf文件

root@0bee7c2d98cb:/usr/local/bin# pwd
/usr/local/bin
root@0bee7c2d98cb:/usr/local/bin# touch sentinel.conf
ok
root@0bee7c2d98cb:/usr/local/bin# ls
docker-entrypoint.sh  redis-benchmark  redis-check-rdb  redis-sentinel  sentinel.conf
gosu              redis-check-aof  redis-cli    redis-server

编写sentinel.conf文件,如果没有vim、vi那么可以在宿主主机中用docker cp将编写好的文件复制到容器中。

sentinel monitor mymastter 39.96.52.225 6379 1
# mymastter:给主机一个名称; 39.96.52.225 6379:主机的IP和端口号,1:表示多少个哨兵同意就能将从机升为主机

也可以这样写入

# 写入
echo "sentinel monitor mymastter 39.96.52.225 6379 1" > sentinel.conf
# 查看
cat sentinel.conf

2、启动哨兵

注意:1、在redis的安装目录启动(也就是有redis-sentinel 文件下)
2、注意不要在主机的容器中启动哨兵,因为等下就是要关闭主机,主机的容器关闭后,哨兵也会被关闭,这样就无法监听了

root@0bee7c2d98cb:/usr/local/bin# pwd
/usr/local/bin
root@0bee7c2d98cb:/usr/local/bin# ls
docker-entrypoint.sh  redis-benchmark  redis-check-rdb  redis-sentinel  sentinel.conf
gosu              redis-check-aof  redis-cli    redis-server
root@0bee7c2d98cb:/usr/local/bin#
# 运行
redis-sentinel sentinel.conf

3、然后通过docker stop 关闭主reids

docker stop redis6379

主机被关闭后哨兵就会自动选择一台从机作为主机,并且之前的主机会变为现在主机的从机。当之前的主机重新运行时依旧会作为新主机的从机

当从机变为主机后,会将以前主机拥有的从机变为自己的从机,以前的主机也会变成自己的从机

4、主机挂掉后如何选举主机呢?

  1. 首先根据优先级 在reids.conf 中配置 replica-priority 100
    值越小优先级越高
  2. 当优先级一样,选择从主机中同步到的数据最全的(看key的个数)
  3. 根据redis运行后随机生成的 的runid,越小越优先

五、搭建redis集群

1、并发写操作(之前的主从复制,只能有一台主机有写功能。搭建redis集群后可以实现多台服务器有写功能。)
2、统一调用接口(并且之前的服务器必须通过不同的ip和端口号进行访问。不能进行统一ip端口进行访问。)
3、rdis集群实现了内存扩容

1、修改redis.conf文件

# 修改redis.conf文件
[root@iz2zedg4ylq9iqtwm11wecz conf]# pwd
/my/redises/redis6379/conf
[root@iz2zedg4ylq9iqtwm11wecz conf]# ls
redis.conf
[root@iz2zedg4ylq9iqtwm11wecz conf]# vim redis.conf 
cluster-enabled yes  #开始集群#集群节点的配置文件名,注意这个配置文件不是启动redis的配置文件,而是在运行后自动生成的集群节点的配置文件
cluster-config-file nodes-6379.conf
cluster-node-timeout 15000 #改节点的超时时间,超时自动切换节点

2、修改redis的默认端口号

在redis.conf 里面就行修改就可以了

# 运行redis客户端
redis-cli -p 6380

注意修改节点的端口号后在连接redis-cli时要指定端口号

3、运行redis后nodes-6379.conf 会在工作目录生成


root@74558bbeeb6e:/data# ls
dump.rdb  nodes-6379.confroot@e763b91a444c:/data# ls
dump.rdb  nodes-6380.confroot@35adf3a37c72:/data# ls
dump.rdb  nodes-6381.conf

注意:请确保节点配置文件都生成

4、将节点合成集群

使用docker安装redis,在运行容器时指定的安装目录为:
root@0bee7c2d98cb:/usr/local/bin# pwd
/usr/local/bin

创建集群

# 在改目录下运行
root@74558bbeeb6e:/usr/local/bin# pwd
/usr/local/bin
root@74558bbeeb6e:/usr/local/bin# redis-cli --cluster create 39.96.52.225:6379 39.96.52.225:6380 39.96.52.225:6381

注意:如果运行失败注意redis的版本
失败参考

我的redis版本为:

root@74558bbeeb6e:/usr/local/bin# redis-server --version redis-server -v
Redis server v=6.2.3 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=dc20d908b7b619b4

生成集群时可能会报以下错误

[ERR] Node 39.96.52.225:6379 is not empty. Either the node already knows other nodes (check with CLUSTER NODES) or contains some key in database 0.

解决方法

成功如下

如果一直等待加入,可能需要修改
1、开放端口号,如果节点的端口为6379 ,那么需要开放6379-16379。比如节点中最大的端口为6389,那么要开放6379-16389
参考
2、如果使用docker搭建的redis,需要在创建docker容器创建时允许联网
解决:创建容器时添加–net host 即可如下

docker run --name redis6379 -p 6379:6379 --net host -v /my/redises/redis6379/conf/redis.conf:/usr/local/etc/redis/redis.conf -v /my/redises/redis6379/data/:/data -d redis redis-server /usr/local/etc/redis/redis.conf

5、连接redis集群

注意:通过任意端口都能连接集群,连接集群后能操作集群里面的所有节点

# 使用 redis-cli -c -p 6379 连接集群,-c 表示连接集群 -p 表示端口号,任意节点的端口号都可以
root@iz2zedg4ylq9iqtwm11wecz:/data# redis-cli -c -p 6379
127.0.0.1:6379># 当然你也可以使用redis-cli 连接单个节点,这样就没有连接上集群
root@iz2zedg4ylq9iqtwm11wecz:/data# redis-cli -p 6380
127.0.0.1:6380># 查看集群的节点
127.0.0.1:6379> cluster nodes
098bd49903e178ddcca36222b7227602c9c5d63e 39.96.52.225:6380@16380 master - 0 1629266807819 2 connected 5461-10922
c75a4531edba630b7445a70b5f48a89fc8e64d3c 39.96.52.225:6381@16381 master - 0 1629266807000 3 connected 10923-16383
a3b57cd2eeb9d7b049d76668c68e4394e96f6164 172.24.12.28:6379@16379 myself,master - 0 1629266803000 1 connected 0-5460

在set key时集群会自动根据key,分配给各个节点进行存储

127.0.0.1:6379> set 11 11
OK
127.0.0.1:6379> set 1122 11
-> Redirected to slot [7470] located at 39.96.52.225:6380
OK
39.96.52.225:6380> set 22 11
-> Redirected to slot [13798] located at 39.96.52.225:6381
OK
39.96.52.225:6381>

6、集群中如何分配节点(那些节点成为主节点,那些节点为从节点,从节点怎么认主)

原则:分配是保证每个主节点运行在不同的ip(服务器)上,主节点和从节点不在同一个ip(服务器上)。目的是防止一台服务器挂掉后,集群受到的影响最小。

7、如何存储key(负载均衡)


根据key的值,利用算法,计算出一个范围在0——16384的slot值,再根据这个slot值确定由哪个节点存储

8、redis集群常见操作

# 根据k2计算出slot,根据slot 的值确定将这个值存到6379这个节点
39.96.52.225:6381> set k2 v1
-> Redirected to slot [449] located at 39.96.52.225:6379
OK
39.96.52.225:6379> get 11
"11"
# 根据k1计算出slot,根据slot 的值找到key在6379这个节点里
39.96.52.225:6379> get k1
-> Redirected to slot [12706] located at 39.96.52.225:6381
"v1"
# 计算key的slot值
39.96.52.225:6381> cluster keyslot k1
(integer) 12706

9、redis集群存在的一些问题

  1. mset 指令与单节点不同
# 使用单节点的指令会报错
39.96.52.225:6381> mset 1 1 2 2 3 3 4 4
(error) CROSSSLOT Keys in request don't hash to the same slot

原因:因为这里的指令mset有多个key,redis的负载均衡算法无法计算出来这些key的范围
解决:给这些key分组

39.96.52.225:6381> mset 1{num} 1 2{num} 2 3{num} 3 4{num} 4
-> Redirected to slot [2765] located at 39.96.52.225:6379
OK

10、故障恢复

主节点宕机后,有两种情况
1、若有从节点,那么从节点会自动升级变为主节点,当以前的主节点恢复后,会成为新主节点的从节点。
2、若没有从节点(或者主节点和从节点都宕机),那么redis的默认配置是,整个集群都不可用。可以通过修改redis.conf的参数配置 cluster-require-full-coverage yes 进行配置 。yes为整个集群不可用。

11、jedis使用redis集群

/*** reis集群测试* @author 15594*/
public class RedisCluster {public static void main(String[] args) {//创建集群操作对象//端口号可以时集群节点中的任意一个HostAndPort hostAndPort = new HostAndPort("39.96.52.225", 6381);JedisCluster jedisCluster = new JedisCluster(hostAndPort);jedisCluster.set("b1","value1");String b1 = jedisCluster.get("b1");System.out.println(b1);}
}

六、redis应用问题

1、缓存穿透——访问不存在的key

请求获取数据的原则是,先访问redis缓存,redis中不存在所需要的数据,就去访问数据库。

  1. 什么是缓存穿透
    当非正常的请求(url)恶意访问redis中不存在的key,使得频繁访问数据库。
  2. 解决方案:
  • 对空值就行缓存。在查询数据库后,对不存在的key也加入redis缓存,但是要设置过期时间。
  • 设置白名单。限制ip访问,或则限制访问次数。
  • 如果redis缓存命中率降低,那么就是核查

可以通过布隆过滤器解决缓存穿透问题。

布隆过滤器详解 看了就会用

2、缓存击穿——某个热门的key过期了

  1. 什么是缓存击穿
    瞬时大量请求访问到某个过期的key,然后这些请求瞬时访问数据库,照成数据库崩溃。
  2. 解决方案
  • 预先设置热门数据
  • 根据访问量增加过期时间

3、缓存雪崩——访问到大量过期的key

  1. 什么是缓存雪崩
    访问到大量过期的key,造成大量的请求访问到数据库,造成服务雪崩
  2. 解决方案
  • 使用多级缓存架构 (nginx缓存+redis缓存+其他缓存)
  • 使用锁或者队列(当大量key失效时,对需要直接访问数据库的请求进行加锁或者加入队列,减轻数据库访问压力)
  • 设置过期标志更新缓存。(未雨绸缪,提前预知key的过期时间,提前更新key)
  • 分散key的过期时间。(不要集中设置key的过期时间)

七、分布式锁

与单机的锁不一样,分布式的锁,对不同的主机是不可见的。因为你不能跨操作系统。单机的锁由jvm控制。

分布式锁是解决分布式环境下集群对共享资源的操作。

synchronized它不香吗为啥还要用分布式锁?

  1. 不加锁

  2. 加synchronized、lock锁


3. 当系统升级变为分布式的集群

  1. 解决分布式集群操作共享资源问题——使用分布式锁

1、redis如何实现

  1. 怎么上锁
# setnx——当key不存在时才能添加key
127.0.0.1:6379> setnx 2 2
(integer) 1
  1. 怎么解锁
# 删除这个key,其他请求才能setnx 这个key(上锁)
127.0.0.1:6379> del 2
(integer) 1
  1. 只是上锁可能会形成死锁
    解决:添加超时时间。超时就自动释放锁,也就是给key设置一个过期时间
# nx——不存在时才添加key ,px设置过期时间 以毫秒为单位 ex是以秒为单位
127.0.0.1:6379> set 3 3 nx px 5000
OK

注意:这里不能通过先setnx key value,在给key设置一个过期时间。因为这样分两条指令执行,在分布式中可能会被打断,照成无法成功设置过期时间

2、jedis实现

2.1、不使用lua脚本(在进行if判断时可能会被自动过期指令打断)

package com.lihua.springbootredis.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;/*** 分布式锁——redis实现* @author 15594*/
@RestController
public class ReidLockController {@Autowiredprivate RedisTemplate redisTemplate;@GetMapping("/testLock")public void testLock(){//分布式中一般用雪花算法获取idUUID uuid = UUID.randomUUID();String uid = uuid.toString();System.out.println(uid);//1、获取锁,相当于setnx,如果能设置成功,返回true,成功获取锁,否则失败             3:过期时间值  TimeUnit.SECONDS 时间单位Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uid,3, TimeUnit.SECONDS);//2、如果获取到锁了,就能操作共享资源if (lock){Integer num = (Integer)redisTemplate.opsForValue().get("num");if (num==null){System.out.println("num为null");return;}if (num==0){return;}String isMyLock= (String) redisTemplate.opsForValue().get("lock");System.out.println(isMyLock);//进行--是也要判断自己的锁是否已近过期被释放并且被其他客户端获取,//isMyLock==null&&isMyLock.equals(uid) 防止代码执行到这里key过期了if (num>0&&isMyLock!=null&&isMyLock.equals(uid)){System.out.println("num--");//这里依旧会出问题,因为key可能在进行了if判断后过期,所有要通过lua脚本保证判断和修改同时就行,不会被打断(自动过期的指令打断)redisTemplate.opsForValue().decrement("num");}//防止释放错别人的锁(锁key过期后,自动释放锁,锁又被其他请求上锁,如果不去判断是不是自己的锁就会误释放别人的锁)if(redisTemplate.opsForValue().get("lock").equals(uid)){//这里依旧会出问题,因为key可能在进行了if判断后过期,所有要通过lua脚本保证判断和修改同时就行,不会被打断(自动过期的指令打断)System.out.println("释放锁");redisTemplate.delete("lock");}System.out.println(redisTemplate.opsForValue().get("num"));}else {//3、获取锁失败等待100毫秒再次尝试获取锁try {Thread.sleep(100);testLock();} catch (InterruptedException e) {e.printStackTrace();}}}}

2.2、使用lua脚本(保证了判断与执行的原子性)

package com.lihua.springbootredis.controller;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;import java.util.Arrays;
import java.util.UUID;
import java.util.concurrent.TimeUnit;/*** 分布式锁——redis实现* @author 15594*/
@RestController
public class ReidLockController {@Autowiredprivate RedisTemplate redisTemplate;@GetMapping("/testLockLua")public void testLockLua(){//分布式中一般用雪花算法获取idUUID uuid = UUID.randomUUID();String uid = uuid.toString();System.out.println(uid);//1、获取锁,相当于setnx,如果能设置成功,返回true,成功获取锁,否则失败             3:过期时间值  TimeUnit.SECONDS 时间单位Boolean lock = redisTemplate.opsForValue().setIfAbsent("lock", uid,3, TimeUnit.SECONDS);//2、如果获取到锁了,就能操作共享资源if (lock){Integer num = (Integer)redisTemplate.opsForValue().get("num");if (num==null){return;}if (num==0){return;}String script = "local i=redis.call('get','num')\n" +"\n" +"if tonumber(i)<=0 then \n" +"    return 0;\n" +"end\n" +"if redis.call('exists',KEYS[1])==0 then \n" +"    return 1;\n" +"end\n" +"if redis.call('get',KEYS[1])==ARGV[1] then\n" +"    redis.call('decr','num');\n" +"end\n" +"return 2;";DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();//设置lua脚本返回值redisScript.setResultType(Long.class);redisScript.setScriptText(script);// 执行脚本                                           KEYS      ARGVredisTemplate.execute(redisScript, Arrays.asList("lock"), uid);System.out.println(redisTemplate.opsForValue().get("num"));String script1 = "if redis.call('exists',KEYS[1])==0 then\n" +"    return 0;\n" +"end    \n" +"if redis.call('get',KEYS[1])==ARGV[1] then\n" +"    redis.call('del',KEYS[1])\n" +"    return 1;\n" +"else\n" +"    return 0;\n" +"end";redisScript.setScriptText(script1);redisTemplate.execute(redisScript,Arrays.asList("lock"),uid);System.out.println("锁已近释放");}else {//3、获取锁失败等待100毫秒再次尝试获取锁try {Thread.sleep(100);testLock();} catch (InterruptedException e) {e.printStackTrace();}}}}

注意:在高并发环境下,if判断是不安全的。遇到if条件判断需要谨慎

Redis集群和应用——02相关推荐

  1. Redis 集群部署及踩过的坑

    本文目标 要在单台机器上搭建Redis集群,方式是通过不同的TCP端口启动多个实例,然后组成集群,同时记录在搭建过程中踩过的坑. 安装准备 centos版本:6.7 redis版本:3.2.3 安装方 ...

  2. 集群空间服务器接收不到消息,解决Redis集群条件下键空间通知服务器接收不到消息的问题...

    解决Redis集群条件下键空间通知服务器接收不到消息的问题 键空间通知介绍 键空间通知使得客户端可以通过订阅频道或模式, 来接收那些以某种方式改动了 Redis 数据集的事件. 可以通过对redis的 ...

  3. Redis集群Twemproxy

    Redis集群Twemproxy 1.环境部署: 操作系统 CentOS 6.4 redis版本 redis-3.0.7 redis主服务器 192.168.1.111 redis从服务器1 192. ...

  4. spring 使用redis集群配置

    上面两篇介绍了redis集群的配置合一些基本的概念,所以接下来当然是要在项目中使用咯,redis的java支持已经做的非常好了,所以我们来试着使用这些api来进行redis的操作,首先我们需要操作re ...

  5. Redis集群研究和实践(基于redis 3.0.5)

    前言 redis 是我们目前大规模使用的缓存中间件,由于它强大高效而又便捷的功能,得到了广泛的使用.现在的2.x的稳定版本是2.8.19,也是我们项目中普遍用到的版本. redis在年初发布了3.0. ...

  6. redis集群搭建及设置账户(转)

    Redis集群搭建以及为集群设置密码 介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. ...

  7. redis指定配置文件启动_深入学习 Redis 集群搭建方案及实现原理

    " 在前面的文章中已经介绍了 本文将详细介绍集群,主要内容包括: 集群的作用 集群的搭建方法及设计方案 集群的基本原理 客户端访问集群的方法 实践须知(集群伸缩.故障转移.参数优化等) 集群 ...

  8. redis集群环境安装(参照redis中文官网,中间遇到了一些问题,so,记录一下)

    创建步骤 01. 准备环境 # yum install gcc # yum install ruby # yum install ruby-devel.x86_64 # yum install rub ...

  9. Redis:Redis集群实战

    Redis集群搭建与简单使用 介绍安装环境与版本 用两台虚拟机模拟6个节点,一台机器3个节点,创建出3 master.3 salve 环境. redis 采用 redis-3.2.4 版本. 两台虚拟 ...

最新文章

  1. linux 安全基线加固
  2. win10安装tesserocr配置 Python使用tesserocr识别字母数字验证码
  3. 神策数据丨IPTV/OTT 精细化运营体系构建指南
  4. Python 进程与线程小随笔
  5. Android Property Animation动画
  6. 想加入IT行业为何建议你学Python,学完真值!
  7. 用python实现一个按需生成用于vim跳转的tags文件的小程序
  8. 下载的代码找不到rt.jar中的类
  9. Ubuntu桌面环境 安装与切换
  10. rtmp中flv和flv文件的区别
  11. 视频会议中回声消除与噪音抑制的技巧
  12. 软件项目管理第四课—投标项目需求分析和应答
  13. vfp 操作excel
  14. 关于在dialog中重置form表单失败的问题
  15. L2-016 愿天下有情人都是失散多年的兄妹 (25分)
  16. MATLAB 数学应用 初等数学 绘制虚数和复数数据图
  17. 浙江工业大学计算机专业考研心得
  18. 树莓派内网穿透及其实现监控的相关整理
  19. 九世轮回篇电子计算机乐谱,mc九局九世轮回篇的歌词
  20. L1-046 整除光棍 (20 分)模拟除法

热门文章

  1. 如何将镜像烧写至iNand(fastboot命令的源码分析)
  2. 打王者荣耀还不过瘾,腾讯绝悟AI这次还拿下了足球世界冠军
  3. 计算机系统维护工作内容
  4. Kong的插件:Rate Limiting
  5. 条形码的正确使用方法和技巧
  6. 12月15日(第12天)
  7. 港科百创 | 苏孝宇教授团队获数千万元Pre-A轮融资,祝贺「音科思」!
  8. 沉痛悼念互联网[云原生领域]技术大牛----左耳朵耗子(陈皓老师)
  9. 中科院博士论文《致谢》
  10. 写尽自己一个人的孤独却写不出心里的寂寞