edis

阅读 / 问答 / 标签

redis高可用实践之FAILOVER

服务的可用性不仅仅是指服务健康运行的时间,还包括出现故障以后的恢复速度。保证一个服务的高可用,基本可以从 软件质量 故障预防 故障恢复三方面着手。对于redis,软件的质量本身有很大的保障,因此对于线上大规模的redis集群运维管理,基本上可以从故障预防和故障恢复两方面着。虽然redis cluster本身具有自动主从容灾的高可用能力,但是某些场景cluster依然无法很好地处理。本文将结合CLUSTER FAILOVER 集群管理命令详细介绍如何进一步提升redis集群的可用性。 首先对CLUSTER FAILOVER命令做个介绍: CLUSTER FAILOVER处理流程 该操作用于正常的主从切换,但是如果master节点宕机了无法响应failover请求,那么failover将会失败,为了处理master宕机的情况,可以添加FORCE 选项。 CLUSTER FAILOVER FORCE: 添加FORCE选项时,failover流程直接从上述的第4步开始,也即跳过了和旧master通信协商复制数据的过程,当master宕机时,force选项可以快速进行人工主从切换。但是该过程仍然需要获得半数master的统=同意才能当选为新主。当出现半数master节点异常时,该流程无法进行主从切换。 CLUSTER FAILOVER TAKEOVER: 为了处理半数master节点异常的场景,可以添加****TAKEOVER 选项。通过TAKEOVER 选项,可以无需获得半数master的认同,而是直接更新状态为master并向所有可达的节点发送最新配置epoch。**** 接下来将结合场景介绍如何通过FAILOVER 提升集群可用性 防患以未然,当机器负载过高或者出现异常故障时,需要将部署在该机器的redis实例迁移出,迁移流程包含: 如果旧机器有实例处于master,则需要先将role改外slave,然后在进行迁移,此时可以通过对slave节点发送cluster failover,将节点改为slave以后在进行删除。 最理想的情况是出现故障之前提前解决处理,但是这毕竟只是理想。当节点宕机或者负载过高导致无法响应时,可能出现FAILOVER失败的情况,此时则可以通过添加FORCE选项进行强制主从切换,将健康的slave节点提升为master从而快速恢复服务。 虽然在线上环境的部署上,redis的master节点会做到尽可能分散,但是在某些场景写,还是可能出现半数master节点故障的情况: 虽然redis cluster本身提供了高可用的能力,但是在某些场景下依然需要人为介入进行处理,本文介绍了FAILOVER的几种应用实践场景,通过将该操作和option集成到自动运维平台,进一步提升了redis的可用性。

如何判断 redis 连接是否有效

命令行内直接连接试试就知道了

decideontheissuetodiscuss还是tobediscussed

接todiscuss就可以。这个题考的是discuss的用法,作为动词的时候,decideontheissuetodiscuss这个是决定要讨论的问题,tobediscussed是被动词,一般都用于被动句子里面的。而这句话就是主动形式的,决定要讨论这个问题,不是决定被讨论这个问题。discussvi也有不及物有的词典表示与about和with连用。disscuss的用法在朗文里的例句是discusssthwithsb。而且一般是discusshowtodo/whattodo。如果是todiscuss就是要论,有待讨论了,也不可能接tobediscussed的。

redis需要设置过期时间吗

一般是根据需求来进行设置。redis通过expire命令来设置key的过期时间。语法:redis.expire(key, expiration)1. 在小于2.1.3的redis版本里,只能对key设置一次expire。redis2.1.3和之后的版本里,可以多次对key使用expire命令,更新key的expire time。2. redis术语里面,把设置了expire time的key 叫做:volatile keys。 意思就是不稳定的key。3. 如果对key使用set或del命令,那么也会移除expire time。尤其是set命令,这个在编写程序的时候需要注意一下。4. redis2.1.3之前的老版本里,如果对volatile keys 做相关写入操作(LPUSH,LSET),和其他一些触发修改value的操作时,redis会删除该key。 也就是说 :redis.expire(key,expiration);redis.lpush(key,field,value);redis.get(key) //return nullredis2.1.3之后的版本里面没有这个约束,可以任意修改。redis.set(key,100);redis.expire(key,expiration);redis.incr(key)redis.get(key)//redis2.2.2 return 101; redis<2.1.3 return 1;5. redis对过期键采用了lazy expiration:在访问key的时候判定key是否过期,如果过期,则进行过期处理。其次,每秒对volatile keys 进行抽样测试,如果有过期键,那么对所有过期key进行处理。

redis keys* 用java代码怎么写

代码如下:local food=redis.call("hget",KEYS[1],"food");food=food+ARGV[1];redis.call("hset",KEYS[1],"food",food);local diamond=redis.call("hget",KEYS[1],"diamond");diamond=diamond+ARGV[2];redis.call("hset",KEYS[1],"diamond",diamond);

redis需要设置过期时间吗

一般是根据需求来进行设置。redis通过expire命令来设置key的过期时间。语法:redis.expire(key, expiration)1. 在小于2.1.3的redis版本里,只能对key设置一次expire。redis2.1.3和之后的版本里,可以多次对key使用expire命令,更新key的expire time。2. redis术语里面,把设置了expire time的key 叫做:volatile keys。 意思就是不稳定的key。3. 如果对key使用set或del命令,那么也会移除expire time。尤其是set命令,这个在编写程序的时候需要注意一下。4. redis2.1.3之前的老版本里,如果对volatile keys 做相关写入操作(LPUSH,LSET),和其他一些触发修改value的操作时,redis会删除该key。 也就是说 :redis.expire(key,expiration);redis.lpush(key,field,value);redis.get(key) //return nullredis2.1.3之后的版本里面没有这个约束,可以任意修改。redis.set(key,100);redis.expire(key,expiration);redis.incr(key)redis.get(key)//redis2.2.2 return 101; redis<2.1.3 return 1;5. redis对过期键采用了lazy expiration:在访问key的时候判定key是否过期,如果过期,则进行过期处理。其次,每秒对volatile keys 进行抽样测试,如果有过期键,那么对所有过期key进行处理。

如何批量删除Redis下特定pattern的keys?

ShawKun,红灯硬闯,马路横穿可以使用linux的xargs来做到 如:*/redis-cli keys "prefix*" | xargs */redis-cli del 如果是访问特定的数据库,则可以:*/redis-cli -n 0 keys "prefix*" | xargs */redis-cli -n 0 del

redis 的keys 是什么意思

redis是以key=>value 形式来存储数据的, 可以理解成数组的 键 和 值的关系;

SpringBoot整合Redisson

Redisson的Github地址: https://github.com/redisson/redisson/wiki/Table-of-Content 基于Redis的Redisson分布式可重入锁RLock对象实现了java.util.concurrent.locks.Lock接口。 大家都知道,如果负责储存这个分布式锁的Redisson节点宕机以后,而且这个锁正好处于锁住的状态时,这个锁会出现锁死的状态。为了避免这种情况的发生,Redisson内部提供了一个 监控锁的看门狗 ,它的作用是在Redisson实例被关闭前,不断的延长锁的有效期。默认情况下,看门狗的检查锁的超时时间是30秒钟,也可以通过修改Config.lockWatchdogTimeout来另行指定。 在RedissonLock类的renewExpiration()方法中,会启动一个定时任务每隔30/3=10秒给锁续期。如果业务执行期间,应用挂了,那么不会自动续期,到过期时间之后,锁会自动释放。 另外Redisson还提供了leaseTime的参数来指定加锁的时间。超过这个时间后锁便自动解开了。 如果指定了锁的超时时间,底层直接调用lua脚本,进行占锁。如果超过leaseTime,业务逻辑还没有执行完成,则直接释放锁,所以在指定leaseTime时,要让leaseTime大于业务执行时间。RedissonLock类的tryLockInnerAsync()方法 分布式可重入读写锁允许同时有多个读锁和一个写锁处于加锁状态。在读写锁中,读读共享、读写互斥、写写互斥。 读写锁测试类,当访问write接口时,read接口会被阻塞住。 Redisson的分布式信号量与的用法与java.util.concurrent.Semaphore相似 现在redis中保存semaphore的值为3 然后在TestController中添加测试方法: 当访问acquireSemaphore接口时,redis中的semaphore会减1;访问releaseSemaphore接口时,redis中的semaphore会加1。当redis中的semaphore为0时,继续访问acquireSemaphore接口,会被阻塞,直到访问releaseSemaphore接口,使得semaphore>0,acquireSemaphore才会继续执行。 CountDownLatch作用:某一线程,等待其他线程执行完毕之后,自己再继续执行。 在TestController中添加测试方法,访问close接口时,调用await()方法进入阻塞状态,直到有三次访问release接口时,close接口才会返回。

redis网络丢包怎么解决

redis 常见问题与处理方法1.VIP:port 提供服务:唯一标记一个redis实例的是ip和端口,前端是用tcp方式来访问redis的,我们提供给应用访问的是一个vip+63379(一般使用63379) 端口,,vip一定是在master上面的.因此我们执行如下命令检查redis状态:[wls81@CNSH044446 ~]$ /wls/wls81/redis/bin/redis-cli -h {vip} -p 63379 -a {password} info replication# Replicationrole:masterconnected_slaves:1slave0:ip=10.11.93.12,port=63379,state=online,offset=146649,lag=1master_repl_offset:146649repl_backlog_active:1repl_backlog_size:1048576repl_backlog_first_byte_offset:2repl_backlog_histlen:146648上面的role这个值一定是master的,只要保证vip在master上我们的Padis cache服务就是没有问题的,如果不通或者role的角色是slave

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 中,第一个字节决定了数据类型: 在 RESP 中,协议不同部分总是以 (CRLF)结尾。 RESP 使用特殊的组合表示空的Bulk Strings或者空的Arrays: $-1 表示空的Bulk Strings, *-1 表示空的Arrays,需要注意的是: $0 与 *0 分别表示有回复,但长度为0。 Simple Strings(简单字符串)的编码方式为:一个 + 号在最前面,后面跟着一个不能包含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 如你所见, *<count>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"] 可以根据上面几部分的介绍来编写Redis客户端,同时进一步了解客户端和服务器之间的交互是如何工作的。 所以,一种典型的交互场景可能如下: 为了获取存储在 mylist 中的列表的长度,客户端发送命令 LLEN mylist 到服务器,然后服务器回复客户端一个整型回复: protocol-spec Redis系列第一篇之SPEC协议

E-prime编程问题,编好的程序运行后出现“Filename on ImageDisplay has not been set"

请问怎么在list里导入图片啊 file name应该写什么啊

Redis 实战 —— 10. 实现内容搜索、定向广告和职位搜索

通过改变程序搜索数据的方式,并使用 Redis 来减少绝大部分基于单词或者关键字进行的内容搜索操作的执行时间。 P154 倒排索引 (inverted indexes) 是互联网上绝大部分搜索引擎使用的底层结构,它类似于书本末尾的索引。倒排索引从每个被索引的文档里面提取一些单词,并记录包含每个单词的文档集合。 P154 示例 假设有三个文档: 我们就能得到下面的倒排索引集合: 检索的条件 "what", "is" 和 "it" 将对应这个集合: {0,1} ∩ {0,1,2} ∩ {0,1,2} = {0,1} 可以发现 Redis 的集合和有序集合非常适合处理倒排索引。 基本索引操作 从文档里面提取单词的过程通常被成为语法分析 (parsing) 和标记化 (tokenization) ,这个过程可以产生一系列用于表示文档的标记 (token) ,有时又被成为单词 (word) 。 P155 标记化的一个常见的附加步骤就是移除非用词 (stop word) 。非用词就是那些在文档中频繁出现却没有提供相应信息量的单词,对这些单词进行搜索将返回大量无用的结果。 P155 本书中实现方向索引的逻辑非常简单: 如果需要支持中文等,就不能简单进行英文分词,需要分词器进行处理。第一次接触倒排索引是在 Elasticsearch 中,感兴趣的可以了解 Elasticsearch 中倒排索引的实现以及 IK 中文分词器。 基本搜索操作 在索引里面查找一个单词是非常容易的,只需要获取单词集合里面的所有文档即可。根据多个单词查找文档时,就需要根据条件处理对应的集合,再从最终集合中获取所有文档。 P156 可以使用 Redis 的集合操作完成对不同条件的处理: 通过以上三类命令,我们基本能实现条件大部分的与或非操作。 分析并执行搜索 我们使用的查询语句进行分词后具有以下特征: 即: "connect +connection chat -proxy -proxies" 表示查询的文档需要包含 "connect" 或 "connection" ,同时也要包含 "chat" ,并且不能包含 "proxy" 和 "proxies" 。 实际处理时,先对同义词组分别取并集,然后与需要查询的单词一起取交集,最后与不希望包含的单词取差集,这样所得到的集合就是用户查询的结果集。 上述搜索功能以及能够搜索出用户查询的所有文档唯一标识的集合,现在我们将根据这个文档唯一标识集合以及每个文档的具体信息进行排序分页。 对于这种情况我们可以使用 Redis 的 SORT 命令对文档唯一标识集合通过引用每个文档的具体信息进行排序分页。 ( 05. Redis 其他命令简介 ) 上面介绍了使用 Redis 进行搜索,并通过引用存储在 HASH 里面的数据对搜索结果进行排序分页。接下来将介绍利用集合和有序集合实现基于多个分值的复合排序操作,它能提供比 SORT 命令更高的灵活性。 P162 假设我们目前需要根据文档对更新时间和得票数进行排序,为此我们需要用两个有序集合存储相关信息。这两个有序集合的成员都是文档唯一标识,成员的分值则分别是文档的更新时间和得票数。 设经过搜索后满足搜索条件的文档唯一标识集合为 filtered_doc_ids ,文档唯一标识及其更新时间对应的有序集合为 doc_ids_with_update ,文档唯一 标识及其得票数对应的有序集合为 doc_ids_with_votes 。那么可以通过 ZINTERSTORE 命令对这三个集合求交集,最后得出的满足搜索条件的文档唯一标识及其排序分值对应的有序集合,再使用 ZRANGE , ZREVRANGE 进行分页获取即可。 P162 示例: ZINTERSTORE filtered_doc_ids_with_sort_score 3 filtered_doc_ids doc_ids_with_update doc_ids_with_votes WEIGHTS 0 {update_weight} {vote_weight} 其中: 所思 这种利用分值的方法很巧妙,基本可以实现多字段排序,但是优先级可能难以掌控,难以做到先按照某一字段排序,再按照另一字段排序的形式。因为每个字段对应的分值的数量级可能差别比较小,这个时候如果需要有排序字段的优先级,那么可能需要对每个权重进行精巧地设计才行。 上面介绍了使用有序集合对多个数值字段进行排序,由于有序集合的分值只能是浮点数,所以非数值字段不能直接用于排序,需要转换成对应的浮点数。但由于双精度浮点数只有 64 个二进制位,实际能使用 63 个二进制位,所以能表示的字符串并不多,只能使用字符串的前几个字符进行分值估计,不足指定字符数的需要补齐到指定字符数。当然如果字符集缩小的话,可以重新进行编码计算,进而可以对更长的字符串进行分值估计。 P165 当这个分值特别大的时候,可能会引发最终计算的分值溢出而出错的问题。 接下来将介绍使用集合和有序集合构建出一个几乎完整的广告服务平台 (ad-serving platform) 。 P166 针对广告的索引操作和针对其他内容的索引操作并没有太大的不同,被索引的的广告通常都拥有像位置、年龄和性别这类必需的定向参数,并且往往只会返回单个广告。 P167 广告的价格 P167 为了尽可能简化广告价格的计算方式,将对所有类型的广告进行转换,使得它们的价格可以基于每千次展示进行计算,产生出一个估算 CPM (estimated CPM, eCPM) 。 P168 将广告插入倒排索引 P169 我们基本可以复用上面提到的搜索功能,除了会将广告的关键词插入倒排索引,还会将广告的定向参数(位置、年龄和性别等)插入倒排索引中,并记录广告的类型、基本价格和 eCPM 价格。 P169 当系统收到广告定向请求的时候,它要做的就是在匹配用户定向参数的一系列广告里面,找出 eCPM 最高的那一个广告。同时,程序还会记录页面内容与广告内容的匹配程度,以及不同匹配程度对广告点击通过率的影响等统计数据。通过使用这些统计数据,广告中与页面相匹配的那些内容就会作为附加值被计入 CPC 和 CPA 的 eCPM 价格,使得那些包含了匹配内容的广告能够更多地被展示出来。 P170 计算附加值 计算附加值就是基于页面内容和广告内容两者之间匹配的单词,计算出应该给广告的 eCPM 价格加上多少增量。每个单词都有一个有序集合,成员为广告 id ,成员的分值为当前单词对这则广告的 eCPM 的附加值。 P171 在寻找合适的广告时,我们首先会过滤出匹配定位位置且至少包含一个页面单词的广告,然后通过计算附加值的方法替代搜索,以便实现每次投放价值最高的广告,并能够根据用户的行为学习。同时由于每个广告匹配的内容不同,最优方式应该是使用加权平均值来计算单词部分的附加值,但限于 Redis 本身的命令,我们最终采取 (max + min) / 2 的形式计算单词部分的附加值(max 表示所有匹配单词的最大附加值, min 表示所有匹配单词的最小附加值),采用如下命令即可: ZUNIONSTORE final_score 3 base max min WEIGHTS 1 0.5 0.5 。 从用户行为中学习 P175 首先需要存储用户的浏览记录,包括三部分:(每 100 次就主动更新一次 eCPM ) P175 其次需要存储用户的点击和动作记录,用于计算 点击通过率 = 点击量或动作次数 / 广告展示次数。(每次都更新 eCPM) P176 最后就是更新 eCPM ,包括两部分: 接下来将使用集合和有序集合实现职位搜索功能,并根据求职者拥有技能来为他们寻找合适的职位。 P180 第一反应肯定是直接对每一个求职者搜索所有的岗位,从而找到求职者合适的岗位。但这种方法效率极低(大部分岗位肯定是技能对不上的),而且无法进行性能扩展。 P181 使用类似上面提到的附加值形式,每次添加一个岗位时,在对应的技能集合中添加这个岗位的 id ( SADD idx:skill:{skill} {job_id} ),再在岗位有序集合中进行添加,成员为岗位 id ,成员的分值为所需的技能数量 ( ZADD job_required_skill_count {job_id} {required_skill_count} )。搜索的时候就先对求职者所有技能对应的集合使用 ZUNIONSTORE 操作计算每个公司匹配的技能数量 ( ZUNIONSTORE matched {n} idx:skill:{skill} ... WEIGHTS 1 ... ),然后再与岗位有序集合求交集,并让公司有序集合的权重为 -1 ( ZINTERSTORE result 2 job_required_skill_count matched WEIGHTS -1 1 ),最后获取分值为 0 的所有岗位即可完成搜索。 P181 所思 书上的这个方法比较麻烦,其实可以使用文章最开始的无序倒排索引,岗位相当于要搜索的文档,岗位所需的技能相当于单词。

java如何计算redis的QPS?

qps表示每秒查询率,是一台服务器每秒能够响应的查询次数。只要知道服务器台数和指定时间内的查询次数,就可以计算了。

redis qps 是什么意思

输入redis的服务命令启动redis(redis-server.exe)。这样的话redis就会一直在命令提示行中运行,当关闭了cmd命令提示行的时候redis-server也相应的被关闭了。

c#怎么操作redis geo

