redis怎么使用_redisson怎么用

2025-03-25 21:40 - 立有生活网

怎么设置centos限定redis使用的内存

SET mykey 1

查看Redis的内存大小限制:

redis怎么使用_redisson怎么用redis怎么使用_redisson怎么用


redis怎么使用_redisson怎么用


登陆redis-cli,执行

例如Redis是一个开源的使用ANSI C语言编写、支持网络、:

[root@server11 ~]# /usr/bin/redis-cli

127.0.0.1:注意:上表表示不同的前缀表示的数据范围不同6379> config get maxmemory

1) "maxmemory"

2) "0"

127.0.0.1:6379>

配置文件里也有对应项# maxmemory ,默认是0

例如:

[root@server11 ~]# cat /etc/redis.conf |grep maxmemory

没有配置maxmemory参数值或配置为0的话,32位系统上默认为3G,64位系统上无限制(其实有限制,就是系统上全部可用内存的大小)。

如何在 Go 语言中使用 Redis 连接池

1、乐观锁实现

一、关于连接池

?>

如何在Go语言中使用Redis连接池

myQueue.add("lili");

性能普遍上不去

CPU 大量资源被系统消耗

网络一旦抖动,会有大量 TIME_WAIT 产生,不得不定期重启服务或定期重启机器

工作不稳定,QPS 忽高忽低

要想解决这些问题,我们就要用到连接池了。连接池的思路很简单,在初始化时,创建一定数量的连接,先把所有长连接存起来,然后,谁需要使用,从这里取走,干完活立马放回来。 如果请求数超出连接池容量,那么就排队等待、退化成短连接或者直接丢弃掉。

二、使用连接池遇到的坑

首先,去看一下 Redis 的 Go Redis driver。 Star 的项目有两个:Radix.v2 和 Redigo。经过简单的比较后,选择了更加轻量级和实现更加优雅的 Radix.v2。

由于我想让这种被 fork 的进程简单点,做的事情单一一些,所以,在没有深入去看 Radix.v2 的 pool 的实现之前,我选择了自己实现一个 Redis pool。(这里,就不贴代码了。后来发现自己实现的 Redis pool 与 Radix.v2 实现的 Redis pool 的原理是一样的,都是基于 channel 实现的, 遇到的问题也是一样的。)

不过在测试过程中,发现了一个诡异的问题。在请求过程中经常会报 EOF 错误。而且是概率性出现,一会有问题,一会又好了。通过反复的测试,发现 bug 是有规律的,当程序空闲一会后,再进行连续请求,会发生3次失败,然后之后的请求都能成功,而我的连接池大小设置的是3。再进一步分析,程序空闲300秒 后,再请求就会失败,发现我的 Redis server 配置了 timeout 300,至此,问题就清楚了。是连接超时 Redis server 主动断开了连接。客户端这边从一个超时的连接请求就会得到 EOF 错误。

然后我看了一下 Radix.v2 的 pool 包的源码,发现这个库本身并没有检测坏的连接,并替换为新server{location/pool{content_by_lua_block{localredis=require"resty.redis"localred=redis:new()localok,err=red:connect("127.0.0.1",6379)ifnotokthenngx.say("failedtoconnect:",err)returnendok,err=red:set("hello","world")ifnotokthenreturnendred:set_keepalive(10000,100)}}}

发现有个 set_keepalive 的方法,查了一下文档,方法的原型是 syntax: ok, err = red:set_keepalive(max_idle_timeout, pool_size) 貌似 max_idle_timeout 这个参数,就是我们所缺少的东西,然后进一步跟踪源码,看看里面是怎么保证连接有效的。

function_M.set_keepalive(self,...)localsock=self.sockifnotsockthenreturnnil,"notinitialized"endifself.subscribedthenreturnnil,"subscribedstate"endreturnsock:setkeepalive(...)end

至此,已经清楚了,使用了 tcp 的 keepalive 心跳机制。

于是,通过与 Radix.v2 的作者一些讨论,选择自己在 redis 这层使用心跳机制,来解决这个问题。

四、的解决方案

在创建连接池之后,起一个 goroutine,每隔一段 idleTime 发送一个 PING 到 Redis server。其中,idleTime 略小于 Redis server 的 timeout 配置。连接池初始化部分代码如下:

p,err:=pool.New("tcp",u.Host,concurrency)errHndlr(err)gofunc(){for{p.Cmd("PING")time.Sleep(idelTimetime.Second)}}()

使用 redis 传输数据部分代码如下:

funcredisDo(ppool.Pool,cmdstring,args...intece{})(replyredis.Resp,errerror){reply=p.Cmd(cmd,args...)iferr=reply.Err;err!=nil{iferr!=io.EOF{Fatal.Println("redis",cmd,args,"erris",err)}}return}

//Cmdautomaticallygetsoneclientfromthepool,executesthegivencommand//(returningitsresult),andputstheclientbackinthepoolfunc(pPool)Cmd(cmdstring,args...intece{})redis.Resp{c,err:=p.Get()iferr!=nil{returnredis.NewResp(err)}deferp.Put(c)returnc.Cmd(cmd,args...)}

