01-redis

Redis

常识:
磁盘:

1.寻址:ms(毫秒级) 2.带宽:G/M

内存:

1.寻址:ns(纳秒) 2,带宽:带宽=内存核心频率×内存总线位数×倍增系数 (秒>毫秒>微秒>纳秒 磁盘比内存在寻址上慢了10W倍)

I/O buffer:

成本问题磁盘与磁道,扇区,一扇区 512Byte带来一个成本变大:索引4K 操作系统,无论你读多少,都是最少4k从磁盘拿

存储引擎:https://db-engines.com/en/
redis:https://redis.io/

Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings), 散列(hashes), 列表(lists), 集合(sets), 有序集合(sorted sets) 与范围查询, bitmaps, hyperloglogs 和 地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication),LUA脚本(Lua scripting), LRU驱动事件(LRU eviction),事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

redis数据类型

image.png

安装 install

1.yum install wget

2.cd ~

3.mkdir soft

4.cd soft

5.wget http://download.redis.io/releases/redis-5.0.5.tar.gz

6.tar xf redis...tar.gz

7.cd redis-src

8.看 README.md

9.make

... yum install gcc

... make distclean

10.make

11.cd src 生成了可执行程序

12.cd..

13.make install PERFEX=/opt/nie/redis5

14.vi /etc/profile

export REDIS_HOME=/opt/nie/redis5

export PATH=$PATH:$REDIS_HOME/bin

source /etc/profile

15.cd utils

16..install_server.sh(可以执行一次或者多次)

(1)一个物理机中可有多个redis 实例(进程),通过port区分

(2)可执行程序就一份在目录,但是内存中未来的多个示例需要各自的配置文件,持久化目录资源。