1、首先确保虚拟机redis安装功并单独虚拟机进行set get存取值 2、本机连接虚拟机redis确保虚拟机redis 6379外打启iptables  modprobe ip_tables iptables -A INPUT -p tcp -i eth0 --dport 6379 -j ACCEPT没iptables 先进行安装升级 apt-getsudo apt-get install iptables3、windows安装phpredis模块 (注本用php5.3 并且扩展vc9编译)

redis-benchmark是属于什么可执行文件

redis-benchmark、redis-cli、redis-server、redis-stat。Redis由四个可执行文件:redis-benchmark、redis-cli、redis-server、redis-stat这四个文件,加上一个redis.conf就构成了整个redis的最终可用包。文件是指形成的正式文书,分为公文、文书、函件和其他文件。

魔兽中有哪些秘籍命令啊?比如输如greedisgood 就可以加钱

iseedeadpeople 地图全亮whosyourdaddy 无敌

varnish和redis的区别

SQUID 是功能最全面的,但是架构太老,性能不咋的Varnish 是内存缓存,速度一流,但是内存缓存也限制了其容量,缓存页面和图片一般是挺好的Nginx 本来是反向代理/web服务器,用了插件可以做做这个副业,但是本身不支持特性挺多ATS 目前是一个不错的选择!

谁能告诉我韩国娱乐公司MNET,SM,JYP,CUBE,PLEDIS,DSP的公司地址?不是网址!

你蹲点怎么样了

morediscussion可以加s吗

可以。morediscussion是一个单词,它的复数形式应该是morediscussions。复数形式的构成通常会在词尾加上s。morediscussion翻译为更多讨论。

Ledisi的《Bravo》 歌词

《Bravo》歌手:Ledisi发行时间:2014-01-13所属专辑:《Pieces Of Me》I"ve got a new walkAnd a new point of viewA new purpose for everything I do.I got a new rule on me.Real folks around me.If you"re wondering I"m about to tell you now.See, it"s the same pretty face, but a brand new smile.Same Ledisi, but she ain"t walking. She"s flying.New game. Making big moves.You see if love found me it can surely find you.I ain"t even got one sad tear left in me.All I really want to is to see the whole world stand up tonight.Take off aye.Celebrate life.It don"t matter who you are (or where you from)If you been working hard,give yourself a round of applause.Bravo. Bravo. Bravo. Come on clap for yourself.Bravo. Bravo. Bravo. Yeah. YeahThere ain"t a wrong time.Or a wrong place to flaunt.If you feel good then go on and show it off.They can say what they wanna.Just let em try.I don"t listen. Baby, lemme tell you why.See, it"s the same pretty woman with the brand new smile.Same Ledisi. But she ain"t walking, she"s flying.New game. Making big moves.You see if love found me it can surely find you.I ain"t even got one sad tear left in me.All I really want is to see the whole world stand up tonight.Take off aye.Yeah, we celebrating life.It don"t matter who you are (or where you from)If you been working hard,give yourself a round of applause.Bravo. Bravo. Bravo. Come on clap for yourself.Bravo. Bravo. Bravo. Yeah. Yeah.So, ladies put your best dress on.Get your hair done.Do it real big. It"s a celebration.Fellas, come on.Everyone.Lemme hear you clap now if this is your one.I ain"t even got one sad tear left in me.All I want is to see the whole world stand up tonight.Take off aye.We celebrating life.It don"t matter who you are (or where you from)If you been working hard,give yourself a round of applause.Bravo. Bravo. Bravo. Come on clap for yourself.Bravo. Bravo. Bravo. Yeah. Yeah.Bravo. Bravo. BravoBravo. Bravo. BravoLedisi的其他热歌01I Miss You Now02I Blame You03Pieces Of Me04The Rain05Alright06Ain"t Gonna Miss U When U"r..07Alone08The One09We Are One10Coffee

DaveEdison人物简介

DaveEdisonDaveEdison,剪辑师、演员,代表作品有《南方炸药桶》《三十而立》。外文名:DaveEdison职业:演员,剪辑合作人物:BobClark代表作品:《南方炸药桶》

is volvo swedish,american or chinese全文翻译

沃尔沃这牌子是瑞典的、美国的还是中国的?

Redis(四)-日志

本节主要分析下Redis日志持久化机制,包括RDB、AOF以及360开源的Pika AOF是 写后日志 ,即先写内存再记录日志;日志中记录用户的操作命令(类似mysql的binlog) 由于Redis是单线程,如果主线程处理写AOF务必会影响用户请求,因此Redis提供了三种写策略 小结 : Always 可靠性高,数据基本不丢失,但是每个命令都要写磁盘,性能影响较大; Everysec 性能适中,宕机时最多丢失1秒数据,Redis的默认策略 No 性能好,但是宕机时丢失数据较多 思考此时AOF日志机制存在什么问题? 写AOF日志的目的是为了给数据做持久化,以便宕机或重启时还原内存数据,要实现这个目标需要考虑几个问题: 触发写AOF有两种方式: 再来思考下:重写机制之后AOF日志用于重启或宕机恢复redis还存在什么问题? 要想解决这两个问题就需要引入下面的RDB,gogogo... RDB即内存快照,就是指内存中的数据在某一个时刻的状态记录(类似thread dump),把这一时刻的状态以文件的形式写到磁盘文件上,用于数据恢复; 触发RDB快照跟AOF一样,同样有两种方式: 看完AOF和RDB的方案,再继续思考下要想实现即高效又完全不丢失数据的目标,还存在哪些问题: Pika 主要解决的是用户使用 Redis 的内存大小超过 50G、80G 等等这样的情况,会遇到启动恢复时间长,一主多从代价大,硬件成本贵,缓冲区容易写满等问题。Pika 就是针对这些场景的一个解决方案。 本节分析了AOF、RDB、Pika三种缓冲方案的实现,以及各自解决了什么问题,又带来了什么问题;具体使用时还要具体分析权衡利弊,下面几点建议

Korean,Italian,Swedish这些单词分别是什么意思?

韩国的意大利的还有一个不知道

Redis | Redis 字符串相关命令

Redis 支持多种数据结构,比如 字符串、列表、集合、有序集合 和 哈希 等数据结构。本次我整理了关于 字符串 相关的命令,也就是关于 Strings 相关的命令,如下图。 上图中用红色圈中的部分,就是关于 字符串 相关的命令。如果想要在 Redis 中查看相关的命令也可以使用 help 命令来进行查看,命令如下。 在按下回车后,可以看到相应分类命令的说明,如下图。 图中就是部分关于 Strings 相关的部分命令。 常用 Strings 相关命令 为了大家能够直接复制命令进行测试,下面我就不截图了。 1、set 命令 set 命令的作用是 设置一个 key 的 value 值 设置 key 对应的字符串类型 上面的命令分别对 key1 设置为 value1,对 key2 设置为 value2。 set 命令除了基本的用法外,还有几个参数,先来说一下 nx 和 xx 两个参数。 nx 表示 key 不存在时,执行操作 xx 表示 Key 存在时,执行操作 命令 set k1 v1 nx 表示,当 k1 不存在时,给 k1 设置字符串值为 v1,此时 k1 并不存在,因此该命令被执行; 命令 set k2 v2 xx 表示,当 k2 存在时,给 k2 设置字符串值为 v2,此时 k2 并不存在,因此该命令没有被执行 再介绍另外两个参数,分别是 ex 和 px,ex 和 px 是在进行 set 命令时可以设置过期时间的命令 ex 表示 设置的过期时间以秒为单位 px 表示 设置的过期时间以毫秒为单位 2、setnx 命令 setnx 命令的作用是 当指定的键不存在时给该键设置一个值 该命令类似 set 命令附带了 nx 参数 在上面的命令中,setnx k1 value1,由于 k1 存在,因此命令没有被执行,setnx k2 value2,由于 k2 不存在,因此命令被执行。 当命令执行成功,返回值为 1 当命令执行不成功,返回值为 0 3、get 命令 get 命令的作用是 获取指定 key 的值 该命令已经被多次使用了,演示如下: 4、getset 命令 getset 命令的作用是 设置一个 key 的 value,并获取设置前的值 该命令相当于 先对指定的 key 进行一次 get 操作,再执行一次 set 操作,两个命令合并,可以保证原子性。 5、mget 命令 mget 命令的作用是 一次获取多个 key 的值,如果 key 不存在则返回 nil 可以看到,key3 是不存在的,因此 key3 返回的值是 nil 6、mset 命令 mset 命令的作用是 设置多个key value 7、msetnx 命令 msetnx 命令的作用是 设置多个key value,仅当key不存在时 可以看出,msetnx k4 vv4 k5 vv5 时,此时不存在 k4 和 k5 因此该命令执行成功,在执行 msetnx k4 v4 k5 v5 k6 v6 时,由于 k4 和 k5 已经存在,则使得这条命令执行失败,因此 k4 和 k5 的值仍然是 vv4 和 vv5,并且没有 k6 这个 key。 8、incr 命令 incr 命令的作用是 执行原子加1操作 9、decr 命令 decr 命令的作用是 整数原子减1 10、incrby 命令 incrby 命令的作用是 执行原子增加一个整数 11、decrby 命令 decrby 命令的作用是 原子减指定的整数 12、incrbyfloat 命令 incrbyfloat 命令的作用是 执行原子增加一个浮点数 13、setrange 命令 setrange 命令的作用是 修改字符串指定偏移的值 字符串的偏移从 0 开始,hello 的长度为 5,最后 1 个下标为 4,当我们 setrange kstr 6 x 时,我们将 kstr 下标 6 的位置设置为了 x,因此在下标 5 的位置处给了一个 x00,即 ASCII 码的 0。 14、getrange 命令 getrange 命令的作用是 获取存储在key上的值的一个子字符串 下标 -1 为最后一个下标,下标 -2 为倒数第二个下标 15、append 命令 append 命令的作用是 追加一个值到key上 总结 这些基础的命令当中,除了可以当作基础的操作 字符串 的命令来用,也有其他方面的用处,比如在高并发当中可以用来设置锁等。把今天整理的命令完善了一个思维导图,图片如下。

请教redis如何做到和mysql数据库的同步

 redis和mysql数据的同步,代码级别大致可以这样做:  读: 读redis->没有,读mysql->把mysql数据写回redis  写: 写mysql->成功,写redis

redis tcp-keepalive为0,tcp连接会释放吗

如果设置为0,则不会进行Keepalive检测

redistribute rip metric 100metric-type 1subnets是

重新分配100metric型1subnets RIP度量

redistribute rip metric-type 1 metric 10 subnets 里metric 的值根据什么来确定

我觉得你可能题目没写全如果我没有猜错,第一行是 把RIP redistribute 进OSPF 这里的metric 默认是20第二行是 把OSPF redistribute 进RIP 。 这里的metric 就是RIP中的跳数 ,默认好像是1

怎么去操作shiro跟redis集成的session