redis什么时候要用事务

RESP 使用特殊的组合表示空的Bulk Strings或者空的Arrays: $-1

Redis事务使用总结:

Redis的事务机制允许同时执行多条指令,它是原子性作,事务中的命令要么全部执行,要么全部不执行,另外,事务中的所有指令都会被序列化,而且其开始执行过程中,不回被即时过来的指令所打断,其需要经历三个过程,分别为开始事务、命令入队以及执行事务。

· 相关命令

· 遇到问题

· 例子演示

一、相关命令

1、MULTI

该命令用来开启事务,它总是返回ok结果,当其执行之后,客户端可以继续发送任意条数量的指令,这些指令不会立即被执行,而是被放到了队列中,直到EXEC被调用之后,所有命令才会被序列化执行。

2、EXEC

该命令负责触发并执行队列中所有的命令。

NOTE:

如果MULTI开启之后,因为某些原因没有成功执行EXEC,那么事务中所有的命令都不会被执行的。

3、DISCARD

该命令用来刷新事务中所有排队等待执行的指令,它总是返回ok结果,并且将服务连接状态恢复到正常。如果已经使用WATCH,那么其会将释放所有被WATCH的key。

4、WATCH

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

NOTE:

A、WATCH使得EXEC命令需要有条件的执行,也就是事务只能在所有被监视的键没有被修改的前提下才能执行。另外,在EXEC被执行之后,所有的WATCH都会被取消。

B、UNWATCH手动取消对所有键的WATCH,如果执行了EXEC或者DISCARD,则不需要手动执行UNWATCH命令。

二、如何使用

Redis原生使用(Redis-cli):

127.0.0.1:6379> multi // 事务开始的动作标志下面即为入队

OK

127.0.0.1:6379> set book-name "Thinking in Ja"

QUEUED

127.0.0.1:6379> get book-name

QUEUED

127.0.0.1:6379> sadd tag "ja" "Programming""Thinking"

QUEUED

127.0.0.1:6379> embers tag

QUEUED

127.0.0.1:6379> exec // 执行事务

1) OK

2) "Thinking in Ja"

3) (integer) 3

4) 1) "Thinking"

3) "ja"

127.0.0.1:6379> discard // 事务已执行完毕 已经自动取消

(error) ERR DISCARD without MULTI

127.0.0.1:6379> multi

OK

127.0.0.1:6379> set book-name "Patterns in Ja"

QUEUED

127.0.0.1:6379> get book-name

QUEUED

QUEUED

127.0.0.1:6379> embers tag

QUEUED

127.0.0.1:6379> discard // 事务未执行 可以刷新队列指令状态 取消执行

OK

127.0.0.1:6379> exec // 事务已经被取消不能再执行

(error) ERR EXEC without MULTI

三、脚本事务

Redis 2.6开始支持了脚本,而该脚本本身就是一种事务机制,所以任何在事务里可以完成的事,在脚本里面也能完成,并且使用脚本更简单些,并且速度也更快。不过因为事务提供了一种即使不使用脚本,也可以避免竞争条件的方法,并且事务本身的实现并不复杂,所以现在的使用也比较多,但不排除日后可能被替代或是占据主要地位的可能。

NOTE:

Redis为什么引入两种处理事务的方式?脚本功能是 Redis 2.6 才引入的,而事务功能则在更早之前就存在,所以 Redis 才会同时存在两种处理事务的方法。另外,事务脚本会在后续文章中总结介绍。

四、遇到问题

举个例子,设我们需要原子性为某个键加1作(设INCR不存在),那么应该是这样的执行语句:

val = GET mykey

val = val + 1

SET mykey ${val}

单个客户端访问作没有任何问题,如果是多个客户端同时访问mykey,就会产生资源共享访问问题,比如:现在有个两个客户端访问同一个键mykey,那么mykey的可能是2,但是我们期望的值应该是3才对,这个类似于高并发下的sync锁机制,所以我们需要使用WATCH来被共享的键mykey,如下:

WATCH mykey(可多个键)cluster.close();

val = GET mykey

val = val + 1

MULTI

SET mykey ${val}

EXEC

NOTE:

虽然大多情况下,多个客户端访问作同一个键的情况很少或没有,但是不能排除这个特殊情况,所以建议在有可能产生键共享的指令中使用WATCH在EXEC执行前对其监管。

2、Redis不支持回滚(Roll Back)

Redis的事务不支持回滚,这点不同于关系数据库中的事务,所以它的内部保持了简单且快速的特点。另外,Redis不支持回滚是这样考虑的:Redis事务中命令之所以会失败,是由于错误的编程所造成,通过事务回滚是不能回避这个根本问题。

NOTE:

Redis事务中命令执行失败,仍会继续执行后面的执行,在没有特殊干预前提下,直到执行完队列中所有指令为止。

3、使用事务可能遇到的问题

A、事务在执行 EXEC 之前,入队的命令可能会出错,举个例子:命令可能会产生语法错误(参数数量错误,参数名错误等),或者其他更的错误,比如内存不足(如果使用maxmemory 设置了内存限制的话)。

B、事务在执行 EXEC 之前,举个例子:事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面等。