(3)service redis_6379 start/stop/status >linux /etc/init.d/****

(4)脚本还会帮你启动。

ps -ef|grep redis

BIO:当一个文件要冲内核加载到内存的时候,进程/线程在执行内核系统调用read,socket数据包没到的时候,read阻塞状态blocking

NIO:一个线程/进程死循环一直读取socket的数据包,读不到就读取下一个,轮询的读,nonblocking,减少多线程的切换

IO多路复用:NIO的io次数还是太高,因为如果有1000个read,那么会有1000次io,多路复用体现在,批量调用内核,一次性返回数据状态,这样线程/进程可以根据有数据的这些fd,去再次去内核拿数据,减少io次数

mmap:内核和jvm在用户空间里的一个共享空间,基于mmap读写磁盘文件不会招致系统调用以及额外的内存copy开销

redis单线程单实例为何快?

1.redis在内存存储数据,操作也在内存。(内存寻址快,带宽大)

2.I/O多路复用技术。基于内核的epoll,epoll为系统函数,当描述符在epoll函数中为ready时,才可以去read,减少线程不必要的调用;mmap为内核态和用户态共享空间,由系统内核实现,减少数据传输。

Redis缓存数据库 - 二进制安全

redis只存储二进制字节流,内部不会帮助转换

  1. 当我在客户端上set数据时,存储的数的字符集编码是你客户端的字符集,比如你的Xshell的字符集是UTF-8,那么当set一个中文时,使用strlen命令得到的长度是三个字节,因为中文在utf-8中是三个字节编码得到的
  2. 2.当数据存储到客户端时,实际上就是一个字节数组

Redis缓存数据库 - bitmap

  • 连接redis:redis-cli -p 6379 ,退出exit
  • 查看某个组命令:help @generic…help @string…
  • 每个组都有自己的命令,比如set k1 1,set是string组的,所以type k1返回的是string
  • mset k1 v1 k2 v2…mget k1 k2…可以同时设置多个key,也可以同时取出多个key
  • 每个数据有二进制编码类型,比如set k1 1,通过object encoding k1,返回int,set k2 hello,返回embstr。如果对数据进行更改,会自动转换数据类型,例如set k1 99,执行append k1 1,数据类型会变为raw不再是int,此时执行incr k1 或者incrby k1 2…decr k1,k1数据类型会变为int
  • getrange k1 0 1 获取k1 0~1范围的内容,strlen 获取长度
  • flushall清除所有key
  • 返回所有key–>keys *
  • redis有16个数据库独立空间,切换数据库select 1,select 2,默认0
  • redis是二进制安全的,所有字符在内部都是字节数组的存在,客户端的编码格式进行解码,连接的时候可以进行格式化处理redis-cli -p 6379 --raw
  • setbit k1 7 1可以进行位图修改,一个字节8位,这个命令就是将第一个字节的第8位改成1
  • bitpos,返回位图第一个出现的位置,bitpos k1 1 0 0,表示在第一个字节里面找1出现的位置,后面数字表示第一个字节数组的索引
  • bitcount:bitcount k1 0 1,表示在第0个字节和第一个字节里面找1出现的次数,0 1表示第一个到第二个字节数组索引
  • bitop :位图操作,例如bitop and andkey k1 k2,意思就是k1 k2进行位与运算,得到结果给目标andkey,…bitop or andkey k1 k2…
应用

image.png

redis_使用

5、list:双向链表,具有head节点和tail节点,可以实现栈、队列、数组、阻塞单播队列
a)lpush(向左边添加)k1 a b c 输出c b a
b)rpush(向右边添加)k2 a b c 输出a b c
c)lpop(从左边弹出)k1 输出c b a
d)rpop(从右边弹出)k1 输出a b c
e)lrange(从开始取到结束)
f)lindex(根据下标取值)
g)lset(根据下标赋值)
h)lrem(从前向后移除N:2个value:xx)k1 2 xx
i)linsert(在value:a的前before/后after插入xx)k1 before a xx
j)blpop(阻塞获取k1的值,获取不到则等待x:20秒,先到先得)k1 20
k)ltrim(把下标start:1前end:3后的数据移除)k1 1 3

6、hash:value中存放一个hashmap

  • hset k1 age 18 单个操作,hmset k1 age 18 name zzz
  • hget k1 age取单个key的值,hmget k1 get name取多个的
  • hkeys k1 取k1的所有key
  • hvals k1 取k1的所有value
  • hgetall k1,取k1的所有key 和value
  • HINCRBYFLOAT k1 age 0.5可以针对value计算

7、set:无序、去重集合
a)sadd(去重插入)k1 a b c d a 输出a b c d
b)smembers(取出所有值)k1 输出a b c d
c)srem(删除)k1 c 输出a b d
d)sinter (求交集并输出) k1(1,2,3,4,5) k2(4,5,6,7,8) 输出 4,5
e)sinterstore(求交集存入新key) k3 k1(1,2,3,4,5) k2(4,5,6,7,8) 输出 2
f)sunion(求并集并输出)k1(1,2,3,4,5) k2(4,5,6,7,8) 输出 1,2,3,4,5,6,7,8
g)sunionstore(求并集存入新key)k3 k1(1,2,3,4,5) k2(4,5,6,7,8) 输出 8
h)srandmember(取出count个随机结果集)k1(1,2,3,4) count ,count是正数,取出一个去重的结果集;count是负数,取出一个带重复的结果集
i)spop(取出一个随机结果)
8、sorted_set:有序去重集合
a)zadd(插入3|a,2|b,4|c)k1 3 a 2 b 4 c 存入2|b,3|a,4|c
b)zrange(按索引取出) k1 0 -1返回b,a,c
c)zrange(按索引取出带分值) k1 0 -1 withscores返回b,2,a,3,c,4
d)zrangebyscores(按分值取出) k1 2 3 返回 b,a
e)zrevrange(倒叙取出)k1 0 1 返回 c,a
f)zscore (根据元素取分值) k1 a 返回3
g)zrank(根据元素取排名)k1 c 返回3
h)zincrby(给分值做加减运算)k1 2.5 a 返回5.5
i)zunionstore(k1和k2取并集存入k3)k3 2 k1(80 a 60 b 70 c) k2(60 a 100 b 40 d) k1的权重 k2的权重 聚合函数(sum、min、max)
zunionstore k3 2 k1 k2 返回d 40 c 70 a 140 b 160
zunionstore k3 2 k1 k2 weights 1 0.5 返回d 20 c 70 a 110 b 110
zunionstore k3 2 k1 k2 aggregate max 返回d 40 c 70 a 80 b 100

9、sorted_set:数据结构(跳跃表skip list)

  • sortedSet包含三部分:元素 、排名、 分值
  • 物理内存左小右大
  • zadd k1 8 apple 6 banana 3 orange,三个元素,分值分别为8 6 3
  • zrange k1 0 -1,取出k1所有元素,排名根据分值有小到大排列
  • zrevrange k1 0 -1,反向排名,分值从大到小排列
  • zscore k1 apple,获取apple的分值
  • zrank k1 apple,获取apple的排名
  • zrange k1 0 -1 withscores,取所有元素并加上分值
  • arange k1 0 1,取前两个
  • zincrby k1 0.5 apple,将apple的分值增加0.5
  • zunionstore dest 2 k1 k2 weights 1 0.5 aggreate max,求交集,默认是sum求和,默认没有权重
  • zremrangebyrank key start stop 移除元素
    image.png
    image.png

redis进阶使用

redis发布订阅

image.png

image.png

事务处理

redis仅支持简单事务

MULTI 开启事务

[commend]

[commend]

EXEC提交事务

redis事务的原理是,MULTI开启事务后的命令不会被执行,只有当EXEC命令后才会按照顺序执行命令

redis只会应为错误的语法而导致命令执行失败,错误的命令会在执行前就被发现,错误的命令会导致命令队列中前面的命令被清空,而后面的命令可以正常执行

redis事物不支持回滚 因为redis单进程如果有两个client发送信息 是放在不同的缓冲区存储 开启事物之后谁先exec 谁先执行

image.png

WATCH key [key ...]
起始版本:2.2.0

时间复杂度:O(1) for every key.

标记所有指定的key 被监视起来,在事务中有条件的执行(乐观锁)。

返回值
simple-string-reply: 总是 OK。

缓存穿透

某查询缓存中没有命中,会尝试从数据库中获取,从而导致大量请求到达数据库,如果数据库中本身没有该数据,这就导致数据库执行了很多不必要的操作,从而增加了数据库的压力。

解决办法:

1 对于热点查询,设置key-null,为其缓存空对象

2 使用布隆过滤器,维护一个bitmap。布隆算法可以客户端实现,也可以直接使用redis中额外引用的,bitmap可以由客户端维护,也可以由redis维护。大致是,bitmap中标记已有的数据,没有的数据直接由维护的bitmap过滤掉,从而不再访问数据库,存在一定概率误标记,但是成本低。

布隆过滤器

1,访问redis.io
2,modules
3,访问RedisBloom的github https://github.com/RedisBloom/RedisBloom
4,linux中wget *.zip
5,yum install unzip
6,unzip *.zip
7,make
8,cp bloom.so /opt/yitian/redis5/
9,redis-server --loadmodule /opt/yitian/redis5/redisbloom.so
10 ,redis-cli
11,bf.add ooxx abc
bf.exits abc
bf.exits sdfsdf
image.png

内存淘汰策略

LRU:多久没碰他(最近时间使用)

LFU: 碰了多少次

给key设置有效期后,不会随着访问延长过期时间,如果发生写操作,会剔除过期时间

EXPIREAT:设置一个时间戳,定时任务,定时删除
image.png

redis非阻塞落地(RDB快照)

Redis父进程fork创建子进程,子进程持有父进程当前的指针,指向实际存储的值。由于父子进程数据隔离(namespace机制隔离),所以父进程发生增删改仅使父进程持有的指针指向新的物理地址,而子进程持有的指针不变,依然指向创建时的实际值,从而达到非阻塞保存时点快照
image.png

阻塞式:save命令,服务器需要关机维护时,使用save命令,确保RDB期间不会有新的写入

非阻塞式:bqsave,服务器正常运行时使用bqsave,保证RDB期间服务仍然可用
image.png

  1. “save 900 1”表示如果900秒内至少1个key发生变化(新增、修改和删除),则重写rdb文件;
  2. “save 300 10”表示如果每300秒内至少10个key发生变化(新增、修改和删除),则重写rdb文件;
  3. “save 60 3600”表示如果每60秒内至少10000个key发生变化(新增、修改和删除),则重写rdb文件

任意一个条件满足就触发重写。

RDB和AOF

RDB

a)时点性
b)手动调用save:阻塞式持久化,redis在持久化时不对外提供服务,持久化结束再开放对外服务
c)手动调用bgsave:异步非阻塞持久化,使用fork()+copyOnWrite
d)配置文件中使用save创建bgsave规则
e)弊端:不支持拉链,只有一个dump.rdb,需要定时策略,每天把文件拷出去加上时间;容易丢失数据,两个时点之间挂机的话窗口数据容易丢失;
f)优点:类似Java中的序列化,恢复速度快

AOF

a)redis的写操作记录到文件中,丢失数据少;
b)redis可以RDB和AOF同时开启,但是只会用AOF做恢复,4.0以后AOF包含RDB全量,增加记录新的写操作,恢复时先RDB再读AOF
c)弊端:体量无限大,恢复慢
d)4.0前解决案:重写,删除抵消命令,合并重复命令,最终变成一个纯指令的日志文件
e)4.0后解决案:重写,将老的数据RDB到aof文件中,将增量以AOF的方式加到日志中。是一个混合体,利用RDB的快和AOF的全
f)redis是内存数据库,会触发IO拖慢速度,可以调整级别(NO;ALWAYS;everysec)
g)如果执行了bgrewriteaof就会只保留当前的状态,历史rdb和历史操作记录就都融合了,没办法再恢复了

配置
appendonly yes
appendfilename "appendonly.aof"
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
appendfsync always
appendfsync everysec :每秒,丢失数据相对较少
appendfsync no :表示不会触发内核刷新buffer,会等内核满了以后才会将数据刷到磁盘中

redis的集群

1.AKF机制 X,Y,Z轴延伸解决单机中存在的问题

image.png

2.延伸X轴–主从复制+哨兵模式–实现高可用image.png

3.通过AKF,一变多–引发数据一致性问题–解决方案

image.png

image.png

主从复制;

https://blog.csdn.net/qq_39131177/article/details/122458695

一、什么是哨兵模式:

1、哨兵模式的架构:
image.png

2、什么是哨兵模式:

在主从模式下(主从模式就是把上图的所有哨兵去掉),master节点负责写请求,然后异步同步给slave节点,从节点负责处理读请求。如果master宕机了,需要手动将从节点晋升为主节点,并且还要切换客户端的连接数据源。这就无法达到高可用,而通过哨兵模式就可以解决这一问题。

哨兵模式是Redis的高可用方式,哨兵节点是特殊的redis服务,不提供读写服务,主要用来监控redis实例节点。 哨兵架构下client端第一次从哨兵找出redis的主节点,后续就直接访问redis的主节点,不会每次都通过sentinel代理访问redis的主节点,当redis的主节点挂掉时,哨兵会第一时间感知到,并且在slave节点中重新选出来一个新的master,然后将新的master信息通知给client端,从而实现高可用。这里面redis的client端一般都实现了订阅功能,订阅sentinel发布的节点变动消息。

3、哨兵的主要工作任务:
(1)监控:哨兵会不断地检查你的Master和Slave是否运作正常。

(2)提醒:当被监控的某个Redis节点出现问题时,哨兵可以通过 API 向管理员或者其他应用程序发送通知。

(3)自动故障迁移:当一个Master不能正常工作时,哨兵会进行自动故障迁移操作,将失效Master的其中一个Slave升级为新的Master,并让失效Master的其他Slave改为复制新的Master;当客户端试图连接失效的Master时,集群也会向客户端返回新Master的地址,使得集群可以使用新Master代替失效Master。

二、哨兵模式的搭建:

1、配置sentinel.conf文件,配件需要监听的主从的master节点

sentinel monitor <master‐name> <ip> <redis‐port> <quorum>

(1)master‐name:主节点master的名字

(2)quorum:哨兵集群中多少个sentinel 认为 master 失效才判定为客观下线,一般配节点数/2+1,也就是说大于半数

2、如果主从master设置了密码,还需要配置:

sentinel auth-pass <master-name> <password>

由于master挂了之后,哨兵会进行重新的选举,如果slave也配置了连接密码,那么最好在其他的节点都配置上 masterauth xxx,保证挂了的服务重启之后能正常加入主从中去

3、修改心跳检测的主观下线时间(后续讲原理的时候会详细讲到):

sentinel down-after-milliseconds <master-name> <time>

(1)time:主观下线阈值,单位为毫秒ms

4、从服务器的个数配置:

sentinel parallel-syncs mymaster 2

5、启动指定的哨兵配置文件启动哨兵:

./redis-server sentinel.conf --sentinel &

6、查看状态信息:

配置完之后,进入./redis-cli,输入info命令,查看哨兵的状态信息

image.png

再使用同样的配置文件,启动另外两个哨兵,在查看信息之后会发现哨兵数量变成3个

image.png

7、Java客户端连接哨兵模式,只需要配置哨兵节点即可

spring.redis.sentinel.master=mymaster #哨兵配置中集群名字
spring.redis.sentinel.nodes=哨兵ip1:哨兵端口1,哨兵ip2:哨兵端口2,哨兵ip3:哨兵端口3
三、哨兵模式的工作原理:

哨兵是一个分布式系统,可以在一个架构中运行多个哨兵进程,这些进程使用流言协议(gossip protocols)来传播Master是否下线的信息,并使用投票协议(agreement protocols)来决定是否执行自动故障迁移,以及选择哪个Slave作为新的Master。哨兵模式的具体工作原理如下:

1、心跳机制:

(1)Sentinel 与 Redis Node:Redis Sentinel 是一个特殊的 Redis 节点。在哨兵模式创建时,需要通过配置指定 Sentinel 与 Redis Master Node 之间的关系,然后 Sentinel 会从主节点上获取所有从节点的信息,之后 Sentinel 会定时向主节点和从节点发送 info 命令获取其拓扑结构和状态信息。

(2)Sentinel与Sentinel:基于 Redis 的订阅发布功能, 每个 Sentinel 节点会向主节点的 sentinel:hello 频道上发送该 Sentinel 节点对于主节点的判断以及当前 Sentinel 节点的信息 ,同时每个 Sentinel 节点也会订阅该频道, 来获取其他 Sentinel 节点的信息以及它们对主节点的判断

通过以上两步所有的 Sentinel 节点以及它们与所有的 Redis 节点之间都已经彼此感知到,之后每个 Sentinel 节点会向主节点、从节点、以及其余 Sentinel 节点定时发送 ping 命令作为心跳检测, 来确认这些节点是否可达。

2、判断master节点是否下线:

(1)每个 sentinel 哨兵节点每隔1s 向所有的master、slave以及其他 sentinel 节点发送一个PING命令,作用是通过心跳检测,检测主从服务器的网络连接状态

(2)如果 master 节点回复 PING 命令的时间超过 down-after-milliseconds 设定的阈值(默认30s),则这个 master 会被 sentinel 标记为主观下线,修改其 flags 状态为SRI_S_DOWN

(3)当sentinel 哨兵节点将 master 标记为主观下线后,会向其余所有的 sentinel 发送sentinel is-master-down-by-addr消息,询问其他sentinel是否同意该master下线

发送命令:sentinel is-master-down-by-addr <current_epoch>

ip:主观下线的服务ip

port:主观下线的服务端口

current_epoch:sentinel的纪元

runid:*表示检测服务下线状态,如果是sentinel的运行id,表示用来选举领头sentinel

(4)每个sentinel收到命令之后,会根据发送过来的 ip和port 检查自己判断的结果,回复自己是否认为该master节点已经下线了

回复内容主要包含三个参数(由于上面发送的runid参数是*,这里先忽略后两个参数)

down_state(1表示已下线,0表示未下线)

leader_runid(领头sentinal id)

leader_epoch(领头sentinel纪元)。

(5)sentinel收到回复之后,如果同意master节点进入主观下线的sentinel数量大于等于quorum,则master会被标记为客观下线,即认为该节点已经不可用。

(6)在一般情况下,每个 Sentinel 每隔 10s 向所有的Master,Slave发送 INFO 命令。当Master 被 Sentinel 标记为客观下线时,Sentinel 向下线的 Master 的所有 Slave 发送 INFO 命令的频率会从 10 秒一次改为每秒一次。作用:发现最新的集群拓扑结构

3、基于Raft算法选举领头sentinel:

到现在为止,已经知道了master客观下线,那就需要一个sentinel来负责故障转移,那到底是哪个sentinel节点来做这件事呢?需要通过选举实现,具体的选举过程如下:

(1)判断客观下线的sentinel节点向其他 sentinel 节点发送 SENTINEL is-master-down-by-addr ip port current_epoch runid

注意:这时的runid是自己的run id,每个sentinel节点都有一个自己运行时id

(2)目标sentinel回复是否同意master下线并选举领头sentinel,选择领头sentinel的过程符合先到先得的原则。举例:sentinel1判断了客观下线,向sentinel2发送了第一步中的命令,sentinel2回复了sentinel1,说选你为领头,这时候sentinel3也向sentinel2发送第一步的命令,sentinel2会直接拒绝回复

(3)当sentinel发现选自己的节点个数超过 majority 的个数的时候,自己就是领头节点

(4)如果没有一个sentinel达到了majority的数量,等一段时间,重新选举

4、故障转移:

有了领头sentinel之后,下面就是要做故障转移了,故障转移的一个主要问题和选择领头sentinel问题差不多,到底要选择哪一个slaver节点来作为master呢?按照我们一般的常识,我们会认为哪个slave节点中的数据和master中的数据相识度高哪个slaver就是master了,其实哨兵模式也差不多是这样判断的,不过还有别的判断条件,详细介绍如下:

(1)在进行选择之前需要先剔除掉一些不满足条件的slaver,这些slaver不会作为变成master的备选

剔除列表中已经下线的从服务
剔除有5s没有回复sentinel的info命令的slave
剔除与已经下线的主服务连接断开时间超过 down-after-milliseconds * 10 + master宕机时长 的slaver
(2)选主过程:

① 选择优先级最高的节点,通过sentinel配置文件中的replica-priority配置项,这个参数越小,表示优先级越高

② 如果第一步中的优先级相同,选择offset最大的,offset表示主节点向从节点同步数据的偏移量,越大表示同步的数据越多

③ 如果第二步offset也相同,选择run id较小的

5、修改配置:

新的master节点选择出来之后,还需要做一些事情配置的修改,如下:

(1)领头sentinel会对选出来的从节点执行slaveof no one 命令让其成为主节点

(2)领头sentinel 向别的slave发送slaveof命令,告诉他们新的master是谁谁谁,你们向这个master复制数据

(3)如果之前的master重新上线时,领头sentinel同样会给起发送slaveof命令,将其变成从节点
来源:https://blog.csdn.net/a745233700/article/details/112451629

数据拆分
集群分治

image.png

redis_击穿

1、redis作为缓存使用,会对冷数据进行清除
a)key有过期时间
b)LRU
c)LFU
2、客户端发来的请求正好是对冷数据的访问,因为已经被清除,所以会直接访问数据库
3、高并发时穿过redis直接访问数据库,被称为击穿
4、解决:
a)第一个访问的人发现key不存在
b)调用setnx()加锁
c)只有获得锁的人去访问数据库,访问后set key
d)其他人都去抢锁,抢不到sleep一会
e)sleep结束再去访问key
5、弊端:
a)第一个人挂了,造成死锁==>可以设置锁的过期时间
b)没挂,锁超时了==>多线程,一个线程去db,一个线程监控是否取完,没有则更新锁的时间
image.png

redis_穿透

1、redis作为缓存使用
2、客户端访问DB中根本不存在的数据
3、访问系统中根本不存在的数据,导致大量访问到达DB,称之为穿透
4、解决:布隆过滤器
a)client端包含过滤器
b)client端包含算法,bitmap放置在redis
c)redis集成布隆
d)弊端:只能增加不能删除==>换一个可删除、修改的过滤器,比如布谷鸟
image.png

redis_雪崩

1、redis作为缓存使用,大量的key同时失效了
2、间接造成大量的访问到达DB
3、因为大量key同时失效导致访问到达DB被称之为雪崩。
4、解决:
a)时点性无关的时候可以使用随机过期时间来让key失效,防止同时失效
b)批处理等定点过期时候,可以使用强依赖击穿方案(加锁访问)
c)业务层增加定点延时,批处理开始时延时访问image.png

redis_分布式锁

1、设置锁setnx,由第一个访问者获得锁
2、增加过期时间,防止访问者宕机或者长处理未结束
3、多线程(守护线程),如果处理未完成延长过期时间
4、可以使用redisson来进行实现,但redis就是为了快,为了保证准确度和一致性,最好使用zookeeper来做分布式锁

Api

config set protected-mode no 准许外部连接
jedis,支持客户端原语,但是非线程安全的
lettuce,支持同步、异步访问,支持原语

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值