第一步:配置WEB.XML<filter> <filter-name>shiroFilter</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> <init-param> <param-name>targetFilterLifecycle</param-name> <param-value>true</param-value> </init-param></filter><filter-mapping> <filter-name>shiroFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping>第二步:SHIRO整合SPRING配置applicationContext-shiro.xml 伪代码:<!--Session集群配置--><bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <property name="globalSessionTimeout" value="3600000"/> <property name="sessionDAO" ref="zkShiroSessionDAO"/> <property name="sessionValidationScheduler" ref="sessionValidationScheduler"/> <property name="sessionValidationSchedulerEnabled" value="true"/> <property name="sessionIdCookie" ref="wapsession"/></bean><!--指定本系统SESSIONID, 默认为: JSESSIONID问题: 与SERVLET容器名冲突, 如JETTY, TOMCAT 等默认JSESSIONID,当跳出SHIRO SERVLET时如ERROR-PAGE容器会为JSESSIONID重新分配值导致登录会话丢失!--><bean id="wapsession" class="org.apache.shiro.web.servlet.SimpleCookie"> <constructor-arg name="name" value="WAPSESSIONID"/></bean><!--定时清理僵尸session,Shiro会启用一个后台守护线程定时执行清理操作用户直接关闭浏览器造成的孤立会话--><bean id="sessionValidationScheduler" class="org.apache.shiro.session.mgt.ExecutorServiceSessionValidationScheduler"> <property name="interval" value="3600000"/> <property name="sessionManager" ref="sessionManager"/></bean><!--由zk做session存储容器--><bean id="zkShiroSessionDAO" class="b2gonline.incometaxexamine._systembase.shiro.ZKShiroSessionDAO"> <!--使用内存缓存登录用户信息,一次获取用户登录信息后缓存到内存减少Shiro大量的读取操作,用户退出或超时后自动清除--> <constructor-arg name="useMemCache" value="true"/> <property name="zookeeperTemplate" ref="zookeeperTemplate"/> <property name="shiroSessionZKPath" value="/SHIROSESSIONS"/> <property name="sessionPrefix" value="session-"/></bean><!-- SHIRO安全接口 --><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> ... <property name="sessionManager" ref="sessionManager"/></bean>第三步:Zookeeper对Shiro-SessionDao实现类ZKShiroSessionDAO.JAVA伪代码:import bgonline.foundation.hadoop.zk.IZookeeperTemplate;import bgonline.foundation.hadoop.zk.ZNode;import org.apache.shiro.cache.AbstractCacheManager;import org.apache.shiro.cache.Cache;import org.apache.shiro.cache.CacheException;import org.apache.shiro.cache.MapCache;import org.apache.shiro.session.Session;import org.apache.shiro.session.UnknownSessionException;import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;import org.apache.shiro.session.mgt.eis.CachingSessionDAO;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.util.SerializationUtils;import java.io.Serializable;import java.util.Collection;import java.util.HashSet;import java.util.List;import java.util.Set;import java.util.concurrent.ConcurrentHashMap;/** * ZOOKEEPER实现SHIRO集群SESSION存储 * * @author aliencode * @date 13-7-10 */public class ZKShiroSessionDAO extends CachingSessionDAO { public ZKShiroSessionDAO() { } private boolean useMemCache = false; /** * SESSION ZK DAO 实例 * 如果开户缓存 * 用户登录时自动缓存, 用户登录超时自动删除 * 由于shiro的cacheManager是全局的, 所以这里使用setActiveSessionsCache直接设置Cache来本地缓存, 而不使用全局zk缓存. * 由于同一用户可能会被路由到不同服务器,所以在doReadSession方法里也做了缓存增加. * * @param useMemCache 是否使用内存缓存登录信息 */ public ZKShiroSessionDAO(boolean useMemCache) { this.useMemCache = useMemCache; if (useMemCache) { setActiveSessionsCache( new MapCache<>(this.ACTIVE_SESSION_CACHE_NAME, new ConcurrentHashMap<Serializable, Session>()) ); } } Logger logger = LoggerFactory.getLogger(this.getClass()); /** * ZK操作类 */ private IZookeeperTemplate zookeeperTemplate; /** * 缓存根路径, 结尾不加/ */ private String shiroSessionZKPath = "/SHIROSESSIONS"; /** * 缓存项前缀 */ private String sessionPrefix = "session-"; /** * 设置Shiro Session 前缀 默认 session- * * @param sessionPrefix */ public void setSessionPrefix(String sessionPrefix) { this.sessionPrefix = sessionPrefix; }public void setZookeeperTemplate(IZookeeperTemplate zookeeperTemplate) { this.zookeeperTemplate = zookeeperTemplate; } /** * 设置Shiro在ZK服务器存放根路径 * * @param shiroSessionZKPath 默认值:/SHIROSESSIONS/ */ public void setShiroSessionZKPath(String shiroSessionZKPath) { this.shiroSessionZKPath = shiroSessionZKPath; } /** * session更新 * * @param session * @throws UnknownSessionException */ @Override public void update(Session session) throws UnknownSessionException { if (session == null || session.getId() == null) { logger.error("session argument cannot be null."); } saveSession(session, "update"); } @Override protected void doUpdate(Session session) { } /** * session删除 * * @param session */ @Override public void delete(Session session) { if (session == null || session.getId() == null) { logger.error("session argument cannot be null."); } logger.debug("delete session for id: {}", session.getId()); zookeeperTemplate.deleteNode(getPath(session.getId())); if (useMemCache) { this.uncache(session); } } @Override protected void doDelete(Session session) { } /** * 获取当前活跃的session, 当前在线数量 * * @return */ @Override public Collection<Session> getActiveSessions() { ZNode zNode = new ZNode(); zNode.setPath(shiroSessionZKPath); Set<Session> sessions = new HashSet<Session>(); //读取所有SessionID , 返回形如: session-9e3b5707-fa80-4d32-a6c9-f1c3685263a5 List<String> ss = zookeeperTemplate.getChildren(zNode); for (String id : ss) { if (id.startsWith(sessionPrefix)) { String noPrefixId = id.replace(sessionPrefix, ""); Session session = doReadSession(noPrefixId); if (session != null) sessions.add(session); } } logger.debug("shiro getActiveSessions. size: {}", sessions.size()); return sessions; } /** * 创建session, 用户登录 * * @param session * @return */ @Override protected Serializable doCreate(Session session) { Serializable sessionId = this.generateSessionId(session); this.assignSessionId(session, sessionId); saveSession(session, "create"); return sessionId; } /** * session读取 * * @param id * @return */ @Override protected Session doReadSession(Serializable id) { if (id == null) { logger.error("id is null!"); return null; } logger.debug("doReadSession for path: {}", getPath(id)); Session session; byte[] byteData = zookeeperTemplate.getData(getPath(id)).getByteData(); if (byteData != null && byteData.length > 0) { session = (Session) SerializationUtils.deserialize(byteData); if (useMemCache) { this.cache(session, id); logger.debug("doReadSession for path: {}, add cached !", getPath(id)); } return session; } else { return null; } } /** * 生成全路径 * * @param sessID * @return */ private String getPath(Serializable sessID) { return shiroSessionZKPath + "/" + sessionPrefix + sessID.toString(); } /** * session读取或更新 * * @param session * @param act update/save */ private void saveSession(Session session, String act) { Serializable sessionId = session.getId(); ZNode sessionNode = new ZNode(); sessionNode.setByteData(SerializationUtils.serialize(session)); sessionNode.setPath(getPath(sessionId)); logger.debug("save session for id: {}, act: {}", sessionId, act); if (act == "update") zookeeperTemplate.setData(sessionNode); else zookeeperTemplate.createNode(sessionNode); }}

tomcat7用redis存储session报错

你存储的的东西好像没有序列化,继承一下serializable

ZoeDiStefano出生于哪里

ZoeDiStefanoZoeDiStefano是一名演员,代表作品有《格林伯格》、《坏妈妈手册》等。外文名:ZoeDiStefano职业:演员代表作品:格林伯格合作人物:诺亚·鲍姆巴赫

为什么笔记本上CreateDispatch总是失败?

笔记本上的组件可能为未注册,导致IDispatch失败.简单判断方法:在MFC的类添加向导中选择TYPE LIB类型库添加,查看组件是否能看到?不能就说明组件未注册.如果是.DLL,可以使用WINDOWS自带的regsvr32 xxx.dll,在"运行"框中执行注册.

谈谈redis,memcache,mongodb的区别和具体应用场景

从以下几个维度,对 redis、memcache、mongoDB 做了对比。1、性能都比较高,性能对我们来说应该都不是瓶颈。总体来讲,TPS 方面 redis 和 memcache 差不多,要大于 mongodb。2、操作的便利性memcache 数据结构单一。(key-value)redis 丰富一些,数据操作方面,redis 更好一些,较少的网络 IO 次数,同时还提供 list,set,hash 等数据结构的存储。mongodb 支持丰富的数据表达,索引,最类似关系型数据库,支持的查询语言非常丰富。3、内存空间的大小和数据量的大小redis 在 2.0 版本后增加了自己的 VM 特性,突破物理内存的限制;可以对 key value 设置过期时间(类似 memcache)memcache 可以修改最大可用内存,采用 LRU 算法。Memcached 代理软件 magent,比如建立10 台 4G 的 Memcache 集群,就相当于有了 40G。 magent -s 10.1.2.1 -s 10.1.2.2:11211 -b10.1.2.3:14000 mongoDB 适合大数据量的存储,依赖操作系统 VM 做内存管理,吃内存也比较厉害,服务不要和别的服务在一起。4、可用性(单点问题)对于单点问题,redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,所以单点问题比较复杂;不支持自动 sharding,需要依赖程序设定一致 hash 机制。一种替代方案是,不用 redis 本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡Memcache 本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的 hash 或者环状的算法,解决单点故障引起的抖动问题。mongoDB 支持 master-slave,replicaset(内部采用 paxos 选举算法,自动故障恢复),auto sharding 机制,对客户端屏蔽了故障转移和切分机制。5、可靠性(持久化)对于数据持久化和数据恢复,redis 支持(快照、AOF):依赖快照进行持久化,aof 增强了可靠性的同时,对性能有所影响memcache 不支持,通常用在做缓存,提升性能;MongoDB 从 1.8 版本开始采用 binlog 方式支持持久化的可靠性6、数据一致性(事务支持)Memcache 在并发场景下,用 cas 保证一致性redis 事务支持比较弱,只能保证事务中的每个操作连续执行mongoDB 不支持事务7、数据分析mongoDB 内置了数据分析的功能(mapreduce),其他不支持8、应用场景redis:数据量较小的更性能操作和运算上memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用 sharding)MongoDB:主要解决海量数据的访问效率问题。表格比较:memcache redis 类型 内存数据库 内存数据库数据类型 在定义 value 时就要固定数据类型 不需要有字符串,链表,集 合和有序集合虚拟内存 不支持 支持过期策略 支持 支持分布式 magent master-slave,一主一从或一主多从存储数据安全 不支持 使用 save 存储到 dump.rdb 中灾难恢复 不支持 append only file(aof)用于数据恢复性能1、类型——memcache 和 redis 都是将数据存放在内存,所以是内存数据库。当然,memcache 也可用于缓存其他东西,例如图片等等。2、 数据类型——Memcache 在添加数据时就要指定数据的字节长度,而 redis 不需要。3、 虚拟内存——当物理内存用完时,可以将一些很久没用到的 value 交换到磁盘。4、 过期策略——memcache 在 set 时就指定,例如 set key1 0 0 8,即永不过期。Redis 可以通过例如 expire 设定,例如 expire name 10。5、 分布式——设定 memcache 集群,利用 magent 做一主多从;redis 可以做一主多从。都可以一主一从。6、 存储数据安全——memcache 断电就断了,数据没了;redis 可以定期 save 到磁盘。7、 灾难恢复——memcache 同上,redis 丢了后可以通过 aof 恢复。Memecache 端口 11211yum -y install memcachedyum -y install php-pecl-memcache/etc/init.d/memcached start memcached -d -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid-d 启动一个守护进程-p 端口-m 分配的内存是 M-c 最大运行并发数-P memcache 的 pid//0 压缩(是否 MEMCACHE_COMPRESSED) 30 秒失效时间//delete 5 是 timeout <?php$memcache = new Memcache; $memcache -> connect("127.0.0.1", 11211); $memcache -> set("name","yang",0,30);if(!$memcache->add("name","susan",0, 30)) {//echo "susan is exist"; }$memcache -> replace("name", "lion", 0, 300); echo $memcache -> get("name");//$memcache -> delete("name", 5);printf "stats " | nc 127.0.0.1 11211telnet localhost 11211 stats quit 退出Redis 的配置文件 端口 6379/etc/redis.conf 启动 Redisredis-server /etc/redis.conf 插入一个值redis-cli set test "phper.yang" 获取键值redis-cli get test 关闭 Redisredis-cli shutdown 关闭所有redis-cli -p 6379 shutdown <?php$redis=new Redis(); $redis->connect("127.0.0.1",6379); $redis->set("test", "Hello World"); echo $redis->get("test"); Mongodbapt-get install mongo mongo 可以进入 shell 命令行pecl install mongo Mongodb 类似 phpmyadmin 操作平台 RockMongo

php面试题 memcache和redis的区别

Redis与Memcached的区别传统MySQL+ Memcached架构遇到的问题  实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:  1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。  2.Memcached与MySQL数据库数据一致性问题。  3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。  4.跨机房cache同步问题。  众多NoSQL百花齐放,如何选择  最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题  1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。  2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。  3.这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计,节点之间通过gossip方式传递集群信息,数据保证最终一致性,后者是一个中心化的方案设计,通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log,然后定期compat归并到磁盘上,将随机写优化为顺序写,提高写入性能。  4.Schema free,auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的,直接存储json格式数据,并且支持auto-sharding等功能,比如mongodb。  面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。  Redis适用场景,如何正确的使用  前面已经分析过,Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢?如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:1 Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。2 Redis支持数据的备份,即master-slave模式的数据备份。3 Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。抛开这些,可以深入到Redis内部构造去观察更加本质的区别,理解Redis的设计。在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的 key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计 算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以 保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存 中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个 操作,直到子线程完成swap操作后才可以进行修改。使用Redis特有内存模型前后的情况对比:VM off: 300k keys, 4096 bytes values: 1.3G usedVM on: 300k keys, 4096 bytes values: 73M usedVM off: 1 million keys, 256 bytes values: 430.12M usedVM on: 1 million keys, 256 bytes values: 160.09M usedVM on: 1 million keys, values as large as you want, still: 160.09M used当 从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行 批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程 池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。如果希望在海量数据的环境中使用好Redis,我相信理解Redis的内存设计和阻塞的情况是不可缺少的。补充的知识点:memcached和redis的比较1 网络IO模型  Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO, 网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如,Memcached最常用的stats 命令,实际Memcached所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。(Memcached网络IO模型)  Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll、kqueue和select,对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。  2.内存管理方面  Memcached使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除,原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/  Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,导致swap也不会剔除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。  3.数据一致性问题  Memcached提供了cas命令,可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。  4.存储方式及其它方面  Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能  Redis除key/value之外,还支持list,set,sorted set,hash等众多数据结构,提供了KEYS  进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其dump文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。  5.关于不同语言的客户端支持  在不同语言的客户端方面,Memcached和Redis都有丰富的第三方客户端可供选择,不过因为Memcached发展的时间更久一些,目前看在客户端支持方面,Memcached的很多客户端更加成熟稳定,而Redis由于其协议本身就比Memcached复杂,加上作者不断增加新的功能等,对应第三方客户端跟进速度可能会赶不上,有时可能需要自己在第三方客户端基础上做些修改才能更好的使用。  根据以上比较不难看出,当我们不希望数据被踢出,或者需要除key/value之外的更多数据类型时,或者需要落地功能时,使用Redis比使用Memcached更合适。  关于Redis的一些周边功能  Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,对于此类功能需要了解其实现原理,清楚地了解到它的局限性后,才能正确的使用,比如pubsub功能,这个实际是没有任何持久化支持的,消费方连接闪断或重连之间过来的消息是会全部丢失的,又比如聚合计算和scripting等功能受Redis单线程模型所限,是不可能达到很高的吞吐量的,需要谨慎使用。  总的来说Redis作者是一位非常勤奋的开发者,可以经常看到作者在尝试着各种不同的新鲜想法和思路,针对这些方面的功能就要求我们需要深入了解后再使用。  总结:  1.Redis使用最佳方式是全部数据in-memory。  2.Redis更多场景是作为Memcached的替代者来使用。  3.当需要除key/value之外的更多数据类型支持时,使用Redis更合适。  4.当存储的数据不能被剔除时,使用Redis更合适。谈谈Memcached与Redis(一)1. Memcached简介Memcached是以LiveJurnal旗下Danga Interactive公司的Bard Fitzpatric为首开发的高性能分布式内存缓存服务器。其本质上就是一个内存key-value数据库,但是不支持数据的持久化,服务器关闭之后数据全部丢失。Memcached使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上,只要安装了libevent即可使用。在Windows下,它也有一个可用的非官方版本(http://code.jellycan.com/memcached/)。Memcached的客户端软件实现非常多,包括C/C++, PHP, Java, Python, Ruby, Perl, Erlang, Lua等。当前Memcached使用广泛,除了LiveJournal以外还有Wikipedia、Flickr、Twitter、Youtube和WordPress等。在Window系统下,Memcached的安装非常方便,只需从以上给出的地址下载可执行软件然后运行memcached.exe –d install即可完成安装。在Linux等系统下,我们首先需要安装libevent,然后从获取源码,make && make install即可。默认情况下,Memcached的服务器启动程序会安装到/usr/local/bin目录下。在启动Memcached时,我们可以为其配置不同的启动参数。1.1 Memcache配置Memcached服务器在启动时需要对关键的参数进行配置,下面我们就看一看Memcached在启动时需要设定哪些关键参数以及这些参数的作用。1)-p <num> Memcached的TCP监听端口,缺省配置为11211;2)-U <num> Memcached的UDP监听端口,缺省配置为11211,为0时表示关闭UDP监听;3)-s <file> Memcached监听的UNIX套接字路径;4)-a <mask> 访问UNIX套接字的八进制掩码,缺省配置为0700;5)-l <addr> 监听的服务器IP地址,默认为所有网卡;6)-d 为Memcached服务器启动守护进程;7)-r 最大core文件大小;8)-u <username> 运行Memcached的用户,如果当前为root的话需要使用此参数指定用户;9)-m <num> 分配给Memcached使用的内存数量,单位是MB;10)-M 指示Memcached在内存用光的时候返回错误而不是使用LRU算法移除数据记录;11)-c <num> 最大并发连数,缺省配置为1024;12)-v –vv –vvv 设定服务器端打印的消息的详细程度,其中-v仅打印错误和警告信息,-vv在-v的基础上还会打印客户端的命令和相应,-vvv在-vv的基础上还会打印内存状态转换信息;13)-f <factor> 用于设置chunk大小的递增因子;14)-n <bytes> 最小的chunk大小,缺省配置为48个字节;15)-t <num> Memcached服务器使用的线程数,缺省配置为4个;16)-L 尝试使用大内存页;17)-R 每个事件的最大请求数,缺省配置为20个;18)-C 禁用CAS,CAS模式会带来8个字节的冗余;2. Redis简介Redis是一个开源的key-value存储系统。与Memcached类似,Redis将大部分数据存储在内存中,支持的数据类型包括:字符串、哈希表、链表、集合、有序集合以及基于这些数据类型的相关操作。Redis使用C语言开发,在大多数像Linux、BSD和Solaris等POSIX系统上无需任何外部依赖就可以使用。Redis支持的客户端语言也非常丰富,常用的计算机语言如C、C#、C++、Object-C、PHP、Python、Java、Perl、Lua、Erlang等均有可用的客户端来访问Redis服务器。当前Redis的应用已经非常广泛,国内像新浪、淘宝,国外像Flickr、Github等均在使用Redis的缓存服务。Redis的安装非常方便,只需从http://redis.io/download获取源码,然后make && make install即可。默认情况下,Redis的服务器启动程序和客户端程序会安装到/usr/local/bin目录下。在启动Redis服务器时,我们需要为其指定一个配置文件,缺省情况下配置文件在Redis的源码目录下,文件名为redis.conf。

tomcat,apache,nginx,php,redis,memcached,lvs-keeplived是什么意思

Tomcat 服务器是一个免费的开放源代码的Web 应用服务器,属于轻量级应用服务器,在中小型系统和并发访问用户不是很多的场合下被普遍使用,是开发和调试JSP 程序的首选。Apache是世界使用排名第一的Web服务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛使用,是最流行的Web服务器端软件之一。它快速、可靠并且可通过简单的API扩充,将Perl/Python等解释器编译到服务器中。Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。Memcached 是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载。它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。Memcached基于一个存储键/值对的hashmap。其守护进程(daemon )是用C写的,但是客户端可以用任何语言来编写,并通过memcached协议与守护进程通信。LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。Keepalived的作用是检测服务器的状态,如果有一台web服务器死机,或工作出现故障,Keepalived将检测到,并将有故障的服务器从系统中剔除,同时使用其他服务器代替该服务器的工作,当服务器工作正常后Keepalived自动将服务器加入到服务器群中,这些工作全部自动完成,不需要人工干涉,需要人工做的只是修复故障的服务器。

Redis 和 Memcached 各有什么优缺点,主要的应用场景是什么样的

1. Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。 2. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。 3. Redis支持数据的备份,即master-slave模式的数据备份。 4. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。 5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从 6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化) 7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复 以上参考:PHP程序员,雷雪松的个人博客。

redis和memcached的区别

1、性能都比较高,性能对我们来说应该都不是瓶颈总体来讲,TPS方面redis和memcache差不多2、操作的便利性memcache数据结构单一redis丰富一些,数据操作方面,redis更好一些,较少的网络IO次数3、内存空间的大小和数据量的大小redis在2.0版本后增加了自己的VM特性,突破物理内存的限制;可以对keyvalue设置过期时间(类似memcache)memcache可以修改最大可用内存,采用LRU算法4、可用性(单点问题)对于单点问题,redis,依赖客户端来实现分布式读写;主从复制时,每次从节点重新连接主节点都要依赖整个快照,无增量复制,因性能和效率问题,所以单点问题比较复杂;不支持自动sharding,需要依赖程序设定一致hash机制。一种替代方案是,不用redis本身的复制机制,采用自己做主动复制(多份存储),或者改成增量复制的方式(需要自己实现),一致性问题和性能的权衡Memcache本身没有数据冗余机制,也没必要;对于故障预防,采用依赖成熟的hash或者环状的算法,解决单点故障引起的抖动问题。5、可靠性(持久化)对于数据持久化和数据恢复,redis支持(快照、AOF):依赖快照进行持久化,aof增强了可靠性的同时,对性能有所影响memcache不支持,通常用在做缓存,提升性能;6、数据一致性(事务支持)Memcache在并发场景下,用cas保证一致性redis事务支持比较弱,只能保证事务中的每个操作连续执行7、数据分析不支持8、应用场景redis:数据量较小的更性能操作和运算上memcache:用于在动态系统中减少数据库负载,提升性能;做缓存,提高性能(适合读多写少,对于数据量比较大,可以采用sharding)

Redis和Memcached的区别

Redis与Memcached的区别传统MySQL+ Memcached架构遇到的问题  实际MySQL是适合进行海量数据存储的,通过Memcached将热点数据加载到cache,加速访问,很多公司都曾经使用过这样的架构,但随着业务数据量的不断增加,和访问量的持续增长,我们遇到了很多问题:  1.MySQL需要不断进行拆库拆表,Memcached也需不断跟着扩容,扩容和维护工作占据大量开发时间。  2.Memcached与MySQL数据库数据一致性问题。  3.Memcached数据命中率低或down机,大量访问直接穿透到DB,MySQL无法支撑。  4.跨机房cache同步问题。  众多NoSQL百花齐放,如何选择  最近几年,业界不断涌现出很多各种各样的NoSQL产品,那么如何才能正确地使用好这些产品,最大化地发挥其长处,是我们需要深入研究和思考的问题,实际归根结底最重要的是了解这些产品的定位,并且了解到每款产品的tradeoffs,在实际应用中做到扬长避短,总体上这些NoSQL主要用于解决以下几种问题  1.少量数据存储,高速读写访问。此类产品通过数据全部in-momery 的方式来保证高速访问,同时提供数据落地的功能,实际这正是Redis最主要的适用场景。  2.海量数据存储,分布式系统支持,数据一致性保证,方便的集群节点添加/删除。  3.这方面最具代表性的是dynamo和bigtable 2篇论文所阐述的思路。前者是一个完全无中心的设计,节点之间通过gossip方式传递集群信息,数据保证最终一致性,后者是一个中心化的方案设计,通过类似一个分布式锁服务来保证强一致性,数据写入先写内存和redo log,然后定期compat归并到磁盘上,将随机写优化为顺序写,提高写入性能。  4.Schema free,auto-sharding等。比如目前常见的一些文档数据库都是支持schema-free的,直接存储json格式数据,并且支持auto-sharding等功能,比如mongodb。  面对这些不同类型的NoSQL产品,我们需要根据我们的业务场景选择最合适的产品。  Redis适用场景,如何正确的使用  前面已经分析过,Redis最适合所有数据in-momory的场景,虽然Redis也提供持久化功能,但实际更多的是一个disk-backed的功能,跟传统意义上的持久化有比较大的差别,那么可能大家就会有疑问,似乎Redis更像一个加强版的Memcached,那么何时使用Memcached,何时使用Redis呢? 如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点:1 Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。2 Redis支持数据的备份,即master-slave模式的数据备份。3 Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。抛开这些,可以深入到Redis内部构造去观察更加本质的区别,理解Redis的设计。在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。Redis只会缓存所有的 key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计 算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以 保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存 中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个 操作,直到子线程完成swap操作后才可以进行修改。使用Redis特有内存模型前后的情况对比:VM off: 300k keys, 4096 bytes values: 1.3G usedVM on: 300k keys, 4096 bytes values: 73M usedVM off: 1 million keys, 256 bytes values: 430.12M usedVM on: 1 million keys, 256 bytes values: 160.09M usedVM on: 1 million keys, values as large as you want, still: 160.09M used当 从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行 批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程 池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。如果希望在海量数据的环境中使用好Redis,我相信理解Redis的内存设计和阻塞的情况是不可缺少的。 补充的知识点:memcached和redis的比较1 网络IO模型  Memcached是多线程,非阻塞IO复用的网络模型,分为监听主线程和worker子线程,监听线程监听网络连接,接受请求后,将连接描述字pipe 传递给worker线程,进行读写IO, 网络层使用libevent封装的事件库,多线程模型可以发挥多核作用,但是引入了cache coherency和锁的问题,比如,Memcached最常用的stats 命令,实际Memcached所有操作都要对这个全局变量加锁,进行计数等工作,带来了性能损耗。(Memcached网络IO模型)  Redis使用单线程的IO复用模型,自己封装了一个简单的AeEvent事件处理框架,主要实现了epoll、kqueue和select,对于单纯只有IO操作来说,单线程可以将速度优势发挥到最大,但是Redis也提供了一些简单的计算功能,比如排序、聚合等,对于这些操作,单线程模型实际会严重影响整体吞吐量,CPU计算过程中,整个IO调度都是被阻塞住的。  2.内存管理方面  Memcached使用预分配的内存池的方式,使用slab和大小不同的chunk来管理内存,Item根据大小选择合适的chunk存储,内存池的方式可以省去申请/释放内存的开销,并且能减小内存碎片产生,但这种方式也会带来一定程度上的空间浪费,并且在内存仍然有很大空间时,新的数据也可能会被剔除,原因可以参考Timyang的文章:http://timyang.net/data/Memcached-lru-evictions/  Redis使用现场申请内存的方式来存储数据,并且很少使用free-list等方式来优化内存分配,会在一定程度上存在内存碎片,Redis跟据存储命令参数,会把带过期时间的数据单独存放在一起,并把它们称为临时数据,非临时数据是永远不会被剔除的,即便物理内存不够,导致swap也不会剔除任何非临时数据(但会尝试剔除部分临时数据),这点上Redis更适合作为存储而不是cache。  3.数据一致性问题  Memcached提供了cas命令,可以保证多个并发访问操作同一份数据的一致性问题。 Redis没有提供cas 命令,并不能保证这点,不过Redis提供了事务的功能,可以保证一串 命令的原子性,中间不会被任何操作打断。  4.存储方式及其它方面  Memcached基本只支持简单的key-value存储,不支持枚举,不支持持久化和复制等功能  Redis除key/value之外,还支持list,set,sorted set,hash等众多数据结构,提供了KEYS  进行枚举操作,但不能在线上使用,如果需要枚举线上数据,Redis提供了工具可以直接扫描其dump文件,枚举出所有数据,Redis还同时提供了持久化和复制等功能。  5.关于不同语言的客户端支持  在不同语言的客户端方面,Memcached和Redis都有丰富的第三方客户端可供选择,不过因为Memcached发展的时间更久一些,目前看在客户端支持方面,Memcached的很多客户端更加成熟稳定,而Redis由于其协议本身就比Memcached复杂,加上作者不断增加新的功能等,对应第三方客户端跟进速度可能会赶不上,有时可能需要自己在第三方客户端基础上做些修改才能更好的使用。  根据以上比较不难看出,当我们不希望数据被踢出,或者需要除key/value之外的更多数据类型时,或者需要落地功能时,使用Redis比使用Memcached更合适。  关于Redis的一些周边功能  Redis除了作为存储之外还提供了一些其它方面的功能,比如聚合计算、pubsub、scripting等,对于此类功能需要了解其实现原理,清楚地了解到它的局限性后,才能正确的使用,比如pubsub功能,这个实际是没有任何持久化支持的,消费方连接闪断或重连之间过来的消息是会全部丢失的,又比如聚合计算和scripting等功能受Redis单线程模型所限,是不可能达到很高的吞吐量的,需要谨慎使用。  总的来说Redis作者是一位非常勤奋的开发者,可以经常看到作者在尝试着各种不同的新鲜想法和思路,针对这些方面的功能就要求我们需要深入了解后再使用。  总结:  1.Redis使用最佳方式是全部数据in-memory。  2.Redis更多场景是作为Memcached的替代者来使用。  3.当需要除key/value之外的更多数据类型支持时,使用Redis更合适。  4.当存储的数据不能被剔除时,使用Redis更合适。

Redis和Memcached的区别

1. Redis中,并不是所有的数据都一直存储在内存中的,这是和Memcached相比一个最大的区别。2. Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,hash等数据结构的存储。3. Redis支持数据的备份,即master-slave模式的数据备份。4. Redis支持数据的持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用。5、分布式--设定memcache集群,利用magent做一主多从;redis可以做一主多从。都可以一主一从6、存储数据安全--memcache挂掉后,数据没了;redis可以定期保存到磁盘(持久化)7、灾难恢复--memcache挂掉后,数据不可恢复; redis数据丢失后可以通过aof恢复以上参考:PHP程序员,雷雪松的个人博客。

redis和memcached的区别

支持的类型不同,redis数据类型更多,或者叫更丰富。导致使用场景少。memcache原生不支持分布式,redis可以。memcache的发展不如redismemcache单key没有redis大。

redis和memcached的区别

memcache 本身是一款分布式的高速缓存系统,以 key-value 的形式常驻内存,一般用来做网站或者数据库的缓存使用。特别是对以下场景非常适合用 memcache 来做缓存:1. 频繁访问的数据2. 安全性要求比较低的数据3. 更新比较频繁的小表(用户状态表、物品库存等)MySQL memcached api MySQL 5.6 —— 开始支持MySQL 5.6 把 memcache 功能以插件形式集成到 MySQL 数据库中,称为 memcached api。这样一来,memcache 的数据以 InnoDB 关系表的形式同步于磁盘,解决了 memcache 的几个问题:1. 解决了 memcache 的数据持久化的问题;2. 可以很方便的以 SQL 语句的形式直接访问 memcache 的数据;3. 不需要单独安装 memcache,安装 MySQL 即可使用。MySQL 5.7 —— 深入优化MySQL 5.7 对 memcached api 做了深入优化,官方数据显示使用 memcached api,在只读的场景中,QPS 提升到 100W。 MySQL 8.0 —— 新增特性MySQL 8.0 发布后,又在功能上给 memcached api 增加了两个新特性。1. 批量获取 KEY相比原来一次只能读取一个 Key 来讲,减少了客户端与 MySQL 服务端的数据交互次数。2. 可以对 KEY 进行 RANGE 操作可以直接类似于 select * from t1 where id between 10 and 20 这样的范围检索语句。

Redis 和 Memcached 各有什么优缺点,主要的应用场景是什么样的

Redis的作者Salvatore Sanfilippo曾经对这两种基于内存的数据存储系统进行过比较:1、Redis支持服务器端的数据操作:Redis相比Memcached来说,拥有更多的数据结构和并支持更丰富的数据操作,通常在Memcached里,你需要将数据拿到客户端来进行类似的修改再set回去。这大大增加了网络IO的次数和数据体积。在Redis中,这些复杂的操作通常和一般的GET/SET一样高效。所以,如果需要缓存能够支持更复杂的结构和操作,那么Redis会是不错的选择。2、内存使用效率对比:使用简单的key-value存储的话,Memcached的内存利用率更高,而如果Redis采用hash结构来做key-value存储,由于其组合式的压缩,其内存利用率会高于Memcached。3、性能对比:由于Redis只使用单核,而Memcached可以使用多核,所以平均每一个核上Redis在存储小数据时比Memcached性能更高。而在100k以上的数据中,Memcached性能要高于Redis,虽然Redis最近也在存储大数据的性能上进行优化,但是比起Memcached,还是稍有逊色。具体为什么会出现上面的结论,以下为收集到的资料:1、数据类型支持不同与Memcached仅支持简单的key-value结构的数据记录不同,Redis支持的数据类型要丰富得多。最为常用的数据类型主要由五种:String、Hash、List、Set和Sorted Set。Redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如图所示:type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string代表value存储的是一个普通字符串,那么对应的encoding可以是raw或者是int,如果是int则代表实际redis内部是按数值型类存储和表示这个字符串的,当然前提是这个字符串本身可以用数值表示,比如:”123″ “456”这样的字符串。只有打开了Redis的虚拟内存功能,vm字段字段才会真正的分配内存,该功能默认是关闭状态的。1)String常用命令:set/get/decr/incr/mget等;应用场景:String是最常用的一种数据类型,普通的key/value存储都可以归为此类;实现方式:String在redis内部存储默认就是一个字符串,被redisObject所引用,当遇到incr、decr等操作时会转成数值型进行计算,此时redisObject的encoding字段为int。2)Hash常用命令:hget/hset/hgetall等应用场景:我们要存储一个用户信息对象数据,其中包括用户ID、用户姓名、年龄和生日,通过用户ID我们希望获取该用户的姓名或者年龄或者生日;实现方式:Redis的Hash实际是内部存储的Value为一个HashMap,并提供了直接存取这个Map成员的接口。如图所示,Key是用户ID, value是一个Map。这个Map的key是成员的属性名,value是属性值。这样对数据的修改和存取都可以直接通过其内部Map的Key(Redis里称内部Map的key为field), 也就是通过 key(用户ID) + field(属性标签) 就可以操作对应属性数据。当前HashMap的实现有两种方式:当HashMap的成员比较少时Redis为了节省内存会采用类似一维数组的方式来紧凑存储,而不会采用真正的HashMap结构,这时对应的value的redisObject的encoding为zipmap,当成员数量增大时会自动转成真正的HashMap,此时encoding为ht。3)List常用命令:lpush/rpush/lpop/rpop/lrange等;应用场景:Redis list的应用场景非常多,也是Redis最重要的数据结构之一,比如twitter的关注列表,粉丝列表等都可以用Redis的list结构来实现;实现方式:Redis list的实现为一个双向链表,即可以支持反向查找和遍历,更方便操作,不过带来了部分额外的内存开销,Redis内部的很多实现,包括发送缓冲队列等也都是用的这个数据结构。4)Set常用命令:sadd/spop/smembers/sunion等;应用场景:Redis set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的;实现方式:set 的内部实现是一个 value永远为null的HashMap,实际就是通过计算hash的方式来快速排重的,这也是set能提供判断一个成员是否在集合内的原因。5)Sorted Set常用命令:zadd/zrange/zrem/zcard等;应用场景:Redis sorted set的使用场景与set类似,区别是set不是自动有序的,而sorted set可以通过用户额外提供一个优先级(score)的参数来为成员排序,并且是插入有序的,即自动排序。当你需要一个有序的并且不重复的集合列表,那么可以选择sorted set数据结构,比如twitter 的public timeline可以以发表时间作为score来存储,这样获取时就是自动按时间排好序的。实现方式:Redis sorted set的内部使用HashMap和跳跃表(SkipList)来保证数据的存储和有序,HashMap里放的是成员到score的映射,而跳跃表里存放的是所有的成员,排序依据是HashMap里存的score,使用跳跃表的结构可以获得比较高的查找效率,并且在实现上比较简单。2、内存管理机制不同在Redis中,并不是所有的数据都一直存储在内存中的。这是和Memcached相比一个最大的区别。当物理内存用完时,Redis可以将一些很久没用到的value交换到磁盘。Redis只会缓存所有的key的信息,如果Redis发现内存的使用量超过了某一个阀值,将触发swap的操作,Redis根据“swappability = age*log(size_in_memory)”计算出哪些key对应的value需要swap到磁盘。然后再将这些key对应的value持久化到磁盘中,同时在内存中清除。这种特性使得Redis可以保持超过其机器本身内存大小的数据。当然,机器本身的内存必须要能够保持所有的key,毕竟这些数据是不会进行swap操作的。同时由于Redis将内存中的数据swap到磁盘中的时候,提供服务的主线程和进行swap操作的子线程会共享这部分内存,所以如果更新需要swap的数据,Redis将阻塞这个操作,直到子线程完成swap操作后才可以进行修改。当从Redis中读取数据的时候,如果读取的key对应的value不在内存中,那么Redis就需要从swap文件中加载相应数据,然后再返回给请求方。 这里就存在一个I/O线程池的问题。在默认的情况下,Redis会出现阻塞,即完成所有的swap文件加载后才会相应。这种策略在客户端的数量较小,进行批量操作的时候比较合适。但是如果将Redis应用在一个大型的网站应用程序中,这显然是无法满足大并发的情况的。所以Redis运行我们设置I/O线程池的大小,对需要从swap文件中加载相应数据的读取请求进行并发操作,减少阻塞的时间。对于像Redis和Memcached这种基于内存的数据库系统来说,内存管理的效率高低是影响系统性能的关键因素。传统C语言中的malloc/free函数是最常用的分配和释放内存的方法,但是这种方法存在着很大的缺陷:首先,对于开发人员来说不匹配的malloc和free容易造成内存泄露;其次频繁调用会造成大量内存碎片无法回收重新利用,降低内存利用率;最后作为系统调用,其系统开销远远大于一般函数调用。所以,为了提高内存的管理效率,高效的内存管理方案都不会直接使用malloc/free调用。Redis和Memcached均使用了自身设计的内存管理机制,但是实现方法存在很大的差异,下面将会对两者的内存管理机制分别进行介绍。Memcached默认使用Slab Allocation机制管理内存,其主要思想是按照预先规定的大小,将分配的内存分割成特定长度的块以存储相应长度的key-value数据记录,以完全解决内存碎片问题。Slab Allocation机制只为存储外部数据而设计,也就是说所有的key-value数据都存储在Slab Allocation系统里,而Memcached的其它内存请求则通过普通的malloc/free来申请,因为这些请求的数量和频率决定了它们不会对整个系统的性能造成影响Slab Allocation的原理相当简单。 如图所示,它首先从操作系统申请一大块内存,并将其分割成各种尺寸的块Chunk,并把尺寸相同的块分成组Slab Class。其中,Chunk就是用来存储key-value数据的最小单位。每个Slab Class的大小,可以在Memcached启动的时候通过制定Growth Factor来控制。假定图中Growth Factor的取值为1.25,如果第一组Chunk的大小为88个字节,第二组Chunk的大小就为112个字节,依此类推。当Memcached接收到客户端发送过来的数据时首先会根据收到数据的大小选择一个最合适的Slab Class,然后通过查询Memcached保存着的该Slab Class内空闲Chunk的列表就可以找到一个可用于存储数据的Chunk。当一条数据库过期或者丢弃时,该记录所占用的Chunk就可以回收,重新添加到空闲列表中。从以上过程我们可以看出Memcached的内存管理制效率高,而且不会造成内存碎片,但是它最大的缺点就是会导致空间浪费。因为每个Chunk都分配了特定长度的内存空间,所以变长数据无法充分利用这些空间。如图 所示,将100个字节的数据缓存到128个字节的Chunk中,剩余的28个字节就浪费掉了。Redis的内存管理主要通过源码中zmalloc.h和zmalloc.c两个文件来实现的。Redis为了方便内存的管理,在分配一块内存之后,会将这块内存的大小存入内存块的头部。如图所示,real_ptr是redis调用malloc后返回的指针。redis将内存块的大小size存入头部,size所占据的内存大小是已知的,为size_t类型的长度,然后返回ret_ptr。当需要释放内存的时候,ret_ptr被传给内存管理程序。通过ret_ptr,程序可以很容易的算出real_ptr的值,然后将real_ptr传给free释放内存。Redis通过定义一个数组来记录所有的内存分配情况,这个数组的长度为ZMALLOC_MAX_ALLOC_STAT。数组的每一个元素代表当前程序所分配的内存块的个数,且内存块的大小为该元素的下标。在源码中,这个数组为zmalloc_allocations。zmalloc_allocations[16]代表已经分配的长度为16bytes的内存块的个数。zmalloc.c中有一个静态变量used_memory用来记录当前分配的内存总大小。所以,总的来看,Redis采用的是包装的mallc/free,相较于Memcached的内存管理方法来说,要简单很多。3、数据持久化支持Redis虽然是基于内存的存储系统,但是它本身是支持内存数据的持久化的,而且提供两种主要的持久化策略:RDB快照和AOF日志。而memcached是不支持数据持久化操作的。1)RDB快照Redis支持将当前数据的快照存成一个数据文件的持久化机制,即RDB快照。但是一个持续写入的数据库如何生成快照呢?Redis借助了fork命令的copy on write机制。在生成快照时,将当前进程fork出一个子进程,然后在子进程中循环所有的数据,将数据写成为RDB文件。我们可以通过Redis的save指令来配置RDB快照生成的时机,比如配置10分钟就生成快照,也可以配置有1000次写入就生成快照,也可以多个规则一起实施。这些规则的定义就在Redis的配置文件中,你也可以通过Redis的CONFIG SET命令在Redis运行时设置规则,不需要重启Redis。Redis的RDB文件不会坏掉,因为其写操作是在一个新进程中进行的,当生成一个新的RDB文件时,Redis生成的子进程会先将数据写到一个临时文件中,然后通过原子性rename系统调用将临时文件重命名为RDB文件,这样在任何时候出现故障,Redis的RDB文件都总是可用的。同时,Redis的RDB文件也是Redis主从同步内部实现中的一环。RDB有他的不足,就是一旦数据库出现问题,那么我们的RDB文件中保存的数据并不是全新的,从上次RDB文件生成到Redis停机这段时间的数据全部丢掉了。在某些业务下,这是可以忍受的。2)AOF日志AOF日志的全称是append only file,它是一个追加写入的日志文件。与一般数据库的binlog不同的是,AOF文件是可识别的纯文本,它的内容就是一个个的Redis标准命令。只有那些会导致数据发生修改的命令才会追加到AOF文件。每一条修改数据的命令都生成一条日志,AOF文件会越来越大,所以Redis又提供了一个功能,叫做AOF rewrite。其功能就是重新生成一份AOF文件,新的AOF文件中一条记录的操作只会有一次,而不像一份老文件那样,可能记录了对同一个值的多次操作。其生成过程和RDB类似,也是fork一个进程,直接遍历数据,写入新的AOF临时文件。在写入新文件的过程中,所有的写操作日志还是会写到原来老的AOF文件中,同时还会记录在内存缓冲区中。当重完操作完成后,会将所有缓冲区中的日志一次性写入到临时文件中。然后调用原子性的rename命令用新的AOF文件取代老的AOF文件。AOF是一个写文件操作,其目的是将操作日志写到磁盘上,所以它也同样会遇到我们上面说的写操作的流程。在Redis中对AOF调用write写入后,通过appendfsync选项来控制调用fsync将其写到磁盘上的时间,下面appendfsync的三个设置项,安全强度逐渐变强。appendfsync no 当设置appendfsync为no的时候,Redis不会主动调用fsync去将AOF日志内容同步到磁盘,所以这一切就完全依赖于操作系统的调试了。对大多数Linux操作系统,是每30秒进行一次fsync,将缓冲区中的数据写到磁盘上。appendfsync everysec 当设置appendfsync为everysec的时候,Redis会默认每隔一秒进行一次fsync调用,将缓冲区中的数据写到磁盘。但是当这一次的fsync调用时长超过1秒时。Redis会采取延迟fsync的策略,再等一秒钟。也就是在两秒后再进行fsync,这一次的fsync就不管会执行多长时间都会进行。这时候由于在fsync时文件描述符会被阻塞,所以当前的写操作就会阻塞。所以结论就是,在绝大多数情况下,Redis会每隔一秒进行一次fsync。在最坏的情况下,两秒钟会进行一次fsync操作。这一操作在大多数数据库系统中被称为group commit,就是组合多次写操作的数据,一次性将日志写到磁盘。appednfsync always 当设置appendfsync为always时,每一次写操作都会调用一次fsync,这时数据是最安全的,当然,由于每次都会执行fsync,所以其性能也会受到影响。对于一般性的业务需求,建议使用RDB的方式进行持久化,原因是RDB的开销并相比AOF日志要低很多,对于那些无法忍数据丢失的应用,建议使用AOF日志。4、集群管理的不同Memcached是全内存的数据缓冲系统,Redis虽然支持数据的持久化,但是全内存毕竟才是其高性能的本质。作为基于内存的存储系统来说,机器物理内存的大小就是系统能够容纳的最大数据量。如果需要处理的数据量超过了单台机器的物理内存大小,就需要构建分布式集群来扩展存储能力。Memcached本身并不支持分布式,因此只能在客户端通过像一致性哈希这样的分布式算法来实现Memcached的分布式存储。下图给出了Memcached的分布式存储实现架构。当客户端向Memcached集群发送数据之前,首先会通过内置的分布式算法计算出该条数据的目标节点,然后数据会直接发送到该节点上存储。但客户端查询数据时,同样要计算出查询数据所在的节点,然后直接向该节点发送查询请求以获取数据。相较于Memcached只能采用客户端实现分布式存储,Redis更偏向于在服务器端构建分布式存储。最新版本的Redis已经支持了分布式存储功能。Redis Cluster是一个实现了分布式且允许单点故障的Redis高级版本,它没有中心节点,具有线性可伸缩的功能。下图给出Redis Cluster的分布式存储架构,其中节点与节点之间通过二进制协议进行通信,节点与客户端之间通过ascii协议进行通信。在数据的放置策略上,Redis Cluster将整个key的数值域分成4096个哈希槽,每个节点上可以存储一个或多个哈希槽,也就是说当前Redis Cluster支持的最大节点数就是4096。Redis Cluster使用的分布式算法也很简单:crc16( key ) % HASH_SLOTS_NUMBER。为了保证单点故障下的数据可用性,Redis Cluster引入了Master节点和Slave节点。在Redis Cluster中,每个Master节点都会有对应的两个用于冗余的Slave节点。这样在整个集群中,任意两个节点的宕机都不会导致数据的不可用。当Master节点退出后,集群会自动选择一个Slave节点成为新的Master节点。