对于发生在 EXEC 执行之前的错误,客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,那么大部分客户端都会停止并取消这个事务。

从 Redis 2.6.5 开始,会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务。

在 Redis 2.6.5 以前, Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令。而新的处理方式则使得在管道技术中包含事务变得简单,因为发送事务和读取事务的回复都只需要和进行一次通讯即可。

至于那些在 EXEC 命令执行之后所产生的错误,并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。

五、例子演示

$redis = new Redis();

$redis->connect('127.0.0.1',6379);

$result = array();

// 开启事务

$redis->multi();

// 添加指令到队列

$redis->set('book-name','Thinking in PHP!');

$redis->sAdd('tags','PHP','Programming','Think这样,我们就有了 keepalive 的机制,不会出现 timeout 的连接了,从 redis 连接池里面取出的连接都是可用的连接了。看似简单的代码,却完美的解决了连接池里面超时连接的问题。同时,就算 Redis server 重启等情况,也能保证连接自动重连。ing');

$bookname = $redis->get('book-name');

$tags = $redis->sMembers('tags');

// 执行事务

$redis->exec();

// 显示结果

echo '书名:'.$bookname.' 标签:'.$tags;

Redis系列篇之SPEC协议

Redis客户端使用被称为 RESP(Redis序列化协议) 的协议与Redis进行通讯。虽然该协议是专门为Redis设计的,但它同样可以被用于其他客户端/的软件项目。

RESP 是以下几点的折中方案:

RESP 可以序列化诸如整型、字符串和数组等不同的数据类型,还有一个特定的错误类型。请求以字符串数组的形式由客户端发送到Redis,字符串数组表示需要执行的命令。Redis用特定于命令的数据类型回复。

RESP 是二进制安全的,不需要处理从一个进程传输到另一个进程的批量数据,因为它使用长度前缀来传输批量数据。

注意: 这里描述的协议仅用于客户端/通信,Redis集群使用不同的二进制协议在之间交换信息。

客户端通过创建端口号为6379的TCP来连接Redis。

虽然 RESP 在技术上是非TCP特定的,但该协议仅用于Redis上下文的(或者等效的面向流的连接,如Unix套接字)TCP连接。

Redis接收由不同参数组成的命令。一旦命令被接收,将会被执行并且发送一个回复给客户端。

除了这两种例外,Redis协议是一种简单的请求-应答协议。

Redis RESP 协议在v1.2版本中介绍,但是到v2.0才变为与通信的标准。

RESP 协议支持以下数据类型: Simple Strings(简单字符串),Errors(错误),Integers(整型),Bulk Strings(批量字符串)以及Arrays(数组)。

Redis通过以下方式将 RESP 用作请求-应答协议:

在 RESP 中,协议不同部分总是以

(CRLF)结尾。

表示空的Bulk Strings, -1

表示空的Arrays,需要注意的是: $0

与 0

分别表示有回复,但长度为0。

Simple Strings(简单字非集群状态下用Jedis获取Redis连接,得到Jedis对象即可,一共有两种:符串)的编码方式为:一个 + 号在最前面,后面跟着一个不能包含CR或者LF字符的字符串(即不允许换行符),并且以CRLF(

)结尾。

Simple Strings(简单字符串)以最小的开销传输非二进制安全的字符串。例如:很多Redis命令执行成功后的回复只是 OK , RESP 简单字符串将以5个字节编码: +OK

如果想要传输二进制安全的字符串,请使用Bulk Strings替代。

当Redis以简单字符串回复时,客户端库应该返回 + 号后面个字符后面的所有字符串(不包括CRLF字节)。

Redis有特定的错误类型,与Simple Strings相似,不同的是个字符是减号 - 而不是加号 + ,二者真正不同的是,客户端将错误视为异常,而构成Error类型的字符串就是错误消息本身。

错误类型的基本格式为:

-Error message

只有当发生错误时才会回复错误,比如你想要在错误的数据类型上执行命令,或者命令根本不存在。客户端收到Error回复时应该抛出异常。

下面是错误回复的例子:

- 号到后面个空格或者新行的个单词表示返回的错误类型,这只是Redis使用的约定,而不是 RESP 错误格式的一部分。

比如, ERR 是一般错误,但是 WRONGTYPE 是一个更具体的错误,暗示客户端尝试执行应对错误类型的作。这被称为 错误前缀 ,是一种允许客户端了解返回的错误类型而无需检查确切错误消息的方法。

客户端实现可能会针对不同的错误返回不同类型的异常,或者通过直接将错误名称作为字符串提供给调用者来提供捕获错误的通用方法。

但是不应将此类功能视为至关重要,因为它很少有用,并且有限的客户端实现可能会简单地返回通用错误条件,例如false

这种类型只是一个以CRLF结尾的字符串,表示一个整数,前缀为 : ,比如: :0

和 :1000

。有很多返回整型的Redis命令,比如: INCR 、 LLEN 以及 LASTSAVE 。返回的整型数据范围为有符号的64位整数。

整型回复同样可以用来表示true或者false,比如 EXISTS 或者 SISMEMBER 将会返回1表示true,0表示false。