Spring redis存放数据后在cli取出数据为nil,请问是什么原因

Spring redis存放数据后在cli取出数据为nil,请问是什么原因redis默认的数据库是0~15一共16个数据库,可以通过配置再改多或改少数据库。 可以使用select来选择要查看的数据库。

英语You can redistribute it怎么翻译?

you can redistribute it .你可以重新分配它。redistribute再分配;重新分配

魔兽中有哪些秘籍命令?比如输如“greedisgood”就可以加钱。

魔兽争霸秘籍在战役模式下(多人游戏不可),敲回车,会出来对话框,然后把下面字符输入即可 无敌并一击必杀: whosyourdaddy 无限能量: thereisnospoon 魔兽争霸秘籍 任务模式里即使失败也继续游戏: strengthandhonor 地图全开: iseedeadpeople 魔兽争霸秘籍 立即胜利: allyourbasearebelongtous 立即失败: somebodysetusupthebomb 禁止任务默认的胜利条件: itvexesme 加黄金: keysersoze [黄金数量](如果未指定数量默认增加500) 加木材: leafittome [木材数量](如果未指定数量默认增加500) 加黄金和木材: greedisgood [数量](如果未指定数量默认增加500) 魔兽争霸秘籍 快速建造: warpten 无人口上限: pointbreak 快速研究技能: whoisjohngalt 快速升级: sharpandshiny 解除科技树限制: synergy 魔兽争霸秘籍 将时间直接设定到白昼: riseandshine 将时间直接设定到夜晚: lightsout 设定具体时间: daylightsavings [小时数] 让时间永远停留在白昼: daylightsavings 魔兽争霸秘籍 等级选择: motherland [种族] [等级] Cool down时间为0。即放完一个魔法立刻可以放第二次。。

redis中使用multi和pipeline以及不使用这两名字的区别

看了手册的都知道multi这个命令的作用就好比是mysql的事务的功能,但是大家都知道事务吗,就是在操作的过程中,把整个操作当作一个原子来处理,避免由于中途出错而导致最后产生的数据不一致,而产生BUG ,Mysql的事务功能可以做到这点,但是在redis中的multi,手册中说是把多个命令当作个事务来处理,但是在真正的测试之后发现并没有所说的事务的功能,个人经过测试发现,只有把他watch命令结合起来用,方可显现出其具有事务的功能,所以这点很是迷惑,关键是有一点很诧异,当启用了multi命令之后整个redis的读写会相对于没有使用multi的的读写要慢一点,我通过读写100W条数据发现,他们的速度相差600多毫秒,搞不清楚为什么相差这么多!个人觉得没有必要,还是不要使用这个multi的为好!

关于redis批量获取数据pipeline

Redis是建立在TCP协议上的CS架构,客户端client对redis server采取请求响应的方式交互.每次交互会有网络延迟,大约30ms. 假设有这样一个场景,redis中存储上千个key值,获取每个key对应field的value,那么要向redis请求上千次 hget(key, field),获取响应也是对应的次数.如果能一次性将所有请求提交给server端,执行完成后批量获取响应,只需向redis请求1次,性能获大幅提升 没有用pipeline之前,基本上获取所有数据需要90多s,现在只需0.3s,性能提升清晰可见 实现以下场景:定时任务每隔1s执行任务函数,但是任务函数执行完成的时间比1s要长,此时启动定时任务要加上两个参数,否则会报错 可允许的实例个数,如果没有设置,则默认为1,表示id相同的任务实例数 像上面的例子中,会报skipped: maximum number of running instances reached (1)的错误,意思APScheduler试图重新执行作业,但前一个仍在运行。 这个参数可以理解为任务的超时容错配置,给executor 一个超时时间,这个时间范围内要是该跑的还没跑完,就别再跑了 像上面的例子中,会报Run time of job …… next run at: ……)” was missed by的错误

Redis pipeline以及批量优化

Redis基于Request/Response 协议。通常情况下一次请求的步骤如下 1 客户端通过tcp 协议发送指令到服务端,等待redis服务端返回结果 2 redis服务端执行命令,返回响应到客户端。 客户端发送请求到接受到服务端返回的响应被称为一次RTT(Round Trip Time). 在不考虑redis 服务端处理耗时的情况下,数据传输的耗时是最要的开销。且redis client 必须等待上一次响应结果才能发送下一个指令,会长时间处于阻塞的状态。 为解决提升reids服务端的吞吐量,redis提供了如下几种解决方案。 redis实现了HMGET/HMSET/MSET/MGET等一系列批量指令。区别与普通指令如GET, MGET可以一次性发送key数组,然后redis服务端一次性返回结果数组。 很明显这种方式可以使用一次RTT处理完多个指令。这种方式的在性能上是最好的,缺点在于 1. 指令类型必须一致,批量指令依赖于Redis的实现,有些指令如setbit 没有批量实现的,就无法使用这种方案。 2. 不能混合指令发送,需要发送的指令必须在一次请求中确定。灵活性比pipeline差。 pipelining 是Request/Reponse协议的一种实现方式。客户端连续发送请求,而不用等待上一次的response返回。最终通过一次读取之前所有的Response。Redis服务支持这种实现方式。 我们通过redis-benchmark对比下普通cs模型和pipleline的性能。 从上面测试结果可以看出pipleline的性能远高于普通的请求方式。 1. pipeline的RTT交互次数,从而减少延迟,在网络延迟比较大的环境下。吞吐量提高会特别明显。 2. redis客户端/服务端减少了sys_call调用次数,减少了用户态到内核态的切换开销。 3. redis客户端发送无需等待上一次response请求结果,减少了阻塞时间。 Pipelining is not just a way in order to reduce the latency cost due to the round trip time, it actually improves by a huge amount the total operations you can perform per second in a given Redis server. This is the result of the fact that, without using pipelining, serving each command is very cheap from the point of view of accessing the data structures and producing the reply, but it is very costly from the point of view of doing the socket I/O. This involves calling the read() and write() syscall, that means going from user land to kernel land. The context switch is a huge speed penalty. Redis-Bloomfilter在1.0.0版本时,操作redis是基于标准的request/response模式, 但是Bloomfilter 在精度和预计插入数量大的情况,需要做多次hash操作。这样一次bloomfilter操作需要进行几十次redis setbit/getbit。这种情况下会严重影响Bloomfilter的吞吐量。由于setbit/getbit 不支持批量操作,所以采用pipeline来优化redis的性能开销。具体可以参考 https://github.com/ttting/redis-bloomfilter 的实现方式。 另外增加对于基于redistemplate的支持。

剑三安装vcredist路径一直找不到

JX33rdParty下不是有安装文件么?直接打开用就行了啊

怎样设置redis cluster的日志输出

redis.conf配置改logfile “”改为logfile /tmp/redis7000.log

php连接redis 报错 Permission denied,为什么会出现这样的错误

1$redis->zAdd("key", 1, "val1");2$redis->zAdd("key", 0, "val0");3$redis->zAdd("key", 5, "val5");4$redis->zRange("key", 0, -1); // array(val0, val1, val5)向名称为key的zset中添加元素member,score用于排序。如果该元素已经存在,则根据score更新该元素的顺序。

crmeb的redis前缀可以随便改吗

不可以。crmeb的redis前缀是不可以随便改的,需要遵守规定。单词中位于词根前面的部分就是前缀。前缀,可以改变单词的意思。

Redis“气急败坏”回击:13 年来,总有人想替 Redis 换套新架构

今年年中,一位前谷歌、前亚马逊的工程师推出了他创作的开源内存数据缓存系统 Dragonfly,用 C/C++ 编写,基于 BSL 许可(Business Source License)分发。 根据过往的基准测试结果来看, Dragonfly 可能是世界上最快的内存存储系统,它提供了对 Memcached 和 Redis 协议的支持,但能够以更高的性能进行查询,运行时内存消耗也更少。与 Redis 相比,Dragonfly 在典型工作负载下实现了 25 倍的性能提升;单个 Dragonfly 服务器每秒可以处理数百万个请求;在 5GB 存储测试中,Dragonfly 所需的内存比 Redis 少 30%。 作为一个开源软件,Dragonfly 在短短两个月获得了 9.2K GitHub 星,177 个 fork 分支。虽然这些年,涌现了不少类似的 Redis 兼容型内存数据存储系统,例如 KeyDB、Skytable,但是都没能像这次这么“轰动”。毕竟 Redis 诞生了十多年,这时从头开始设计一个缓存系统,可以抛弃 历史 包袱,更好地利用资源。 为回击新冒头的 Dragonfly,Redis 的联合创始人兼 CTO Yiftach Shoolman 和 Redis Labs 的首席架构师 Yossi Gottlieb、Redis Labs 的性能工程师 Filipe Oliveira 联合发布了一篇名为《13 年后,Redis 是否需要新的架构》的文章。 在文章中,他们特地给出了自认更加公平的 Redis 7.0 vs. Dragonfly 基准测试结果:Redis 的吞吐量比 Dragonfly 高 18% - 40%,以及一些有关 Redis 架构的观点和思考,以证明 “为什么 Redis 的架构仍然是内存实时数据存储(缓存、数据库,以及介于两者之间的所有内容)的最佳架构”。 虽然他们强调 Redis 架构仍然是同类最佳,但也没法忽视 Dragonfly 这些新软件提供的一些新鲜、有趣的想法和技术,Redis 表示其中的一些甚至有可能在未来进入 Redis(比如已经开始研究的 io_uring 、更现代的 dictionaries、更有策略地使用线程等)。 另外,Redis 指出 Dragonfly 基准测试的比较方法 “不能代表 Redis 在现实世界中的运行方式” 。对此,Reddit 上有网友反驳称: 还有人表示,这篇文章是 Redis 团队在有礼貌地否认“Dragonfly 是最快的缓存系统”,但更多网友表示,Redis 发文章进行“回击”,就已经代表他们的营销部门输了: 我们当然一直在寻求为 Redis 提升性能、扩充功能的创新方向,但这里我们想聊聊自己的观点和思考,阐释 Redis 时至今日为何仍是最出色的实时内存数据存储(包括缓存、数据库以及介于二者之间的一切)方案之一。 接下来,我们将重点介绍 Redis 对于速度和架构差异的观点,再以此为基础做出比较。在文章的最后,我们还会提供基准测试结果、与 Dragonfly 项目的详尽性能比较信息,欢迎大家自行对比参考。 Dragonfly 基准测试其实是将独立单进程 Redis 实例(只能使用单一核心)与多线程 Dragonfly 实例(可以使用虚拟机 / 服务器上的全部可用核心)进行比较。很明显,这样的粗暴比较并不能代表 Redis 在现实场景下的运行状态。作为技术构建者,我们希望更确切地把握自有技术同其他方案间的差异,所以这里我们做了一点公平性调整:将具有 40 个分片的 Redis 7.0 集群(可使用其中的大部分实例核心)与 Dragonfly 团队在基准测试中使用的最大实例类型(AWS c4gn.16xlarge)进行性能比较。 在这轮测试中,我们看到 Redis 的吞吐量比 Dragonfly 要高出 18% 至 40%,而这还仅仅只用到全部 64 个 vCore 中的 40 个。 在我们看来,每一位多线程项目的开发者在立项之前,都会根据以往工作中经历过的痛点来指导架构决策。我们也承认,在多核设备上运行单一 Redis 进程(这类设备往往提供几十个核心和数百 GB 内存)确实存在资源无法充分利用的问题。但 Redis 在设计之初也确实没有考虑到这一点,而且众多 Redis 服务商已经拿出了相应的解决方案,借此在市场上占得一席之地。 Redis 通过运行多个进程(使用 Redis 集群)实现横向扩展,包括在单一云实例背景下也是如此。在 Redis 公司,我们进一步拓展这个概念并建立起 Redis Enterprise。Redis Enterprise 提供管理层,允许用户大规模运行 Redis,并默认启用高可用性、即时故障转移、数据持久与备份等功能。 下面,我们打算分享幕后使用的一些原则,向大家介绍我们如何为 Redis 的生产应用设计良好的工程实践。 通过在每个虚拟机上运行多个 Redis 实例,我们可以: 我们不允许单一 Redis 进程的大小超过 25 GB(运行 Redis on Flash 时上限为 50 GB)。如此一来,我们就能: 以横向扩展的方式灵活运行内存数据存储,是 Redis 获得成功的关键。下面来看具体原因: 我们仍然欣赏由社区提出的种种有趣思路和技术方案。其中一部分有望在未来进入 Redis(我们已经开始研究 io_uring、更现代的字典、更丰富的线程使用策略等)。但在可预见的未来,我们不会放弃 Redis 所坚守的无共享、多进程等基本架构原则。这种设计不仅具备最佳性能、可扩展性和弹性,同时也能够支持内存内实时数据平台所需要的各类部署架构。 附录:Redis 7.0 对 Draonfly 基准测试细节 版本: 目标: 客户端配置: 资源利用与配置优化: 最后,我们还发现 Redis 和 Dragonfly 都不受网络每秒数据包或传输带宽的限制。我们已经确认在 2 个虚拟机间(分别作为客户端和服务器,且均使用 c6gn.16xlarge 实例)使用 TCP 传递约 300 B 大小的数据包负载时,可以让每秒数据包传输量达到 1000 万以上、传输带宽超过 30 Gbps。 单 GET 通道延迟低于 1 毫秒: 30 条 GET 通道: 单 SET 通道延迟低于 1 毫秒: 30 条 SET 通道: 用于各变体的 memtier_benchmark 命令: 单 GET 通道延迟低于 1 毫秒 30 条 GET 通道 单 SET 通道延迟低于 1 毫秒 30 条 SET 通道 在本次比较测试中,我们在客户端(用于运行 memtier_benchmark)和服务器(用于运行 Redis 和 Dragonfly)使用了相同的虚拟机类型,具体规格为: 参考链接: https://redis.com/blog/redis-architecture-13-years-later/ https://www.reddit.com/r/programming/comments/wiztpx/redis_hits_back_at_dragonfly/ 原文链接:https://www.infoq.cn/article/AlF5NIhHdskayl0MTyQG

failedtoconnecttothedisplayunit

无法连接到显示单元。1.在本地连接点击右键,选诊断后,在已找到的问题中显示“本地连接”没有有效的IP配置.查看网络连接详细信息。2.再次检查八口交换机,发现总线端口处的指示灯有时亮有时又不亮,更换端口后,仍然无法正常上网,根据墙壁模块的。3.由此判断应是汇聚交换机至墙壁模块的线路出现问题。

Ledisi的《Say No》 歌词

歌曲名:Say No歌手:Ledisi专辑:Turn Me Loose/It"S ChristmasLedisi - Say NoC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightNo please say yes‘cause I need to feel you next to meI need your love andI"m not gonna say no not tonightTonight is not the nightthat I"m gonna run from youMy body needs your touchand you"re not gonna hear no not tonightWhat I feel is taking overI lost myself, I"m throughCan"t control what I"m feelin""Been runnin; but I run back to youYour eyes is like a mirrorI know you feel it tooMight be a sin tonight this yearnin"only ends when I"m with youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightWe keep playing gamesA kiss here it"s all the sameIt"s time to go all the wayI want to know what I"ve been waiting forYou move just the oceanYour lips I can"t ignoreYour hands might know the secretsWe ain"t even deep and I want moreSee we can"t pretend likewe don"t want to taste the sweetnessChocolate caramel ice creamon a dream float with red wineMy mind is somewhere elseMy soul wants to exploreYou look at me and it"s overNo need for wordsYou know that I adore youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightI"m not gonna say noI"m not gonna say noI"m not gonna say noNot tonightWhatever you wantWhatever you wantI got it for youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonighthttp://music.baidu.com/song/9370556

Ledisi的《Say No》 歌词

歌曲名:Say No歌手:Ledisi专辑:Turn Me LooseLedisi - Say NoC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightNo please say yes‘cause I need to feel you next to meI need your love andI"m not gonna say no not tonightTonight is not the nightthat I"m gonna run from youMy body needs your touchand you"re not gonna hear no not tonightWhat I feel is taking overI lost myself, I"m throughCan"t control what I"m feelin""Been runnin; but I run back to youYour eyes is like a mirrorI know you feel it tooMight be a sin tonight this yearnin"only ends when I"m with youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightWe keep playing gamesA kiss here it"s all the sameIt"s time to go all the wayI want to know what I"ve been waiting forYou move just the oceanYour lips I can"t ignoreYour hands might know the secretsWe ain"t even deep and I want moreSee we can"t pretend likewe don"t want to taste the sweetnessChocolate caramel ice creamon a dream float with red wineMy mind is somewhere elseMy soul wants to exploreYou look at me and it"s overNo need for wordsYou know that I adore youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightI"m not gonna say noI"m not gonna say noI"m not gonna say noNot tonightWhatever you wantWhatever you wantI got it for youC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonightC"mon we can do whatever we wantI don"t mind do whatever you wantIt"s alright do whatever you wantI"m not gonna say no not tonighthttp://music.baidu.com/song/547136

【Redis】Redis Cluster-集群数据迁移

Redis通过对KEY计算hash,将KEY映射到slot,集群中每个节点负责一部分slot的方式管理数据,slot最大个数为16384。 在集群节点对应的结构体变量clusterNode中可以看到slots数组,数组的大小为CLUSTER_SLOTS除以8,CLUSTER_SLOTS的值是16384: clusterState clusterNode里面保存了节点相关的信息,集群数据迁移信息并未保存在clusterNode中,而是使用了clusterState结构体来保存: clusterState与clusterNode的关系 在手动进行数据迁移时,需要执行以下步骤: 在进行数据迁移之前,首先在需要迁入的目标节点使用 SETSLOT 命令标记要将SLOT从哪个节点迁入到当前节点: 然后在源节点也就是slot所在节点使用 MIGRATING 命令标记将数据迁出到哪个节点: 比如slot1当前在node1中,需要将slot1迁出到node2,那么首先在nodd2上执行 IMPORTING 命令,标记slot准备从node1迁到当前节点node2中: 然后在node1中执行 MIGRATING 命令标记slot1需要迁移到node2: clusterCommand SETSLOT 命令的处理在clusterCommand函数(cluster.c文件中)中: 在标记完迁入、迁出节点后,就可以使用 CLUSTER GETKEYSINSLOT 命令获取待迁出的KEY: <slot>:哈希槽的值 <count>:迁出KEY的数量 getkeysinslot 命令的处理也在clusterCommand函数中,处理逻辑如下: 完成上两步之后,接下来需要在源节点中执行 MIGRATE 命令进行数据迁移, MIGRATE 既支持单个KEY的迁移,也支持多个KEY的迁移,语法如下: migrateCommand MIGRATE 命令对应的处理函数在migrateCommand中(cluster.c文件中),处理逻辑如下: createDumpPayload createDumpPayload函数在cluster.c文件中: restoreCommand 目标节点收到迁移的数据的处理逻辑在restoreCommand中(cluster.c文件中): 数据迁移的最后一步, 需要使用 CLUSTER SETSLOT 命令,在源节点和目标节点执行以下命令,标记slot最终所属的节点,并清除第一步中标记的迁移信息 : <slot>:哈希槽 <node>:哈希槽最终所在节点id clusterCommand CLUSTER SETSLOT <slot> NODE <node> 命令的处理依旧在 clusterCommand 函数中,处理逻辑如下: 总结 参考 极客时间 - Redis源码剖析与实战(蒋德钧) Redis版本:redis-6.2.5