其他命令比如 SADD 、 SREM 、 SETNX 如果被执行了将会返回1,否则返回0。

其他返回整型的命令: SETNX 、 DEL 、 EXISTS 、 INCR 、 INCRBY 、 DECR 、 DECRBY 、 DBSIZE 、 LASTSAVE 、 RENAMENX 、 MOVE 、 LLEN 、 SADD 、 SREM 、 SISMEMBER 、 SCARD 。

Bulk Strings被用来表示单个的长度512MB的二进制安全字符串。

Bulk Strings编码方式为:

所以,字符串 hello 被编码为: $5

hello

一个空字符串}}被编码为: $0

RESP Bulk Strings也可用特殊格式表示不存在(NULL),在这种格式中,长度为-1,没有数据: $-1

,这被称作 NULL Bulk String ,当回复NULL Bulk String时,客户端库的API不应该返回空的字符串,而是返回nil对象。

客户端使用RESP Arrays发送命令到。同样,某些返回元素给客户端的命令使用RESP数组作为回复,比如: LRANGE 命令。RESP Arrays以下面的格式发送:

所以,空数组编码为: 0

包含"hello"和"world"两个元素的RESP数组被编码为: 2

$5

hello

$5

world

如你所见, CRLF 前缀后面,组成数组的其他数据类型只是一个接一个的连接起来,比如一个由3个整型构成的Array编码结果为: 3

:1而你在搭建分布式系统的时候,要保证每个都是稳定的,不然你的可用性就没有得到相对应的保证,也谈不上是什么分布式了。只能称之为一个伪分布式。

:2

:3

Array可以包含不同的数据类型,比如一个有4个整型和一个批量字符串组成的Array编码为:(为了直观,以换行的形式展现)

行 5

为了表示后面还有5个回复,然后再读取后面的5个数组元素。

值为NULL的数组也存在(通常使用NULL Bulk String,由于历史原因,NULL存在两种格式)。比如 BLPOP 超时时将会返回一个长度为-1的NULL Array: -1

在RESP中同样存在嵌套的数组,比如两个嵌套的数组编码结果为:

上面的编码结果包含两个元素的数组,个元素由(1,2,3)构成的子数组,第二个元素由一个Bulk String(+Hello)和一个Error(-World)组成的数组。

一个Array的单个元素可能为NULL。这在Redis回复中用来表示这些元素丢失而不是空字符串。当 SORT 命令使用 GET pattern 子命令并且key缺失时,将会发生这种情况。一个包含NULL元素的数组回复为:

上面的编码解析结果为:["hello", nil, "world"]

所以,一种典型的交互场景可能如下:

为了获取存储在 mylist 中的列表的长度,客户端发送命令 LLEN mylist 到,然后回复客户端一个整型回复:

protocol-spec

Redis系列篇之SPEC协议

redis什么时候要用事务

可以根据上面几部分的介绍来编写Redis客户端,同时进一步了解客户端和之间的交互是如何工作的。

Redis事务使用总结:

Redis的事务机制允许同时执行多条指令,它是原子性作,事务中的命令要么全部执行,要么全部不执行,另外,事务中的所有指令都会被序列化,而且其开始执行过程中,不回被即时过来的指令所打断,其需要经历三个过程,分别为开始事务、命令入队以及执行事务。

· 相关命令

· 遇到问题

· 例子演示

一、相关命令

1、MULTI

该命令用来开启事务,它总是返回ok结果,当其执行之后,客户端可以继续发送任意条数量的指令,这些指令不会立即被执行,而是被放到了队列中,直到EXEC被调用之后,所有命令才会被序列化执行。

2、EXEC

该命令负责触发并执行队列中所有的命令。

NOTE:

如果MULTI开启之后,因为某些原因没有成功执行EXEC,那么事务中所有的命令都不会被执行的。

3、DISCARD

该命令用来刷新事务中所有排队等待执行的指令,它总是返回ok结果,并且将服务连接状态恢复到正常。如果已经使用WATCH,那么其会将释放所有被WATCH的key。

4、WATCH

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

NOTE:

A、WATCH使得EXEC命令需要有条件的执行,也就是事务只能在所有被监视的键没有被修改的前提下才能执行。另外,在EXEC被执行之后,所有的WATCH都会被取消。

B、UNWATCH手动取消对所有键的WATCH,如果执行了EXEC或者DISCARD,则不需要手动执行UNWATCH命令。

二、如何使用

Redis原生使用(Redis-cli):

127.0.0.1:6379> multi // 事务开始的动作标志下面即为入队

OK

127.0.0.1:6379> set book-name "Thinking in Ja"

QUEUED

127.0.0.1:6379> get book-name

QUEUED

127.0.0.1:6379> sadd tag "ja" "Programming""Thinking"

QUEUED

127.0.0.1:6379> embers tag

QUEUED

127.0.0.1:6379> exec // 执行事4,重新分配slot务

1) OK

2) "Thinking in Ja"

3) (integer) 3

4) 1) "Thinking"

3) "ja"

127.0.0.1:6379> discard // 事务已执行完毕 已经自动取消

(error) ERR DISCARD without MULTI