018.Redis Cluster故障转移原理

当集群内某个节点出现问题时,需要通过一种健壮的方式保证识别出节点是否发生了故障。Redis集群内节点通过ping/pong消息实现节点通信,消息不但可以传播节点槽信息,还可以传播其他状态如:主从状态、节点故障等。因此故障发现也是通过消息传播机制实现的,主要环节包括: 主观下线(PFAIL-Possibly Fail) 和 客观下线(Fail) 一个节点认为某个节点失联了并不代表所有的节点都认为它失联了。所以集群还得经过一次协商的过程,只有当大多数节点都认定了某个节点失联了,集群才认为该节点需要进行主从切换来容错。Redis 集群节点采用 Gossip 协议来广播自己的状态以及自己对整个集群认知的改变。比如一个节点发现某个节点失联了(PFail),它会将这条信息向整个集群广播,其它节点也就可以收到这点失联信息。如果一个节点收到了某个节点失联的数量 (PFail Count) 已经达到了集群的大多数,就可以标记该节点为确定下线状态 (Fail),然后向整个集群广播,强迫其它节点也接收该节点已经下线的事实,并立即对该失联节点进行主从切换。 集群中每个节点都会定期向其他节点发送ping消息,接收节点回复pong消息作为响应。如果在 cluster-node-timeout 时间内通信一直失败,则发送节点会认为接收节点存在故障,把接收节点标记为主观下线(PFail)状态 主观下线简单来讲就是,当 cluster-note-timeout 时间内某节点无法与另一个节点顺利完成ping消息通信时,则将该节点标记为主观下线状态 Redis集群对于节点最终是否故障判断非常严谨,只有一个节点认为主观下线并不能准确判断是否故障。当某个节点判断另一个节点主观下线后,相应的节点状态会跟随消息在集群内传播,通过Gossip消息传播,集群内节点不断收集到故障节点的下线报告。当 半数以上持有槽的主节点 都标记某个节点是主观下线时。触发客观下线流 程。 为什么必须是负责槽的主节点参与故障发现决策? 因为集群模式下只有处理槽的主节点才负责读写请求和集群槽等关键信息维护,而从节点只进行主节点数据和状态信息的复制。 为什么半数以上处理槽的主节点? 必须半数以上是为了应对网络分区等原因造成的集群分割情况,被分割的小集群因为无法完成从主观下线到 客观下线这一关键过程,从而防止小集群完成故障转移之后继续对外提供服务。 客观下线流程: 注意: 如果在 cluster-node-time*2 时间内无法收集到一半以上槽节点的下线报告,那么之前的下线报告将会过期,也就是说主观下线上报的速度追赶不上下线报告过期的速度,那么故障节点将永远无法被标记为客观下线从而导致 故障转移失败。因此不建议将 cluster-node-time 设置得过小 广播fail消息是客观下线的最后一步,它承担着非常重要的职责: 需要理解的是,尽管存在广播fail消息机制,但是集群所有节点知道故障节点进入客观下线状态是不确定的。比如当出现网络分区时有可能集群被分割为一大一小两个独立集群中。大的集群持有半数槽节点可以完成客观下线并广播fail消息,但是小集群无法接收到fail消息,网络分区会导致分割后的小集群无法收到大集群的fail消息,因此如果故障节点所有的从节点都在小集群内将导致无法完成后续故障转移,因此部署主从结构时需要根据自身机房/机架拓扑结构,降低主从被分区的可能性。 故障节点变为客观下线后,如果下线节点是持有槽的主节点则需要在它的从节点中选出一个替换它,从而保证集群的高可用。下线主节点的所有从节点承担故障恢复的义务,当从节点通过内部定时任务发现自身复制的主节点进入客观下线时,将会触发故障恢复流程

【Redis】Redis Cluster-集群故障转移

在集群定时任务 clusterCron 中,会遍历集群中的节点,对每个节点进行检查,判断节点是否下线。与节点下线相关的状态有两个,分别为 CLUSTER_NODE_PFAIL 和 CLUSTER_NODE_FAIL 。 CLUSTER_NODE_PFAIL :当前节点认为某个节点下线时,会将节点状态改为 CLUSTER_NODE_PFAIL ,由于可能存在误判,所以需要根据集群中的其他节点共同决定是否真的将节点标记为下线状态, CLUSTER_NODE_PFAIL 可以理解为疑似下线,类似哨兵集群中的主观下线 。 CLUSTER_NODE_FAIL :集群中有过半的节点标认为节点已下线,此时将节点置为 CLUSTER_NODE_FAIL 标记节点下线, CLUSTER_NODE_FAIL 表示节点真正处于下线状态,类似哨兵集群的客观下线 。 在集群定时任务遍历集群中的节点进行检查时,遍历到的每个节点记为 node ,当前节点记为 myself ,检查的内容主要有以下几个方面: 一、判断孤立主节点的个数 如果当前节点 myself 是从节点,正在遍历的节点 node 是主节点,并且 node 节点不处于下线状态,会判断孤立节点的个数,满足以下三个条件时,认定 node 是孤立节点,孤立节点个数增1: 二、检查连接 这一步主要检查和节点间的连接是否正常,有可能节点处于正常状态,但是连接有问题,此时需要释放连接,在下次执行定时任务时会进行重连,释放连接需要同时满足以下几个条件: 三、疑似下线判断 ping_delay 记录了当前时间距离向 node 节点发送PING消息的时间, data_delayd 记录了 node 节点向当前节点最近一次发送消息的时间,从ping_delay和data_delay中取较大的那个作为延迟时间。 如果延迟时间大于超时时间,判断 node 是否已经处于 CLUSTER_NODE_PFAIL 或者 CLUSTER_NODE_FAIL 状态,如果都不处于,将节点状态置为 CLUSTER_NODE_PFAIL ,认为节点疑似下线。 上述检查完成之后, 会判断当前节点是否是从节点,如果不处于 CLUSTER_MODULE_FLAG_NO_FAILOVER 状态,调用 clusterHandleSlaveFailover 处理故障转移,不过需要注意此时只是将节点置为疑似下线,并不满足故障转移条件,需要等待节点被置为FAIL下线状态之后,再次执行集群定时任务进入到 clusterHandleSlaveFailover 函数中才可以开始处理故障转移。 当前节点认为某个node下线时,会将node状态置为 CLUSTER_NODE_PFAIL 疑似下线状态,在定时向集群中的节点交换信息也就是发送PING消息时,消息体中记录了node的下线状态,其他节点在处理收到的PING消息时, 会将认为node节点下线的那个节点加入到node的下线链表fail_reports中,并调用 markNodeAsFailingIfNeeded 函数判断是否有必要将节点置为下线FAIL状态 : markNodeAsFailingIfNeeded markNodeAsFailingIfNeeded用于判断是否有必要将某个节点标记为FAIL状态: clusterHandleSlaveFailover 由上面的内容可知,节点客观下线时会被置为 CLUSTER_NODE_FAIL 状态,下次执行集群定时任务时,在故障转移处理函数 clusterHandleSlaveFailover 中,就可以根据状态来检查是否需要执行故障转移。 不过在看 clusterHandleSlaveFailover 函数之前,先看一下 clusterState 中和选举以及故障切换相关的变量定义: clusterHandleSlaveFailover函数中的一些变量 data_age : 记录从节点最近一次与主节点进行数据同步的时间 。如果与主节点处于连接状态,用当前时间减去最近一次与master节点交互的时间,否则使用当前时间减去与master主从复制中断的时间。 auth_age : 当前时间减去发起选举的时间 ,也就是距离发起选举过去了多久,用于判断选举超时、是否重新发起选举使用。 needed_quorum : quorum的数量,为集群中节点的数量的一半再加1 。 auth_timeout : 等待投票超时时间。 auth_retry_time : 等待重新发起选举进行投票的时间,也就是重试时间 。 一、故障转移条件检查 首先进行了一些条件检查,用于判断是否有必要执行故障转移,如果 处于以下几个条件之一,将会跳出函数,结束故障转移处理 : 二、主从复制进度校验 cluster_slave_validity_factor 设置了故障切换最大主从复制延迟时间因子,如果不为0需要校验主从复制延迟时间是否符合要求。 如果主从复制延迟时间 data_age 大于 mater向从节点发送PING消息的周期 + 超时时间 * 故障切换主从复制延迟时间因子 并且不是手动执行故障切换,表示主从复制延迟过大,不能进行故障切换终止执行。 三、是否需要重新发起选举 如果距离上次发起选举的时间大于超时重试时间,表示可以重新发起投票。 四、延迟发起选举 五、发起投票 如果满足执行故障的条件,接下来需从节点想集群中的其他节点广播消息,发起投票,不过只有主节点才有投票权。 failover_auth_sent 为0表示还未发起投票,此时开始发起投票: 六、执行故障切换 当某个节点获取到了集群中大多数节点的投票,即可进行故障切换,这里先不关注,在后面的章节会讲。 clusterGetSlaveRank用于计算当前节点的等级,遍历所属主节点的所有从节点,根据主从复制进度 repl_offset 计算, repl_offset 值越大表示复制主节点的数据越多,所以等级越高,对应的 rank 值就越低。 从节点在发起选举使用了 rank 的值作为延迟时间,值越低延迟时间越小,意味着选举优先级也就越高。 当从节点认为主节点故障需要发起投票,重新选举主节点时,在集群中广播了 CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST 消息,对应的处理在 clusterProcessPacket 函数中,里面会调用 clusterSendFailoverAuthIfNeeded 函数进行投票: clusterSendFailoverAuthIfNeeded clusterSendFailoverAuthIfNeeded函数用于进行投票,处理逻辑如下: 以上条件校验通过, 表示当前节点可以投票给发送请求的节点,此时更新 lastVoteEpoch ,记录最近一次投票的纪元(轮次),更新投票时间 node->slaveof->voted_time ,然后向发起请求的节点回复 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 消息。 主节点对发起投票请求节点的回复消息 CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK 同样在消息处理函数 clusterProcessPacket 中,会对发送回复消息的节点进行验证: 同时满足以上三个条件时, 表示发送者对当前节点进行了投票,更新当前节点记录的收到投票的个数, failover_auth_count 加1,此时有可能获取了大多数节点的投票,先调用 clusterDoBeforeSleep 设置一个 CLUSTER_TODO_HANDLE_FAILOVER 标记,在周期执行的时间事件中会调用对状态进行判断决定是否执行故障转移。 从节点收到投票后,会添加 CLUSTER_TODO_HANDLE_FAILOVER 标记,接下来看下对 CLUSTER_TODO_HANDLE_FAILOVER 状态的处理。 在 beforeSleep 函数(server.c文件中),如果开启了集群,会调用 clusterBeforeSleep 函数,里面就包含了对 CLUSTER_TODO_HANDLE_FAILOVER 状态的处理: beforeSleep 函数是在Redis事件循环 aeMain 方法中被调用的,详细内容可参考 事件驱动框架源码分析 文章。 clusterBeforeSleep 在clusterBeforeSleep函数中,如果节点带有 CLUSTER_TODO_HANDLE_FAILOVER 标记,会调用 clusterHandleSlaveFailover 函数进行处理: clusterHandleSlaveFailover 函数在上面我们已经见到过,这次我们来关注集群的故障转移处理。 如果当前节点获取了大多数的投票,也就是 failover_auth_count (得到的投票数量)大于等于 needed_quorum , needed_quorum 数量为集群中节点个数的一半+1,即可执行故障转移,接下来会调用 clusterFailoverReplaceYourMaster 函数完成故障转移。 clusterFailoverReplaceYourMaster 如果从节点收到了集群中过半的投票,就可以成为新的master节点,并接手下线的master节点的slot,具体的处理在clusterFailoverReplaceYourMaster函数中,主要处理逻辑如下: 总结

redis cluster集群选主

redis数据淘汰原理 redis过期数据删除策略 redis server事件模型 redis cluster mget 引发的讨论 redis 3.x windows 集群搭建 redis 命令执行过程 redis string底层数据结构 redis list底层数据结构 redis hash底层数据结构 redis set底层数据结构 redis zset底层数据结构 redis 客户端管理 redis 主从同步-slave端 redis 主从同步-master端 redis 主从超时检测 redis aof持久化 redis rdb持久化 redis 数据恢复过程 redis TTL实现原理 redis cluster集群建立 redis cluster集群选主 u2003当slave发现自己的master变为FAIL状态时,便尝试进行Failover,以期成为新的master。由于挂掉的master可能会有多个slave。Failover的过程需要经过类Raft协议的过程在整个集群内达到一致, 其过程如下: u2003在作为slave角色节点会定期发送ping命令来检测master的存活性,如果检测到master未响应,那么就将master节点标记为疑似下线。 u2003clusterHandleSlaveFailover执行重新选主的核心逻辑。u2003clusterHandleSlaveFailover内部通过clusterRequestFailoverAuth方法向集群当中的所有节点发送CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST报文,通知大家slave准备执行failover。 u2003当节点收到超过n/2+1个master的response后即升级为主。u2003在redis主从选举过程中报文相关的解析逻辑,clusterProcessPacket内部主要处理CLUSTERMSG_TYPE_FAILOVER_AUTH_REQUEST和CLUSTERMSG_TYPE_FAILOVER_AUTH_ACK报文。redis cluster集群的源码分析(1) Redis Cluster 实现细节

Redis-Cluster

是一种去中心化的集群架构 Redis Cluster 的性能与单节点部署是同级别的。 多主节点、负载均衡、读写分离 Redis Cluster 支持标准的 主从复制配置来保障高可用和高可靠。 failover (故障转移) Redis Cluster 也实现了一个类似 Raft 的共识方式,来保障整个集群的可用性。 向 Redis Cluster 中添加新节点,或者移除节点,都是透明的,不需要停机。 水平、垂直方向都非常容易扩展。 数据分区,海量数据存储 部署 Redis Cluster 不需要其他的代理或者工具,而且 Redis Cluster 和单机 Redis 几乎完全兼 容。 角色: master、slave Redis Cluster 由多个Redis节点组构成,是一个P2P(point to point)无中心节点的集群架构,依靠Gossip协议传播集群 Gossip协议是一个通信协议,一种传播消息的方式。 思想启发于:病毒传播 这些收到信息的节点接下来会做同样的事情,即把这些信息传递给其他一些随机选择的节点。 信息会周期性的传递给N个目标节点。这个N被称为fanout(扇出) gossip协议包含多种消息,包括meet、ping、pong、fail、publish等等 通过gossip协议,cluster可以提供 集群间状态同步更新 、 选举自助failover 等重要的集群功能。 分布式架构设计中,核心问题即为如何分片数据。在技术的更替中出现过以下分布式hash算法: redis-cluster把所有的物理节点映射到[0-16383]个slot上,基本上采用平均分配和连续分配的方式。 slot槽必须在节点上连续分配,如果出现不连续的情况,则RedisCluster不能工作。 采用 raft 协议(参照Paxos算法 https://www.jianshu.com/p/40c658c9dcc2 ) 当slave 收到过半的master 同意时,会成为新的master。此时会以最新的Epoch 通过PONG 消息广播自己成为master,让Cluster 的其他节点尽快的更新拓扑结构(node.conf)。 就是上面讲的从节点选举 人工故障切换是预期的操作,而非发生了真正的故障,目的是以一种安全的方式(数据无丢失)将当前master节点和其中一个slave节点(执行cluster-failover的节点)交换角色 1、向从节点发送cluster failover 命令(slaveof no one) 2、从节点告知其主节点要进行手动切换(CLUSTERMSG_TYPE_MFSTART) 3、主节点会阻塞所有客户端命令的执行(10s) 4、从节点从主节点的ping包中获得主节点的复制偏移量 5、从节点复制达到偏移量,发起选举、统计选票、赢得选举、升级为主节点并更新配置 6、切换完成后,原主节点向所有客户端发送moved指令重定向到新的主节点 以上是在主节点在线情况下。 如果主节点下线了,则采用cluster failover force或cluster failover takeover 进行强制切换。 扩容 扩容节点数据必须为空 缩容 只能删除数据为空的节点 我们知道在一主一从的情况下,如果主从同时挂了,那整个集群就挂了。 为了避免这种情况我们可以做一主多从,但这样成本就增加了。 Redis提供了一种方法叫副本漂移,这种方法既能提高集群的可靠性又不用增加太多的从机。 Master1宕机,则Slaver11提升为新的Master1 集群检测到新的Master1是单点的(无从机) 集群从拥有最多的从机的节点组(Master3)中,选择节点名称字母顺序最小的从机(Slaver31)漂移 到单点的主从节点组(Master1)。 具体流程如下(以上图为例): 1、将Slaver31的从机记录从Master3中删除 2、将Slaver31的的主机改为Master1 3、在Master1中添加Slaver31为从节点 4、将Slaver31的复制源改为Master1 5、通过ping包将信息同步到集群的其他节点

Redis Cluster集群

redis的搭建可以查看我的上一篇文章: http://www.jianshu.com/p/6356356abebb 搭建redis cluster环境最少需要3个主节点,这里参考官网的示例创建6个节点,其中为3个主节点,3从节点,对应的redis节点IP和端口如下: 下面是一个最少选项的集群的配置文件 创建一个新的目录, 并创建六个以端口号为名字的子目录, 稍后我们在将每个目录中运行一个 Redis 实例: 命令如下: 在文件夹 7000 至 7005 中, 各创建一个 redis.conf 文件, 文件的内容可以使用上面的示例配置文件, 但记得将配置中的端口号和nodes.conf(同一服务器相同名字有冲突)从 7000 改为与文件夹名字相同的号码。 启动cluster实例 实例打印的日志显示, 因为 nodes.conf 文件不存在, 所以每个节点都为它自身指定了一个新的 ID : 实例会一直使用同一个 ID , 从而在集群中保持一个独一无二(unique)的名字. 进入redis目录,用如下命令创建集群。 安装ruby即可 缺少rubygems组件,使用yum安装 提示不能加载redis,是因为缺少redis和ruby的接口,使用gem 安装 在执行集群命令 至此集群模式搭建完成。 使用redis-cli命令进入集群环境,进入集群模式需要带上 -c ,不带则表示进入7000端口的普通redis。 集群 节点 槽(slot) 键 参考地址: https://redis.io/topics/cluster-tutorial

Redis-Cluster集群

在哨兵模式中,仍然只有一个 master 节点。当并发写请求较大时,哨兵模式并不能缓解写压力。 在redis-cluster集群中,每一个主节点可以添加多个从节点,主节点和从节点遵循主从模式的特性。 当用户需要处理更多的读请求时,添加从节点可以扩展系统的读性能。 redis集群的主节点内置了类似Sentinel的节点故障检测和自动故障转移功能。当集群中的某个主节点下线时,集群中的其他在线主节点发现了以后,会对已下线的主节点进行故障转移。集群进行故障转移的方法和Sentient进行故障转移的方法基本一致,不同的是,在集群里面,故障转移是由集群中其他在线的主节点负责进行的,所以集群中不需要使用Sentinel。 redis-cluster集群将键存储空间分割为16384个槽位(slot),事实上集群最大节点数量是16384个【官方建议最大节点数量不超过1000个节点】。 所有主节点都负责16384个哈希槽中的一部分,当16384个槽都有某个节点在负责处理时,集群进入上线状态,并开始处理客户端发送的数据命令请求。 一个slot槽位可以存放多个数据,key的槽位计算公式:HASH_SLOT = CRC16(key) mod 16384 由于Redis集群无中心节点,请求会随机发给任意主节点。 主节点只会处理自己负责槽位的命令请求,其他槽位的命令请求,该主节点会返回客户端一个转向错误。 客户端根据错误中包含的地址和端口重新向正确的负责的主节点发起命令请求。 系统:CentOS7 Redis: 5.0.9 Redis节点 注意: 配置文件主要修改: 执行结果 按照之前的配置修改并启动,使用以下命令将其加入集群: 添加完新节点后,需要对新添加的主节点进行hash槽重新分配,这样该主节点才能存储数据,redis共有16384个槽。 删除从节点192.168.164.13:7000,node_id:cb21c351b3d2378976bf7d215553d0e04d7fad43 执行结果 存在slot的主节点无法直接删除,所以我们需要先移动主节点192.168.164.13:7001的slot至其他三个主节点 查看集群节点信息 删除主节点 执行结果 查看集群信息

解决k8s集群中Redis Cluster故障

k8s集群中的一个node节点故障,将这个node节点下线后上面的pod迁移到其他节点,但是大量pod都产生报错。经排查,是由于redis集群故障导致。但是查看resdis pod,都是running状态,如下图 由于这些pod是组成集群使用,既然pod是正常的,应用又报redis链接的错误,所以问题肯定出在Redis Cluster上,查看Redis Cluster状态: 这个示意图我只画出三个node,简单表达一下意思即可。三个node上各运行了一个master和一个slave节点。由于node3节点故障已经移除集群,这个节点上之前运行的其他无状态pod迁移到其他节点可以正常运行,但是master2和slave2在node3上有持久化数据,虽然在node4上重建了,但是由于缺失数据,原来的集群状态被破坏了,所以重新部署也无法恢复,由于是master2和slave2的数据都丢失了,集群无法重建。通过开发了解到,redis上都是缓存数据,丢失影响不大,于是删除本地持久化数据,重新部署redis node,再手动创建集群。 三个节点都添加完成,并且没有报错。进入一个master节点查看集群状态: 集群状态终于恢复正常。重建后的Redis Cluster集群架构示意图如下 总结:对于有状态的应用,redis、mysql等,容器化时一定要考虑周全,避免主从节点运行在一个节点上。对于redis应用,如果读写I/O不是特别高,还是建议直接使用主从复制架构,故障恢复简单且迅速。

如何通过命令搭建redis-cluster

redis cluster配置好,并运行一段时间后,我们想添加节点,或者删除节点,该怎么办呢。一,redis cluster命令行查看复制打印?//集群(cluster) CLUSTER INFO 打印集群的信息 CLUSTER NODES 列出集群当前已知的所有节点(node),以及这些节点的相关信息。 //节点(node) CLUSTER MEET <ip> <port> 将 ip 和 port 所指定的节点添加到集群当中,让它成为集群的一份子。 CLUSTER FORGET <node_id> 从集群中移除 node_id 指定的节点。 CLUSTER REPLICATE <node_id> 将当前节点设置为 node_id 指定的节点的从节点。 CLUSTER SAVECONFIG 将节点的配置文件保存到硬盘里面。 //槽(slot) CLUSTER ADDSLOTS <slot> [slot ...] 将一个或多个槽(slot)指派(assign)给当前节点。 CLUSTER DELSLOTS <slot> [slot ...] 移除一个或多个槽对当前节点的指派。 CLUSTER FLUSHSLOTS 移除指派给当前节点的所有槽,让当前节点变成一个没有指派任何槽的节点。 CLUSTER SETSLOT <slot> NODE <node_id> 将槽 slot 指派给 node_id 指定的节点,如果槽已经指派给另一个节点,那么先让另一个节点删除该槽>,然后再进行指派。 CLUSTER SETSLOT <slot> MIGRATING <node_id> 将本节点的槽 slot 迁移到 node_id 指定的节点中。 CLUSTER SETSLOT <slot> IMPORTING <node_id> 从 node_id 指定的节点中导入槽 slot 到本节点。 CLUSTER SETSLOT <slot> STABLE 取消对槽 slot 的导入(import)或者迁移(migrate)。 //键 (key) CLUSTER KEYSLOT <key> 计算键 key 应该被放置在哪个槽上。 CLUSTER COUNTKEYSINSLOT <slot> 返回槽 slot 目前包含的键值对数量。 CLUSTER GETKEYSINSLOT <slot> <count> 返回 count 个 slot 槽中的键。 这些命令是集群所独有的。执行上述命令要先登录查看复制打印?[root@manage redis]# redis-cli -c -p 6382 -h 192.168.10.220 //登录 192.168.10.220:6382> cluster info //查看集群情况 cluster_state:ok cluster_slots_assigned:16384 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 --slave --master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2 192.168.10.220:6385 192.168.10.219:6379 注释:--slave,表示添加的是从节点--master-id 03ccad2ba5dd1e062464bc7590400441fafb63f2,主节点的node id,在这里是前面新添加的6378的node id192.168.10.220:6385,新节点192.168.10.219:6379集群任一个旧节点4,重新分配slot查看复制打印?# 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 "all" to use all the nodes as source nodes for the hash slots. Type "done" once you entered all the source nodes IDs. Source node #1:all //表示全部节点重新洗牌 Do you want to proceed with the proposed reshard plan (yes/no)? yes //确认重新分 新增加的主节点,是没有slots的,

Redis Cluster

u200b Redis Cluster 集群分区方案采用去中心化的方式,包括:sharding(分区)、replication(复制)、failover(故障转移) u200b Redis Cluster 由多个Redis节点组构成,是一个P2P(point to point)无中心节点的集群架构,依靠Gossip协议传播集群 Gossip协议是一个通信协议,一种传播消息的方式。 起源于:病毒传播 Gossip协议基本思想: 一个节点周期性(每秒)随机选择一些节点,并把信息传递给这些节点。 这些收到信息的节点接下来会做同样的事情,即把这些信息传递给其他一些随机选择的节点。 信息会周期性的传递给N个目标节点。这个N被称为 fanout (扇出) gossip协议包含多种消息,包括meet、ping、pong、fail、publish等等 通过gossip协议,cluster可以提供集群间状态同步更新、选举自助failover等重要的集群功能。 redis-cluster把所有的物理节点映射到[0-16383]个 slot 上,基本上采用平均分配和连续分配的方式。 比如上图中有5个节点,这样在 Redis Cluster 创建时,slot槽可按下表分配 cluster 负责维护节点和slot槽的对应关系 value------>slot-------->节点 当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把 结果对 16384 求余数,这样每个 key 都会对应一个编号在 0-16383 之间的哈希槽,redis 会根据节点 数量大致均等的将哈希槽映射到不同的节点。 比如: set name zhangsan hash("name")采用crc16算法,得到值:1324203551%16384=15903 根据上表15903在13088-16383之间,所以name被存储在Redis5节点。 slot槽必须在节点上连续分配,如果出现不连续的情况,则RedisCluster不能工作。 redis版本说明 redis.5.0.5 服务器说明 启动 7001、7002、7003、7011、7012、7013 配置启动脚本 三主三从 客户端连接集群 -c 以集群方式连接 扩容节点数据必须为空 启动 7004、7014 将 7004、7014 添加到集群 只能删除数据为空的节点 集群中的每个节点都会定期地(每秒)向集群中的其他节点发送PIN 如果在一定时间内(cluster-node-timeout),发送ping的节点A没有收到某节点B的pong回应,则A将B 标识为pfail。 A在后续发送ping时,会带上B的pfail信息, 通知给其他节点。 如果B被标记为pfail的个数大于集群主节点个数的一半(N/2 + 1)时,B会被标记为fail,A向整个集群 广播,该节点已经下线 其他节点收到广播,标记B为fail。 采用 raft 协议 每个从节点,都根据自己对master复制数据的offset,来设置一个选举时间,offset越大(复制数 据越多)的从节点,选举时间越靠前,优先进行选举。 slave 通过向其他master发送FAILVOER_AUTH_REQUEST 消息发起竞选, master 收到后回复FAILOVER_AUTH_ACK 消息告知是否同意。 slave 发送FAILOVER_AUTH_REQUEST 前会将currentEpoch 自增,并将最新的Epoch 带入到 FAILOVER_AUTH_REQUEST 消息中,如果自己未投过票,则回复同意,否则回复拒绝。 所有的 Master 开始slave选举投票,给要进行选举的slave进行投票,如果大部分master node(N/2 + 1)都投票给了某个从节点,那么选举通过,那个从节点可以切换成master。 RedisCluster失效的判定 : 1、集群中半数以上的主节点都宕机(无法投票) 2、宕机的主节点的从节点也宕机了(slot槽分配不连续) 当slave 收到过半的master 同意时,会成为新的master。此时会以最新的Epoch 通过PONG 消息广播 自己成为master,让Cluster 的其他节点尽快的更新拓扑结构(node.conf)。 自动切换 就是上面讲的从节点选举 手动切换 人工故障切换是预期的操作,而非发生了真正的故障,目的是以一种安全的方式(数据无丢失)将当前 master节点和其中一个slave节点(执行cluster-failover的节点)交换角色 1、向从节点发送cluster failover 命令(slaveof no one) 2、从节点告知其主节点要进行手动切换(CLUSTERMSG_TYPE_MFSTART) 3、主节点会阻塞所有客户端命令的执行(10s) 4、从节点从主节点的ping包中获得主节点的复制偏移量 5、从节点复制达到偏移量,发起选举、统计选票、赢得选举、升级为主节点并更新配置 6、切换完成后,原主节点向所有客户端发送moved指令重定向到新的主节点 以上是在主节点在线情况下。 如果主节点下线了,则采用cluster failover force或cluster failover takeover 进行强制切换。 我们知道在一主一从的情况下,如果主从同时挂了,那整个集群就挂了。 为了避免这种情况我们可以做一主多从,但这样成本就增加了。 Redis提供了一种方法叫副本漂移,这种方法既能提高集群的可靠性又不用增加太多的从机。 Master1宕机,则Slaver11提升为新的Master1 集群检测到新的Master1是单点的(无从机) 集群从拥有最多的从机的节点组(Master3)中,选择节点名称字母顺序最小的从机(Slaver31)漂移 到单点的主从节点组(Master1)。 具体流程如下(以上图为例): 1、将Slaver31的从机记录从Master3中删除 2、将Slaver31的的主机改为Master1 3、在Master1中添加Slaver31为从节点 4、将Slaver31的复制源改为Master1 5、通过ping包将信息同步到集群的其他节点

Redis cluster 原理

Redis cluster 实现了所有的single key 操作,对于multi key操作的话,这些key必须在一个节点上面,redis cluster 通过 hash tags决定key存贮在哪个slot上面。 节点首要功能是存贮数据,集群状态,映射key到相应的节点。自动发现其他节点,发现失败节点,让从变为主。 为了完成以上功能,cluster使用tcp和二进制协议(Redis Cluster Bus),节点间互联.node 同时使用gossip协议传播信息,包括节点的发现,发送ping包,Pub/Sub信息。 因为节点并不代理请求转发,会返回MOVED和ASk错误,clients就可以直连到其他节点。client理论上面可以给任意节点发送请求,如果需要就重定向。但实际应用中client存贮一个从key到node的map来提高性能。 Redis cluster 使用异步复制的模式,故障转移的时候,被选为主的节点,会用自己的数据去覆盖其他副本节点的数据。所以总有一个时间口会丢失数据。 下面一个例子会丢失数据: master partition 变得不可用 它的一个从变为主 一定时间之后,这个主又可用了 客户端这时候还使用旧的的路由,在这个主变为从之前,写请求到达这个主。 3、可用性 假设n个主节点,每个主下面挂载一个从,挂掉一个,集群仍然可用。挂点两个,可用性是1 -(1/(n 2 -1))(第一个节点挂掉后,还剩下n 2-1个节点),只有一个节点的主挂掉的可能性是 1/n*2 -1) replicas migration 使可用性更高 4、性能 reids cluster 不代理请求到正确的节点,而是告诉客户端正确的节点 client 会保存一份最新的key与node映射,一般情况,会直接访问到正确的节点。 异步写副本 一般的操作和单台redis有相同的性能,一个有n个主节点的集群性能接近n*单个redis 综上 高性能 线性扩展 合理的写安全 高可用 是rediscluser 的主要目标 因为首先redis 存贮的数据量会特别大,如果合并需要更大的空间 key空间分布被划分为16384个slot,所以一个集群,主节点的个数最大为16384(一般建议master最大节点数为1000) HASH_SLOT = CRC16(key) mod 16384 hash tag 是为了保证不同的key,可以分布到同一个slot上面,来执行multi-key的操作 hash tag的规则是以第一个{开始,到第一个}结尾,中间的内容,来做hash。 例子 {user1000}.following 与 {user1000}.followers user1000作为key foo{}{bar} 整个key {{bar}} {bar 为key {bar}{zap} bar 为key Ruby Example 从左到右依次为:node id, address:port, flags, last ping sent, last pong received, configuration epoch, link state, slots 其中node id是第一次启动获得的一个160字节的随机字符串,并把id保存在配置文件中,一直不会再变 每个节点有一个额外的TCP端口,这个端口用来和其他节点交换信息。这个端口一般是在与客户端链接端口上面加10000,比如客户端端口为6379,那么cluster bus的端口为16379. node-to-node 交流是通过cluster bus与 cluster bus protocol进行。其中cluster bus protocol 是一个二进制协议,因为官方不建议其他应用与redis 节点进行通信,所以没有公开的文档,要查看的话只能去看源码。 Redis cluster 是一个网状的,每一个节点通过tcp与其他每个节点连接。假如n个节点的集群,每个节点有n-1个出的链接,n-1个进的链接。这些链接会一直存活。假如一个节点发送了一个ping,很就没收到pong,但还没到时间把这个节点设为 unreachable,就会通过重连刷新链接。 node 会在cluster bus端口一直接受连接,回复ping,即使这个ping 的node是不可信的。但是其他的包会被丢掉,如果发送者不是cluster 一员。 一个node有两种方式接受其他其他node作为集群一员 这样只要我们把节点加入到一个节点,就会自动被其他节点自动发现。 客户端可以自由的连接任何一个node,如果这个node 不能处理会返回一个MOVED的错误,类似下面这样 描述了key 的hash slot,属于哪个node client 会维护一个hash slots到IP:port的映射 当收到moved错误的时候,可以通过CLUSTER NODES或者CLUSTER SLOTS去刷新一遍整个client cluster 支持运行状态下添加和删除节点。添加删除节点抽象:把一部分hash slot从一个节点移动到另一个节点。 所以,动态扩容的核心就是在节点之间移动hash slot,hash slot 又是key的集合。所以reshare 就是把key从一个节点移动到其他节点。 redis 提供如下命令: 前两个指令:ADDSLOTS和DELSLOTS,用于向当前node分配或者移除slots,指令可以接受多个slot值。分配slots的意思是告知指定的master(即此指令需要在某个master节点执行)此后由它接管相应slots的服务;slots分配后,这些信息将会通过gossip发给集群的其他nodes。 ADDSLOTS指令通常在创建一个新的Cluster时使用,一个新的Cluster有多个空的Masters构成,此后管理员需要手动为每个master分配slots,并将16384个slots分配完毕,集群才能正常服务。简而言之,ADDSLOTS只能操作那些尚未分配的(即不被任何nodes持有)slots,我们通常在创建新的集群或者修复一个broken的集群(集群中某些slots因为nodes的永久失效而丢失)时使用。为了避免出错,Redis Cluster提供了一个redis-trib辅助工具,方便我们做这些事情。 DELSLOTS就是将指定的slots删除,前提是这些slots必须在当前node上,被删除的slots处于“未分配”状态(当然其对应的keys数据也被clear),即尚未被任何nodes覆盖,这种情况可能导致集群处于不可用状态,此指令通常用于debug,在实际环境中很少使用。那些被删除的slots,可以通过ADDSLOTS重新分配。 SETSLOT是个很重要的指令,对集群slots进行reshard的最重要手段;它用来将单个slot在两个nodes间迁移。根据slot的操作方式,它有两种状态“MIGRATING”、“IMPORTING” 1)MIGRATING:将slot的状态设置为“MIGRATING”,并迁移到destination-node上,需要注意当前node必须是slot的持有者。在迁移期间,Client的查询操作仍在当前node上执行,如果key不存在,则会向Client反馈“-ASK”重定向信息,此后Client将会把请求重新提交给迁移的目标node。 2)IMPORTING:将slot的状态设置为“IMPORTING”,并将其从source-node迁移到当前node上,前提是source-node必须是slot的持有者。Client交互机制同上。 假如我们有两个节点A、B,其中slot 8在A上,我们希望将8从A迁移到B,可以使用如下方式: 1)在B上:CLUSTER SETSLOT 8 IMPORTING A 2)在A上:CLUSTER SETSLOT 8 MIGRATING B 在迁移期间,集群中其他的nodes的集群信息不会改变,即slot 8仍对应A,即此期间,Client查询仍在A上: 1)如果key在A上存在,则有A执行。 2)否则,将向客户端返回ASK,客户端将请求重定向到B。 这种方式下,新key的创建就不会在A上执行,而是在B上执行,这也就是ASK重定向的原因(迁移之前的keys在A,迁移期间created的keys在B上);当上述SET SLOT执行完毕后,slot的状态也会被自动清除,同时将slot迁移信息传播给其他nodes,至此集群中slot的映射关系将会变更,此后slot 8的数据请求将会直接提交到B上。 动态分片的步骤: 在上文中,我们已经介绍了MOVED重定向,ASK与其非常相似。在resharding期间,为什么不能用MOVED?MOVED意思为hash slots已经永久被另一个node接管、接下来的相应的查询应该与它交互,ASK的意思是当前query暂时与指定的node交互;在迁移期间,slot 8的keys有可能仍在A上,所以Client的请求仍然需要首先经由A,对于A上不存在的,我们才需要到B上进行尝试。迁移期间,Redis Cluster并没有粗暴的将slot 8的请求全部阻塞、直到迁移结束,这种方式尽管不再需要ASK,但是会影响集群的可用性。 1)当Client接收到ASK重定向,它仅仅将当前query重定向到指定的node;此后的请求仍然交付给旧的节点。 2)客户端并不会更新本地的slots映射,仍然保持slot 8与A的映射;直到集群迁移完毕,且遇到MOVED重定向。 一旦slot 8迁移完毕之后(集群的映射信息也已更新),如果Client再次在A上访问slot 8时,将会得到MOVED重定向信息,此后客户端也更新本地的集群映射信息。 可能有些Cluster客户端的实现,不会在内存中保存slots映射关系(即nodes与slots的关系),每次请求都从声明的、已知的nodes中,随机访问一个node,并根据重定向(MOVED)信息来寻找合适的node,这种访问模式,通常是非常低效的。 当然,Client应该尽可能的将slots配置信息缓存在本地,不过配置信息也不需要绝对的实时更新,因为在请求时偶尔出现“重定向”,Client也能兼容此次请求的正确转发,此时再更新slots配置。(所以Client通常不需要间歇性的检测Cluster中配置信息是否已经更新)客户端通常是全量更新slots配置: 遇到MOVED时,客户端仅仅更新特定的slot是不够的,因为集群中的reshard通常会影响到多个slots。客户端通过向任意一个nodes发送“CLUSTER NODES”或者“CLUSTER SLOTS”指令均可以获得当前集群最新的slots映射信息;“CLUSTER SLOTS”指令返回的信息更易于Client解析。 通常情况下,read、write请求都将有持有slots的master节点处理;因为redis的slaves可以支持read操作(前提是application能够容忍stale数据),所以客户端可以使用“READONLY”指令来扩展read请求。 “READONLY”表明其可以访问集群的slaves节点,能够容忍stale数据,而且此次链接不会执行writes操作。当链接设定为readonly模式后,Cluster只有当keys不被slave的master节点持有时才会发送重定向消息(即Client的read请求总是发给slave,只有当此slave的master不持有slots时才会重定向,很好理解): 1)此slave的master节点不持有相应的slots 2)集群重新配置,比如reshard或者slave迁移到了其他master上,此slave本身也不再支持此slot。 集群中的nodes持续的交换ping、pong数据,这两种数据包的结构一样,同样都携带集群的配置信息,唯一不同的就是message中的type字段。 通常,一个node发送ping消息,那么接收者将会反馈pong消息;不过有时候并非如此,比如当集群中添加新的node时,接收者会将pong信息发给其他的nodes,而不是直接反馈给发送者。这样的好处是会将配置尽快的在cluster传播。 通常一个node每秒都会随机向几个nodes发送ping,所以无论集群规模多大,每个nodes发送的ping数据包的总量是恒定的。每个node都确保尽可能半个NODE_TIMEOUT时间内,向那些尚未发送过ping或者未接收到它们的pong消息的nodes发送ping。在NODE_TIMEOUT逾期之前,nodes也会尝试与那些通讯异常的nodes重新建立TCP链接,确保不能仅仅因为当前链接异常而认为它们就是不可达的。 当NODE_TIMEOUT值较小、集群中nodes规模较大时,那么全局交换的信息量也会非常庞大,因为每个node都尽力在半个NODE_TIMEOUT时间内,向其他nodes发送ping。比如有100个nodes,NODE_TIMEOUT为60秒,那么每个node在30秒内向其他99各nodes发送ping,平均每秒3.3个消息,那么整个集群全局就是每秒330个消息。这些消息量,并不会对集群的带宽带来不良问题。 心跳数据包的内容 ping和pong数据包中也包含gossip部分,这部分信息告诉接受者,当前节点持有其他节点的状态,不过它只包含sender已知的随机几个nodes,nodes的数量根据集群规模的大小按比例计算。 gossip部分包含了 集群失效检测就是,当某个master或者slave不能被大多数nodes可达时,用于故障迁移并将合适的slave提升为master。当slave提升未能有效实施时,集群将处于error状态且停止接收Client端查询。 每个node持有其已知nodes的列表包括flags,有2个flag状态:PFAIL和FAIL;PFAIL表示“可能失效”,是一种尚未完全确认的失效状态(即某个节点或者少数masters认为其不可达)。FAIL表示此node已经被集群大多数masters判定为失效(大多数master已认定为不可达,且不可达时间已达到设定值,需要failover)。 nodes的ID、ip+port、flags,那么接收者将根据sender的视图,来判定节点的状态,这对故障检测、节点自动发现非常有用。 当node不可达的时间超过NODE_TIMEOUT,这个节点就被标记为PFAIL(Possible failure),master和slave都可以标记其他节点为PFAIL。所谓不可达,就是当“active ping”(发送ping且能受到pong)尚未成功的时间超过NODE_TIMEOUT,因此我们设定的NODE_TIMEOUT的值应该比网络交互往返的时间延迟要大一些(通常要大的多,以至于交互往返时间可以忽略)。为了避免误判,当一个node在半个NODE_TIMEOUT时间内仍未能pong,那么当前node将会尽力尝试重新建立连接进行重试,以排除pong未能接收