127.0.0.1:6379> multi

OK

127结果:.0.0.1:6379> set book-name "Patterns in Ja"

QUEUED

127.0.0.1:6379> get book-name

QUEUED

QUEUED

127.0.0.1:6379> embers tag

QUEUED

127.0.0.1:6379> discard // 事务未执行 可以刷新队列指令状态 取消执行

OK

127.0.0.1:6379> exec // 事务已经被取消不能再执行

(error) ERR EXEC without MULTI

三、脚本事务

Redis 2.6开始支持了脚本,而该脚本本身就是一种事务机制,所以任何在事务里可以完成的事,在脚本里面也能完成,并且使用脚本更简单些,并且速度也更快。不过因为事务提供了一种即使不使用脚本,也可以避免竞争条件的方法,并且事务本身的实现并不复杂,所以现在的使用也比较多,但不排除日后可能被替代或是占据主要地位的可能。

NOTE:

Redis为什么引入两种处理事务的方式?脚本功能是 Redis 2.6 才引入的,而事务功能则在更早之前就存在,所以 Redis 才会同时存在两种处理事务的方法。另外,事务脚本会在后续文章中总结介绍。

四、遇到问题

举个例子,设我们需要原子性为某个键加1作(设INCR不存在),那么应该是这样的执行语句:

val = GET mykey

val = val + 1

SET mykey ${val}

单个客户端访问作没有任何问题,如果是多个客户端同时访问mykey,就会产生资源共享访问问题,比如:现在有个两个客户端访问同一个键mykey,那么mykey的可能是2,但是我们期望的值应该是3才对,这个类似于高并发下的sync锁机制,所以我们需要使用WATCH来被共享的键mykey,如下:

WATCH mykey(可多个键)

val = GET mykey

val = val + 1

MULTI

SET mykey ${val}

EXEC

NOTE:

虽然大多情况下,多个客户端访问作同一个键的情况很少或没有,但是不能排除这个特殊情况,所以建议在有可能产生键共享的指令中使用WATCH在EXEC执行前对其监管。

2、Redis不支持回滚(Roll Back)

Redis的事务不支持回滚,这点不同于关系数据库中的事务,所以它的内部保持了简单且快速的特点。另外,Redis不支持回滚是这样考虑的:Redis事务中命令之所以会失败,是由于错误的编程所造成,通过事务回滚是不能回避这个根本问题。

NOTE:

Redis事务中命令执行失败,仍会继续执行后面的执行,在没有特殊干预前提下,直到执行完队列中所有指令为止。

3、使用事务可能遇到的问题

A、事务在执行 EXEC 之前,入队的命令可能会出错,举个例子:命令可能会产生语法错误(参数数量错误,参数名错误等),或者其他更的错误,比如内存不足(如果使用maxmemory 设置了内存限制的话)。

B、事务在执行 EXEC 之前,举个例子:事务中的命令可能处理了错误类型的键,比如将列表命令用在了字符串键上面等。

对于发生在 EXEC 执行之前的错误,客户端以前的做法是检查命令入队所得的返回值:如果命令入队时返回QUEUED ,那么入队成功;否则,就是入队失败。如果有命令在入队时失败,那么大部分客户端都会停止并取消这个事务。

从 Redis 2.6.5 开始,会对命令入队失败的情况进行记录,并在客户端调用 EXEC 命令时,拒绝执行并自动放弃这个事务。

在 Redis 2.6.5 以前, Redis 只执行事务中那些入队成功的命令,而忽略那些入队失败的命令。而新的处理方式则使得在管道技术中包含事务变得简单,因为发送事务和读取事务的回复都只需要和进行一次通讯即可。

至于那些在 EXEC 命令执行之后所产生的错误,并没有对它们进行特别处理: 即使事务中有某个/某些命令在执行时产生了错误, 事务中的其他命令仍然会继续执行。

五、例子演示

$redis = new Redis();

$redis->connect('127.0.0.1',6379);

$result = array();

// 开启事务

$redis->multi();

// 添加指令到队列

$redis->set('book-name','Thinking in PHP!');

$redis->sAdd('tags','PHP','Programming','Thinking');

$bookname = $redis->get('book-name');

$tags = $redis->sMembers('tags');

// 执行事务

$redis->exec();

// 显示结果

echo '书名:'.$bookname.' 标签:'.$tags;

redis都支持哪些语言,ja,php以外还有吗?支持Android,C#吗?对于Android怎么用?

· 如何使用

Ja连接redis的使用示例

· 如何使用

Redis是开源的key-value存储工具,redis通常用来存储结构化的数据,因为redis的key可以包含String、hash、listset和sorted list。

// 用完一定要释放连接

Redisclient支持多种语言,包括:c、C++、C#、php、ja、python、go等语言,根据自己的开发语言,选择合适的redis client版本类型即可。我是使用ja语言开发的,针对ja语言,redis client也提供了多种客户端支持,按照类型依次是:Jedis、Redisson、JRedis、JDBC-Redis、RJC、redis-protocol、aredis、lettuce。前两种类型是比较的,我们采用了Redisson类型版本作为redisclient的使用。

Redisson版的redis可发工程搭建

1. 新建men工程

2. 在pom.xml文件的dependencies下增加如下内容:

org.redisson

redisson

1.0.2

org.slf4j

slf4j-log4j12

1.7.7

3. 保存pom.xml后,等eclispe工程构建完成后即可进行开发了

开发示例

下面是演示连接redis、保存读取concurrentMap对象、保存读取set对象和保存读取Queue对象的示例代码,代码比较简单,这里就不再详细讲解了,代码如下:

[ja] view plaincopy

package com.my.test.redis;

import ja.util.Queue;

import ja.util.Set;

import ja.util.concurrent.ConcurrentMap;

import org.redisson.Config;

import org.redisson.Redisson;

public class RedisExample {

/

@param args

/

public static void main(String[] args) {

// 1.初始化

config.setConnectionPoolSize(10);

config.addAddress("127.0.0.1:6379");

Redisson redisson = Redisson.create(config);

System.out.println("reids连接成功...");

// 2.测试concurrentMap,put方法的时候就会同步到redis中

map.put("wuguowei", "男");

map.put("zhangsan", "nan");

map.put("lisi", "女");

ConcurrentMap resultMap = redisson.getMap("FirstMap");

System.out.println("resultMap==" + resultMap.keySet());

// 2.测试Set

Set mySet = redisson.getSet("MySet");

mySet.add("wuguowei");

mySet.add("lisi");

Set resultSet = redisson.getSet("MySet");

System.out.println("resultSet===" + resultSet.size());

//3.测试Queue队列

Queue myQueue = redisson.getQueue("FirstQueue");

myQueue.add("wuguowei");

myQueue.add("zhangsan");

myQueue.peek();

myQueue.poll();

Queue resultQueue=redisson.getQueue("FirstQueue");

// 关闭连接

redisson.shutdown();

Redis怎么实现分布式锁

一个数据库只拥有有限的资源,并且如果你没有充分使用这些资源,你可以通过使用更多的连接来提高吞吐量。一旦所有的资源都在使用,那么你就不 能通过增加更多的连接来提高吞吐量。事实上,吞吐量在连接负载较大时就开始下降了。通常可以通过限制与可用的资源相匹配的数据库连接的数量来提高延迟和吞 吐量。

阿粉最近迷上了 Redis,为什么呢?感觉 Redis 确实功能很强大呀,一个基于内存的系统 Key-Value 存储的数据库,竟然有这么多的功能,而阿粉也要实实在在地把 Redis 来弄一下,毕竟面试的时候,Redis 可以说是一个非常不错的加分项。

2) "Programming"

为什么需要分布式锁?

目前很多的大型项目全部都是基于分布式的,而分布式场景中的数据一致性问题一直是一个不可忽视的问题,大家知道关于分布式的 CAP 理论么?

CAP 理论就是说任何一个分布式系统都无法同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance),最多只能同时满足两结果:项。

而我们的系统最终满足的永远都是最终一致性,而这种最终一致性,有些时候有人会喜欢问关于分布式事务,而有些人则偏重在分布式锁上。

但是阿粉选择的就是使用缓存来实现分布式锁,也就是我们在项目中最经常使用的 Redis ,谈到 Redis,那真是可以用在太多地方了,比如说:

我们今天就来实现用 Redis 来实现分布式锁,并且要学会怎么使用。

1.准备使用 Jedis 的 jar 包,在项目中导入 jar 包。

jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime); 这个加锁的姿势才是我们最需要了解的,不然你用的时候都不知道怎么使用。

key:加锁的键,实际上就是相当于一个的标志位,不同的业务,你可以使用不同的标志位进行加锁。

requestId:这个东西实际上就是用来标识他是哪一个请求进行的加锁,因为在分布式锁中,我们要知道一件事,就是加锁的和解锁的,必须是同一个客户端才可以。

而且还有一种比较经典的就是 B 把 A 的锁给释放了,导致释放混乱,如果你不加相同的请求,A 线程处理业务,执行了加锁,锁的过期时间是5s, B线程尝试获取锁,如果 A 处理业务时间超过5s,这时候 A 就要开始释放锁,而B在这时候没有检测到这个锁,从而进行了加锁,这时候加锁的时候,A还没处理完对应业务,当他处理完了之后,再释放锁的话,要是就是直接把 B 刚加的锁释放了,要么就是压根都没办法释放锁。

SET_IF_NOT_EXIST:看字面意思,如果 key 不存在,我们进行Set作,如果存在,啥都不干,也就不在进行加锁。

SET_WITH_EXPIRE_TIME:是否过期

expireTime:这是给 key 设置一个过期的时间,万一你这业务一直被锁着了,然后之后的业务想加锁,你直接给一直持有这个这个锁,不进行过期之后的释放,那岂不是要凉了。

上面的方法中 tryGetDistributedLock 这个方法也就是我们通常使用的加锁的方法。

大家看到这个 script 的时候,会感觉有点奇怪,实际上他就是一个 Lua 的脚本,而 Lua 脚本的意思也比较简单。