Redis Cluster集群的搭建

搭建集群工作需要以下三个步骤: 1)准备节点。 2)节点握手。 3)分配槽。 Redis集群一般由多个节点组成,节点数量至少为6个才能保证组成完整高可用的集群。每个节点需要开启配置cluster-enabled yes,让Redis运行在集群模式下。建议为集群内所有节点统一目录,一般划分三个目录:conf、data、log,分别存放配置、数据和日志相关文件。把6个节点配置统一放在conf目录下,集群相关配置如下: 其他配置和单机模式一致即可,配置文件命名规则redis-{port}.conf,准备好配置后启动所有节点。 Cluster集群启动过程如下图:每个节点目前只能识别出自己的节点信息,可以执行cluster nodes命令获取集群节点状 态。 节点握手是指一批运行在集群模式下的节点通过Gossip协议彼此通信,达到感知对方的过程。节点握手是集群彼此通信的第一步,由客户端发起命令:cluster meet{ip}{port} cluster meet命令是一个异步命令,执行之后立刻返回。内部发起与目标节点进行握手通信,握手通信过程: 1)节点6379本地创建6380节点信息对象,并发送meet消息。 2)节点6380接受到meet消息后,保存6379节点信息并回复pong消息。 3)之后节点6379和6380彼此定期通过ping/pong消息进行正常的节点通 信。 分别执行meet命令让其他节点加入到集群中, 最后执行cluster nodes命令确认6个节点都彼此感知并组成集群。 节点建立握手之后集群还不能正常工作,这时集群处于下线状态,所有的数据读写都被禁止,通过cluster info命令可以获取集群当前状态。 Redis集群把所有的数据映射到16384个槽中。每个key会映射为一个固定的槽,只有当节点分配了槽,才能响应和这些槽关联的键命令。通过cluster addslots命令为节点分配槽。这里利用bash特性批量设置槽(slots),命令如下: 执行cluster info查看集群状态,如下所示: 当前集群状态是OK,集群进入在线状态。所有的槽都已经分配给节点,执行cluster nodes命令可以看到节点和槽的分配关系: 集群模式下,Reids节点角色分为主节点和从节点。首次启动的节点和被分配槽的节点都是主节点,从节点负责复制主节点槽信息和相关的数据。使用cluster replicate{nodeId}命令让一个节点成为从节点。其中命令执行必须在对应的从节点上执行,nodeId是要复制主节点的节点ID,命令如下: Redis集群模式下的主从复制使用了之前介绍的Redis复制流程,依然支持全量和部分复制。复制(replication)完成后,整个集群的结构如图:集群搭建需要很多步骤当集群节点众多时,必然会加大搭建集群的复杂度和运维成本。因此Redis官方提供了redis-trib.rb工具方便我们快速搭建集群。 redis-trib.rb是采用Ruby实现的Redis集群管理工具。内部通过Cluster相关命令帮我们简化集群创建、检查、槽迁移和均衡等常见运维操作,使用之前需要安装Ruby依赖环境。 1、安装Ruby: 2、安装rubygem redis依赖: 3、安装redis-trib.rb: 4、安装完Ruby环境后,执行redis-trib.rb命令确认环境是否正确,输出如 下: 首先我们跟之前内容一样准备好节点配置并启动: 启动好6个节点之后,使用redis-trib.rb create命令完成节点握手和槽分配过程,命令如下: --replicas参数指定集群中每个主节点配备几个从节点,这里设置为1。 如果部署节点使用不同的IP地址,redis-trib.rb会尽可能保证主从节点不分配在同一机器下,因此会重新排序节点列表顺序。节点列表顺序用于确定主从角色,先主节点之后是从节点。创建过程中首先会给出主从节点角色分配的计划,当我们同意这份计划之后输入yes,redis-trib.rb开始执行节点握手和槽分配操作。 集群完整性指所有的槽都分配到存活的主节点上,只要16384个槽中有一个没有分配给节点则表示集群不完整。可以使用redis-trib.rb check命令检测之前创建的集群是否成功,check命令只需要给出集群中任意一个节点地址就可以完成整个集群的检查工作,命令如下:

redis集群为什么要ruby

安装redis集群需要版本号在3.0以上redis-cluster安装前需要安装ruby环境搭建集群需要使用到官方提供的ruby脚本。需要安装ruby的环境。yum -y install rubyyum -y install rubygemsredis集群管理工具redis-trib.rb[root@bogon ~]# cd redis-3.0.0[root@bogon redis-3.0.0]# cd src[root@bogon src]# ll *.rb-rwxrwxr-x.1 root root 48141 Apr 1 07:01 redis-trib.rb脚本需要的ruby包:redis-3.0.0.gem安装 gem install redis-3.0.0.gem[root@bogon ~]# gem install redis-3.0.0.gemSuccessfully installed redis-3.0.01 gem installedInstalling ri documentation forredis-3.0.0...Installing RDoc documentation forredis-3.0.0...集群的搭建需求,创建6台redis服务器,虚拟机模拟端口号为7001-7006第二步:修改redis的配置文件1、修改端口号第三步:把创建集群的ruby脚本复制到redis-cluster目录下。第四步:启动6个redis实例第五步:创建集群。

dataease配置redis链接信息

您问的是dataease如何配置redis链接信息吧,步骤如下:1、打开DataEase管理器,选择需要连接的数据库,在“属性”选项卡中找到“数据源连接字符串”选项;2、在“数据源连接字符串”中输入内容来配置Redis连接信息(修改为自己的实际配置);3、完成配置后,单击“测试连接”按钮,验证连接是否成功;4、如果连接成功,则可以使用DataEase管理器进行数据库管理操作。如果连接失败,可以检查连接信息是否输入正确,以及Redis服务器是否已启动等问题。

appledistribution是什么软件

appledistribution不是软件。是苹果分销的意思。apple distribution这个单词词语从字面上可以解释成苹果分销的意思,其中的“销”就是销售平台的意思,而苹果主要的分销渠道就是直营店、运营商和大规模零售商这三个。发展历史苹果公司创立之初,主要开发和销售的个人电脑,截至2014年致力于设计、开发和销售消费电子、计算机软件、在线服务和个人计算机。苹果的Apple II于1970年代开启了个人电脑革命,其后的Macintosh接力于1980年代持续发展。该公司硬件产品主要是Mac电脑系列、iPod媒体播放器、iPhone智能手机和iPad平板电脑;在线服务包括iCloud、iTunes Store和App Store;消费软件包括OS X和iOS操作系统、iTunes多媒体浏览器、Safari网络浏览器,还有iLife和iWork创意和生产套件。苹果公司在高科技企业中以创新而闻名世界。

appledistribution是什么软件

appledistribution不是软件。是苹果分销的意思。apple distribution这个单词词语从字面上可以解释成苹果分销的意思,其中的“销”就是销售平台的意思,而苹果主要的分销渠道就是直营店、运营商和大规模零售商这三个。发展历史苹果公司创立之初,主要开发和销售的个人电脑,截至2014年致力于设计、开发和销售消费电子、计算机软件、在线服务和个人计算机。苹果的Apple II于1970年代开启了个人电脑革命,其后的Macintosh接力于1980年代持续发展。该公司硬件产品主要是Mac电脑系列、iPod媒体播放器、iPhone智能手机和iPad平板电脑;在线服务包括iCloud、iTunes Store和App Store;消费软件包括OS X和iOS操作系统、iTunes多媒体浏览器、Safari网络浏览器,还有iLife和iWork创意和生产套件。苹果公司在高科技企业中以创新而闻名世界。

redis的IO模型

我们的应用都是部署在linux系统中,linux系统也是一种应用,它是基于计算机硬件的一种操作系统软件。当我们接收一次网络传输,计算机硬件的网卡会从网络中将读到的字节流写到linux的buffer缓冲区内存中,然后用户空间会调用linux对外暴露的接口,将linux中的buffer内存中的数据再读取到用户空间。这一次读操作就是一次IO。同样写也是这样的。 不同的操作系统,IO模型不一样,下面介绍的是Linux系统的几种IO模型 这样做是为了保护Linux操作系统,避免外部应用或者人为直接操作内核系统。 当线程操作在用户空间时候的状态称为: 用户态 当线程操作在内核空间时候的状态称为: 内核态 IO的性能瓶颈: a.用户态与内核态的切换(数据拷贝) b.读写线程的阻塞等待 linux的IO模型就是针对这两点去优化的 当用户应用线程调用linux操作系统的recvfrom函数读取数据的时候,如果内核的buffer内存中没有数据,那么用户线程会 阻塞等待 ,直到内核的buffer内存中有数据了,才去将内核的buffer内存中的数据拷贝到用户应用内存中。 类似于你排队买包子,但是包子这时候没有了,但是你不知道还有没有包子,如果没有,你只能在那等待包子出炉,什么也做不了,干等着,直到包子出炉了,你才能拿到包子,放到自己的口袋中。 问题: 当一个线程阻塞住了,会导致后续所有的线程都阻塞住,即使后面的读写数据已经就绪,也无法进行读写。 当用户应用线程调用linux操作系统的recvfrom函数读取数据的时候,如果内核的buffer内存中没有数据,那么用户线程会 直接拿到结果(没有数据) 不需要等待,于是又会发起一次recvfrom函数调用,直到内核的buffer内存中有数据了,才去将内核的buffer内存中的数据拷贝到用户应用内存中。 类似于你排队买包子,老板直接和你说没有包子了,你已经知道了结果,你一遍又一遍的问老板,还有没有包子了,直到老板出炉了包子,告诉你,你才能拿到包子,放到口袋中。 问题: 如果一直没有数据的话,线程会死循环的调用recvfrom函数,频繁使用CPU资源,导致CPU资源的浪费。 内核kernel)利用文件描述符(file descriptor)来访问文件。文件描述符是非负整数打开现存文件或新建文件时,内核会返回一个文件描述符。读写文件也需要使用文件描述符来指定待读写的文件。文件包含音频文件,常规文件,硬件设备等等,也包括网络套接字(Socket)。 IO多路复用就是利用单线程去监听多了文件描述符FD,并在某个文件描述符FD可读,可写的时候接收到通知,避免无效的等待,充分利用CPU资源。 用户应用线程调用select函数去监听多个FD文件描述符,如果没有数据,还是要等待,如果有就绪的文件FD,说明有数据,那就去读对应的FD就绪的文件数据,此时内核会将文件FD集合拷贝到用户内存中,然后去遍历FD集合,找到可以读的数据的FD,然后再去读取,读完了之后会将FD的集合再拷贝到内核内存中。 类似于你去餐厅排队点餐,这时候有一个服务员,服务员通过平板监控后厨,你只需要询问服务员有没有东西吃就可以了,如果没有你还是需要等待,但是如果有了,服务员通过监控就知道有东西可以吃了,就会让你点餐了。 poll模式其实和select模式原理差不多,不同的点在于,poll模式底层加上了一个event事件,分成读事件,写事件,异常事件等等。 流程: a.先添加需要监听的事件,是读事件,还是写事件,可以是多个事件 b.将监听到的事件FD,转换成 链表 ,保存在内核缓冲区 c.内核缓冲区将事件FD 链表 拷贝到用户缓冲区,并返回就绪的FD数量 d.用户缓冲区判断就绪的FD数量,如果大于0则开始便利事件FD 链表 poll模式的问题: a.需要将整个FD链表从用户空间拷贝到内核空间,poll结束还要再次拷贝到用户空间 b.poll无法得知是具体的哪个就绪的FD事件,需要便利整个FD事件( 链表 ) 对比select模式 由于使用了链表,理论上事件个数可以是无数个,但是随着事件个数增多,链表的遍历性能会下降,而且当没有就绪事件的时候还是需要等待。 epoll模式是在poll模式的基础上再次改进,首先将存储事件的FD链表改成了红黑树(理论上也是无上限的),红黑树的遍历性能稳定,其次就是将具体的就绪事件单独复制出来然后拷贝给用户缓冲区,用户缓冲区拿到的是已经就绪的事件,无需遍历性能再次提升。 流程: a.先将注册的监听事件 b.将所有的FD挂载在一个红黑树中 c.当FD就绪调用回调函数将对应的FD复制到一个链表中 d.将链表从内核缓冲区拷贝到用户缓冲区,并返回链表大小n e.用户线程直接判断n大小,当n不为0的时候,直接读取链表(全部是就绪的FD)的数据即可 当用户应用线程调用linux操作系统的sigaction函数,直接返回,然后该线程去做其他事情了,当有数据来了的时候,内核空间会去递交信号给用户空间,此时用户空间会调用recvfrom函数去将数据从内核空间缓冲区拷贝到用户空间缓冲区,并处理数据。 类似于你点餐点完了,服务员会给你一个号码,然后你的餐好了,服务员会叫你的号码,然后你就去拿餐。 问题: 当调用的线程过多,对应的信号量会增多,SIGIO函数处理不及时,会导致保存信号的队列溢出;而且内核空间与用户空间频繁的进行信号量的交互,性能很差。 性能上来说也是不错的,就是在实际开发中,需要控制它的线程并发数,所以实现起来会非常麻烦,所以使用很少 三种IO多路复用对比来说epoll的效果是最好的。解决了select和poll模式中存在的问题。 而redis就是使用的epoll模式的IO模型。

redis如何实现自定义过期时间?

找到你们项目中的redis工具类,里面加一个方法我使用的是RedisTemplatepublic boolean expire(final String key, long expire) { return redisTemplate.expire(key, expire, TimeUnit.SECONDS); }用来设置对应的key的生命周期。记得采纳哦

Redis分布式锁的原理是什么?如何续期?

在传统单体应用单机部署的情况下,并发问题可以通过使用Java并发相关的锁如synchronized,但是当规模上升到分布式集群的情况下,要控制共享资源访问,就需要通过分布式锁来实现。常见的分布式锁方案如数据库乐观锁,Redis锁,zk锁等。Redis分布式锁的原理 Redis分布式锁可以有多种方式实现但是其核心就是通过以下三个Redis命令组合实现。 SETNX SETNX key val 当且仅当key不存在时,set一个key为val的字符串,返回1;若key存在,则什么都不做,返回0。 Expire expire key timeout 为key设置一个超时时间,单位为second,超过这个时间锁会自动释放,避免死锁。 Delete delete key 删除key 核心思想 使用setnx获取锁。如果成功取到锁,则使用expire命令为锁添加一个超时时间,超过该时间则自动释放锁。 获取锁的时候还设置一个获取的超时时间,若超过这个时间则放弃获取锁。注意 上面为Redis的一个最简单的锁实现原理,实际中还需要考虑更多具体的情况作出相应的调整。如 上面的demo中,当集群系统时间不一致时会有问题 当服务器异常关闭或是重启,加锁后没来得急设置锁超时时间,如何避免死锁 实际开发环境中不确定的因素有很多,需要慢慢地去调整实践达到理想状态,可以考虑使用redisson框架来实现。 如何续期? 这个情况比较独特,出现这个问题的根本原因在于锁失效的时间小于业务处理的时间导致业务还没处理完毕锁就释放了。那么解决方案是合理地结合业务去设置锁失效的时间。但是也有更好的方案就如前文提到的redisson,其中的可重入锁概念。默认情况下,加锁的时间是30秒.如果加锁的业务没有执行完,那么到 30-10 = 20秒的时候,就会进行一次续期,把锁重置成30秒。 以上就是redis锁的原理及续期的方式,希望我的回答能对你有所帮助。

如何设置redis中hash的field的expire

hset hash_key field_name field_value 设置 hash 类型中的属性(字段)值 返回1,表示 新的属性 field_name field_value 被添加到 hash_key 的hash中; 返回0,表示 旧的属性 field_name 已经存在,且值被更新为 field_value。

java编程代码 redisTemplate过期时间问题

我以前项目中的做法是在保存的对象上,增加一个过期时间属性,get之后,判断系统时间是否超过过期时间,超过的话就删掉这个key,或者是从DB重新加载。
 首页 上一页  1 2 3 4  下一页  尾页