其实这时候就有些人说,直接 del 删除不行么?你试试你如果这么写的话,你们的会不会把你的腿给你打断。

在这里给大家放一段使用的代码,比较简单,但是可以直接用到你们的项目当中

我们先把这个实现方式实现了,然后我们再来说说大家最不愿意看的理论知识,毕竟这理论知识是你面试的时候经常会被问到的。

分布式CAP理论:

加州大学伯克利分校的 Eric Brewer 在 ACM PODC 会议上提出 CAP 猜想。2年后,麻省理工学院的 S Gilbert 和 Nancy Lynch 从理论上证明了 CAP。之后,CAP 理论正式成为分布式计算领域的公认定理。

也就是说,在二十年前的时候,CAP 理论只是个猜想。结果两年之后被证实了,于是,大家在考虑分布式的时候,就有根据来想了,不再是空想了。

什么是分布式的 CAP 理论 ?

一个分布式系统最多只能同时满足一致性(Consistency)、可用性(Availability)和分区容错性(Partition tolerance)这三项中的两项

这个和(Atomicity)不太一样,因为之前看有些人说,在 CAP 理论中的 A 和数据库事务中的 A 是一样的,单词都不一样,那能一样么?

Availability :分布式中的 A 表示的是可用性,也就是说服务一直可用,而且是正常响应时间。

Consistency: 一致性

也就是说你的更新作成功并返回客户端完成后,所有在同一时间的数据完全一致,这个如果你在使用 Redis 做数据展示的时候,很多面试官都会问你,那你们是怎么保证数据库和缓存的一致性的呢?

毕竟你只是读取的话,没什么问题,但是设计到更新的时候,不管是先写数据库,再删除缓存;还是先删除缓存,再写库,都有可能出现数据不一致的情况。

所以如果你对这个很感兴趣,可以研究一下,比如说:

Partition tolerance:分区容错性

分布式系统在遇到某或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。

其实在 CAP 理论当中,我们是没有办法同时满足一致性、可用性和分区容错性这三个特性,所以有所取舍就可以了。

关于使用 Redis 分布式锁,大家学会了么?

redis cluster命令cluster nodes怎么用

如果不使用连接池,那么,每次传输数据,我们都需要进行创建连接,收发数据,关闭连接。在并发量不高的场景,基本上不会有什么问题,一旦并发量上去了,那么,一般就会遇到下面几个常见问题:

redis cluster配置好,并运行一段时间后,我们想添加,或者删除,该怎么办呢。

一,redis cluster命令行

查看打印?

//集群(cluster)

CLUSTER INFO 打印集群的信息

CLUSTER NODES 列出集群当前已知的所有(node),以及这些的相关信息。

//(node)

CLUSTER MEET

将 ip 和 port 所指定的添加到集群当中,让它成为集群的一份子。

CLUSTER FORGET 从集群中移除 node_id 指定的。

CLUSTER SAVECONFIG 将的配置文件保存到硬盘里面。

//槽(slot)

CLUSTER ADDSLOTS [slot ...] 将一个或多个槽(slot)指派(assign)给当前。

CLUSTER DELSLOTS [slot ...] 移除一Jedis jedis = null;个或多个槽对当前的指派。

CLUSTER FLUSHSLOTS 移除指派给当前的所有槽,让当前变成一个没有指派任何槽的。

CLUSTER SETSLOT NODE 将槽 slot 指派给 node_id 指定的,如果槽已经指派给另一个,那么先让另一个删除该槽>,然后再进行指派。

CLUSTER SETSLOT MIGRATING 将本的槽 slot 迁移到 node_id 指定的中。

CLUSTER SETSLOT IMPORTING 从 node_id 指定的中导入槽 slot 到本。

CLUSTER SETSLOT STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。

//键 (key)

CLUSTER KEYSLOT 计算键 key 应该被放置在哪个槽上。

CLUSTER COUNTKEYSINSLOT 返回槽 slot 目前包含的键值对数量。

这些命令是集群所的。执行上述命令要先登录

查看打印?

[root@ma redis]# redis-cli -c -p 6382 -h 192.168.10.220 //登录

192.168.10.220:6382> cluster //查看集群情况

cluster_state:ok

cluster_slots_ok:16384

cluster_slots_pfail:0

cluster_slots_fail:0

cluster_known_nodes:6

cluster_size:3

cluster_current_epoch:8

cluster_my_epoch:4

cluster_stats_messages_sent:82753

cluster_stats_messages_received:82754

二,添加

1,新配置二个测试

查看打印?

# cd /etc/redis

//新增配置

# cp redis-6379.conf redis-6378.conf && sed -i "s/6379/6378/g" redis-6378.conf

# cp redis-6382.conf redis-6385.conf && sed -i "s/6382/6385/g" redis-6385.conf

//启动

# redis-server /etc/redis/redis-6385.conf > /var/log/redis/redis-6385.log 2>&1 &

# redis-server /etc/redis/redis-6378.conf > /var/log/redis/redis-6378.log 2>&1 &

2,添加主

# redis-trib.rb add-node 192.168.10.219:6378 192.168.10.219:6379

注释:

192.168.10.219:6378是新增的

192.168.10.219:6379集群任一个旧

3,添加从

# redis-trib.rb add-node --sle ---id 03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.10.220:6385 192.168.10.219:6379

注释:

--CLUSTER GETKEYSINSLOT 返回 count 个 slot 槽中的键。sle,表示添加的是从

---id 03ccad2ba5dd1e062464bc7590400441fafb63f2,主的node id,在这里是前面新添加的6378的node id

192.168.10.220:6385,新

192.168.10.219:6379集群任一个旧

查看打印?

# redis-trib.rb reshard 192.168.10.219:6378 //下面是主要过程

How many slots do you want to move (from 1 to 16384)? 1000 //设置slot数1000

What is the receiving node ID? 03ccad2ba5dd1e062464bc7590400441fafb63f2 //新node id

Please enter all the source node IDs.

Type 'done' once you entered all the source nodes IDs.

Source node #1:all //表示全部重新洗牌

Do you want to proceed with the proed reshard plan (yes/no)? yes //确认重新分

新增加的主,是没有slots的,

如何利用redis从数据库读出数据

127.0.0.1:6379> sadd tag "Ja" "Thinking""Programming"

应用Redis实现数据的读写Type 'all' to use all the nodes as source nodes for the hash slots.,同时利用队列处理器定时将数据写入mysql。同时要注意避免冲突,在recluster_slots_assigned:16384dis启动时去mysql读取所有表键值存入redis中,往redis写数据时,对redis主键自增并进行读取,若mysql更新失败,则需要及时清除缓存及同步redis主键。这样处理,主要是实时读写redis,而mysql数据则通过队列异步处理,缓解mysql压力,不过这种方法应用场景主要基于高并发,而且redis的高可用集群架构相对更复杂,一般不是很。

thinkphp5模型如何使用redis作数据库CURD作

Radix.v2 包是根据功能划分成一个个的 sub package,每一个 sub package 在一个的子目录中,结构非常清晰。我的项目中会用到的 sub package 有 redis 和 pool。

模型中添加如下代码,可实现更新或插入前删除缓存:

protected static function iniConcurrentMap map = redisson.getMap("FirstMap");t()

{TurnGiftSetting::beforeInsert(function ($model) {

$redis = new Redis(config('redis'));

$redis->rm(self::$redisKey);

});System.out.println("resultQueue==="+resultQueue);

TurnGiftSetting::beforeUpdate(function ($model) {

$redis = new Redis(config('redis'));

$redis->rm(self::$redisKey);

});

TurnGiftSetting::beforeDelete(function ($model) {

$redis = new Redis(config('redis'));

$redis->rm(self::$redisKey);

});

TurnGiftSetting::beforeWrite(function ($model) {

$redis = new Redis(config('redis'));

$redis->rm(self::$redisKey);

});

}

Redis是什么,用来做什么

这种不先判断锁的拥有者而直接解锁的方式,会导致任何客户端都可以随时进行解锁,也就是说,这锁就算不是我加的,我都能开,这怎么能行呢?

可基于内存亦可持久化的日志型、

如果你能在面试的时候把这些都给面试官说清楚,至少感觉你应该能达到你自己的工资要求。

Key-Value数据库,并提供多种语言的API。

其中,Radix.v2 连接池内部进行了连接池内连接的获取和放回,代码如下:

redis是将数据存储在内存中的高速缓存,key-value类型的,nosql数据库。用来分担数据库的I/O压力,提高数据访问速度。

具体可以查看

Redis是由意大利人Salvatore Sanfilippo(网名:antirez)开发的一款内存高速缓存数据库。Redis全称为:Remote Dictionary (远程数据服务),该软件使用C语言编写,Redis是一个key-value存储系统,它支持丰富的数据类型,如:string、list、set、zset(sorted set)、hash。

众多语言都支持Redis,因为Redis交换数据快,在中常用来存储一些需要频繁调取的数据,节省内存开销,也提升了速度。将一些热点数据存储到Redis中,要用的时候,直接从内存取,提高了速度和节约了的开销。

1、会话缓存(最常用)

2、消息队列(支付)

3、活动排行榜或计数

4、发布,消息(消息通知)

5、商品列表,评论列表

拉格朗日前哨站的作用 拉格朗日前哨站建造速

腐烂国度2巨霸版全效果前哨站资料汇总 3、玩家下一步使用自己的艇摧毁防御驱逐舰就可以了。 腐烂国度2巨霸版全效果前哨站资料汇总。不少玩家可能还不太清楚25.0版本中的效果前哨站有什么作···

河北养殖负压风机哪里有 专业生产养殖负压风

今天源源来给大家分享一些关于专业生产养殖负压风机厂家方面的知识吧,希望大家会喜欢哦 河北养殖负压风机哪里有 专业生产养殖负压风机厂家 河北养殖负压风机哪里有 专业生产养殖负压风机···

卫星转发器增益 卫星转发器的各种模型

大家好,今日小栢来为大家解答以上的问题。卫星转发器增益,卫星转发器的各种模型很多人还不知道,现在让我们一起来看看吧! 卫星转发器增益 卫星转发器的各种模型 卫星转发器增益 卫星转···