1. 首页 > 手机 >

redis删除指定key redis删除指定key命令

Redis随笔-rename效率问题

「因为Redis中过期的key是由主线程删除的,为了不阻塞用户的请求,所以删除过期key的时候是少量多次」 。源码可以参考expire.c中的activeExpireCycle方法

rename 是redis中给key重命名命令, rename key newkey 的意思就是将key重命名为newkey。

redis删除指定key redis删除指定key命令redis删除指定key redis删除指定key命令


大部分文档在介绍 rename 的时候只将它描述成一个时间复杂度为O(1)的命令,却忘了说明它可能导致的性能问题(涉及覆盖旧值的时候 时间复杂度应该是O(1)+O(M))。

我们先做个试验看看 rename 的问题。

先搭建一个redis,版本号为3.2,看看它的内存信息

接着用lua给redis创建一个名为 test 的大key, test 有500w个field,每个field的值都是1

这时候我们看看redis的内存占用情况

接下来我们创建一个临时key,并用它来 rename 掉大key test

这时就能看到执行时间的异常了, rename 执行时间长达2.36秒,这是为什么呢?我们再看看redis内存占用情况:

通过 返回的信息我们可以发现在执行 rename 之后redis将大key test 大小为300多兆的值对象直接删除并回收掉了,而redis删除一个key的时间复杂度是O(M),在这里M是被删除的成员数量---500w。应该就是这个 "隐式"删除作 导致了高延迟的产生。

newkey如果本就存在,redis会用key的值覆盖掉newkey的值, 而newkey原本的值会被redis隐式地删除 。我们知道大key的删除伴随着高延迟(redis是单进程服务,会在删除大key期间block住接下来其他命令的执行),这就导致时间复杂度本为O(1)的 rename 也有可能卡住redis。

这句文档的原话我没在其他文档里找到类似的翻译,看这些文档的开发者可能会误以为这是个特别安全的O(1)命令。

既然文档里这个是不一定的,不是所有的锁子都可以万无一失。已经说明了这种行为的存在,我就顺便看看源码这块逻辑是怎么走的:

正常O(1)重命名的逻辑不用多说,涉及到覆盖的过程可以简化成如下图:

在改变指针的指向之前,redis会先用 if (lookupKeyWrite(c->db,c->argv[2]) != NULL) 判断 newkey 是否有对应的值,若有 则调用 dbDelete(c->db,c->argv[2]); 将newkey的值 v2 删掉。

用redis的时候, keys 、 hgetall 、 del 这些命令我们会多加小心,因为不合理地调用它们可能会长时间block住redis的其他请求 甚至导致CPU使用率居高不下从而卡住整个。但其实 rename 这个不起眼的命令也可能造成一样的问题,使用时也需要谨慎对待。

RENAME – Redis

在不影响性能的情况下,怎么快速批量删除redis数据

16 }

业务场景: redis数据切换到Oracle,取消持久化,redis只做缓存

2. 是否maxmemory不足导致redis自动清理部分key以节省空间

具体需求: 从redis从库里获得了400w个无过期时间的hashkey,需要在主库中将其删除

矛盾点:1.如果直接批量删除会导致redis拥塞,影响正常业务2.如果每删除一个key,sleep50ms,不会影响业务,但是根据经验要跑两天

最终问题: 在不影响性能的情况下,怎么快速批量删除redis数据?

Redis删key删得飞快,400w也不在话下。我怀疑其实瓶颈在于网络。

如果你是一个一个key删的,每次发送一个命令都会导致客户端等待redis的回复,浪费了大量网络带宽。

可以试试用pipelining/transactions。在不饱和redis端网络带宽的前提下,以速度发送命令,然后一次执行。

如果这都不行的话,可以写一个Lua脚本,识别并删除无用的key,发送到redis用eval执行。这样应该不会阻塞网络。

如果这样还是影响业务的话。。解决方案是创建一个/sle,在sle上删除key,而将请求用处理。删完key之后把sle晋升成,再将请求转向它。

2014年07月24日回答

滕亦飞1.3k

尝试下 redis 的 eval 命令。

例如删除 old-fashioned: 开头的所有 KEY

eval "redis.call('del', unpack(redis.call('keys','old-fashioned:')))" 0

如果单次删除性能消耗大,可以考虑分批删除。

redis怎么设置自动删除最久数据

用一个可以"find reference"的IDE,沿着setex(Set the value and expiration of a key)命令一窥究竟:

void setexCommand(redis c) {

c->argv[3] = tryObjectEncoding(c->argv[3]);

setGenericCommand(c,0,c->argv[1],c->argv[3],c->argv[2]);

}setGenericCommand是一个实现set,setnx,setex的通用函数,参数设置不同而已。

void setCommand(redis c) {

setGenericCommand(c,0,c->argv[1],c->argv[2],NULL);

}void setnxCommand(redis c) {

setGenericCommand(c,1,c->argv[1],c->argv[2],NULL);

}void setexCommand(redis c) {

c->argv[3] = tryObjectEncoding(c->argv[3]);

setGenericCommand(c,0,c->argv[1],c->argv[3],c->argv[2]);

}再看setGenericCommand:

1 void setGenericCommand(redis c, int nx, robj key, robj val, robj expire) {

2 long seconds = 0; / initialized to oid an harmness warning /

34 if (expire) {

5 if (getLongFromObjectOrReply(c, expire, &seconds, NULL) != REDIS_OK)

6 return;

7 if (seconds <= 0) {

8 addReplyError(c,"invalid expire time in SETEX");

9 return;

10 }

11 }

12

13 if (lookupKeyWrite(c->db,key) != NULL && nx) {

14 addReply(c,shared.czero);

15 return;

17 setKey(c->db,key,val);

18 server.dirty++;

19 if (expire) setExpire(c->db,key,time(NULL)+seconds);

20 addReply(c, nx ? shared.cone : shared.ok);

21 }

22

13行处理"Set the value of a ke当实际使用的内存超过maxmemoey后,Redis提供了如下几种可选策略。y, only if the key does not exist"的场景,17行插入这个key,19行设置它的超时,注意时间戳已经被设置成了到期时间。这里要看一下redisDb(即c->db)的定义:

typedef struct redisDb {

dict dict; / The keyspace for this DB /

dict expires; / Timeout of keys with a timeout set /

dict blocking_keys; / Keys with clients waiting for data (BLPOP) /

dict io_keys; / Keys with clients waiting for VM I/O /

dict watched_keys; / WATCHED keys for MULTI/EXEC CAS /

int id;

} redisDb;

仅关注dict和expires,分别来存key-value和它的超时,也就是说如果一个key-value是有超时的,那么它会存在dict里,同时也存到expires里,类似这样的形式:dict[key]:value,expires[key]:timeout.

当然key-value没有超时,expires里就不存在这个key。剩下setKey和setExpire两个函数无非是插数据到两个字典里,这里不再详述。

那么redis是如何删除过期key的呢。

通过查看dbDelete的调用者,首先注意到这一个函数,是用来删除过期key的。

1 int expireIfNeeded(redisDb db, robj key) {

2 time_t when = getExpire(db,key);

34 if (when < 0) return 0; / No expire for this key /

56 / Don't expire anything while loading. It will be done later. /

7 if (server.loading) return 0;

89 / If we are running in the context of a sle, return ASAP:

10 the sle key expiration is controlled by the that will

11 send us synthesized DEL operations for expired keys.

12

13 Still we try to return the right rmation to the caller,

14 that is, 0 if we think the key should be still valid, 1 if

15 we think the key is expired at this time. /

16 if (server.host != NULL) {

17 return time(NULL) > when;

18 }

20 / Return when this key has not expired /

21 if (time(NULL) <= when) return 0;

22

23 / Delete the key /

24 server.stat_expiredkeys++;

25 propagateExpire(db,key);

26 return dbDelete(db,key);

27 }

28

ifNeed表示能删则删,所以4行没有设置超时不删,7行在"loading"时不删,16行非主库不删,21行未到期不删。25行同步从库和文件。

再看看哪些函数调用了expireIfNeeded,有lookupKeyRead,lookupKeyWrite,dbRandomKey,existsCommand,keysCommand。通过这些函数命名可以看出,只要访问了某一个key,顺带做的事情就是尝试查看过期并删除,这就保证了用户不可能访问到过期的key。但是如果有大量的key过期,并且没有被访问到,那么就浪费了许多内存。Redis是如何处理这个问题的呢。

dbDelete的调用者里还发现这样一个函数:

1 / Try to expire a few timed out keys. The algorithm used is adaptive and

2 will use few CPU cycles if there are few expiring keys, otherwise

3 it will get more aggressive to oid that too much memory is used by

4 keys that can be removed from the keyspace. /

5 void activeExpireCycle(void) {

6 int j;

9 int expired;

10 redisDb db = server.db+j;

12 / Continue to expire if at the end of the cycle more than 25%

14 do {

15 long num = dictSize(db->expires);

16 time_t now = time(NULL);

18 expired = 0;

19 if (num > REDIS_EXPIRELOOKUPS_PER_CRON)

20 num = REDIS_EXPIRELOOKUPS_PER_CRON;

21 while (num--) {

22 dictEntry de;

23 time_t t;

24

25 19 if ((de = dictGetRandomKey(db->expires)) == NULL) break;

26 t = (time_t) dictGetEntryVal(de);

27 if (now > t) {

28 sds key = dictGetEntryKey(de);

29 robj keyobj = createStringObject(key,sdslen(key));

31 propagateExpire(db,keyobj);

32 dbDelete(db,keyobj);

33 decrRefCount(keyobj);

34 expired++;

35 server.stat_expiredkeys++;

36 }

37 }

38 } while (expired > REDIS_EXPIRELOOKUPS_PER_CRON/4);

40 }

41

这个函数的意图已经有说明:删一点点过期key,如果过期key较少,那也只用一点点cpu。25行随机取一个key,38行删key成功的概率较低就退出。这个函数被放在一个cron里,每毫秒被调用一次。这个算法保证每次会删除一定比例的key,但是如果key总量很大,而这个比例控制的太大,就需要更多次的循环,浪费cpu,控制的太小,过期的key就会变多,浪费内存——这就是时空权衡了。

在dbDelete的调用者里还发现这样一个函数:

/ This function gets called when 'maxmemory' is set on the config file to limit

the max memory used by the server, and we are out of memory.

This function will try to, in order:

- Try to remove keys with an EXPIRE set

It is not sible to free enough memory to reach used-memory < maxmemory

the server will start refusing commands that will enlarge n more the

memory usage.

/

void freeMemoryIfNeeded(void)

这个函数太长就不再详述了,注释部分说明只有在配置文件中设置了内存时候才会调用这个函数,而设置这个参数的意义是,你把redis当做一个内存cache而不是key-value数据库。

redis的expire方法

清空作 flushdb 和 flushall ,在Redis4.0后,在指令后面增加 async ,就也可以像上面一样异步执行。

EXPIRE key seconds(单位/秒) 为给定 key 设置生存时间,当 key 过期时(生存时间为 0 ),它会被自动删除。在 Redis 中,带有生存时间的 key 被称为『易失的』(volatile)。

以上3种删除过期key的途径,第二种定期删除一定比例的key是主要的删除途径,种“读时删除”保证过期key不会被访问到,第三种是一个当内存超出设定时的手段。由此也能看出redis设计的巧妙之处,

生存时间可以通过使用 DEL 命令来删除整个 key 来移除,或者被 SET 和 GETSET 命令覆写(overwrite),这意味着,如果一个命令只是修改(alter)一个带生存时间的 key 的值而不是用一个新的 key 值来代替(replace)它的话,那么生存时间不会被改变。

比如说,对一个 key 执行 INCR 命令,对一个列表进行 LPUSH 命令,或者对一个哈希表执行 HSET 命令,这类作都不会修改 key 本身的生存时间。

另一方面,如果使用 RENAME 对一个 key 进行改名,那么改名后的 key 的生存时间和改名前一样。

RENAME 命令的另一种可能是,尝试将一个带生存时间的 key 改名成另一个带生存时间的 another_key ,这时旧的 another_key (以及它的生存时间)会被删除,然后旧的 key 会改名为 another_key ,因此,新的 another_key 的生存时间也和原本的 key 一样。

使用 PERSIST 命令可以在不删除 key 的情况下,移除 key 的生存时间,让 key 重新成为一个『持久的』(persistent) key 。

Redis过期删除策略和内存淘汰策略

由于大key test 的创建,redis内存占用多了300多兆。

Redis可以用使用 expire 指令设置过期时间,在Redis内部,每当我们设置一个键的过期时间时,Redis就会将该键带上过期时间存放到一个过期字典中。当我们查询一个键时,Redis便首先检查该键是否存在过期字典中,如果存在,那就获取其过期时间。然后将过期时间和当前系统时间进行比对,比系统时间大,那就没有过期;反之判定该键过期。

那对于过期数据,一般有三种方式进行处理:

Redis的过期删除策略: 惰性删除 和 定期删除 两种策略配合使用。

spring-boot-starter-data-redis 包中提供了过期的类,对于key过期,需要得到通知,做业务处理的,可以做此。

springboot整合Redis参考, SpringBoot整合Redis - (jianshu)

在整合Redis的基础上,在新加配置

配置类

将Redis用作缓存时,如果内存空间用满,就会自动驱逐老的数据。

Redis中有6种淘汰策略:

redis.con懒惰处理f 文件中配置策略,有2个地方:

redis当一个key被设置了过期key会被自动删除么

理论上会删除,但是由于redis版本的问题或者说过期删除机制的问题,有很小很小的可能13 of the keys were expired. /,一个key过期了但是却没被删除。

这种情况发生在redis的删除del在删除一个大对象的时候有可能造成卡顿。为了解决这个问题Redis4.0引入了unlink指令,将这个key的对象引用从Redis内存数据里删除,将删除作封装成一个任务丢到一个异步队列里。然后有个异步线程会从这个队列里取出任务并执行。,一个key你给人家设置了有效时间,但是却频繁去修改它的value,就有小小的可能会发生

Redis有哪些慢作?

可以通过如下方式优化

从业务到Redis这条调用链路中变慢的原因可能有2个

但是大多数情况下都是Redis服务的问题。但是应该如何衡量Redis变慢了呢?命令执行时间大于1s,大于2s?这其实并没有一个固定的标准。

例如在一个配置较高的中,0.5毫秒就认为Redis变慢了,在一个配置较低的中,3毫秒才认为Redis变慢了。所以我们要针对自己的机器做基准测试,看平常情况下Redis处理命令的时间是多长?

我们可以使用如下命令来监测和统计测试期间的延迟(以微秒为单位)

比如执行如下命令2、定期删除+惰性删除策略是如何工作的?

参数中的60是测试执行的秒数,可以看到延迟为3725微秒(3毫秒左右),如果命令的执行远超3毫秒,此时Redis就有可能很慢了!

那么Redis有哪些慢作呢?

Redis的各种命令是在一个线程中依次执行的,如果一个命令在Redis中执行的时间过长,就会影响整体的性能,因为后面的请求要等到前面的请求被处理完才能被处理,这些耗时的作有如下几个部分

Redis可以通过日志记录那些耗时长的命令,使用如下配置即可

执行如下命令,就可以查询到最近记录的慢日志

之前的文章我们已经介绍了Redis的底层数据结构,它们的时间复杂度如下表所示

名称 时间复杂度 dict(字典) O(1) ziplist (压缩列表) O(n) zskiplist (跳表) O(logN) quicklist(快速列表) O(n) intset(整数) O(n)

「单元素作」 :对中的元素进行增删改查作和底层数据结构相关,如对字典进行增删改查时间复杂度为O(1),对跳表进行增删查时间复杂为O(logN)

「范围作」 :对进行遍历作,比如Hash类型的HGETALL,Set类型的SMEMBERS,List类型的LRANGE,ZSet类型的ZRANGE,时间复杂度为O(n),避免使用,用SCAN系列命令代替。(hash用hscan,set用sscan,zset用zscan)

「聚合作」 :这类作的时间复杂度通常大于O(n),比如SORT、SUNION、ZUNIONSTORE

「统计作」 :当想获取中的元素个数时,如LLEN或者SCARD,时间复杂度为O(1),因为它们的底层数据结构如quicklist,dict,intset保存了元素的个数

「当想获取Redis中的key时,避免使用keys 」 ,Redis中保存的键值对是保存在一个字典中的(和Ja中的HashMap类似,也是通过数组+链表的方式实现的),key的类型都是string,value的类型可以是string,set,list等

例如当我们执行如下命令后,redis的字典结构如下

我们可以用keys命令来查询Redis定的key,如下所示

keys命令的复杂度是O(n),它会遍历这个dict中的所有key,如果Redis中存的key非常多,所有读写Redis的指令都会被延迟等待,所以千万不用在生产环境用这个命令(如果你已经准备离职的话,祝你玩的开心)。

「既然不让你用keys,肯定有替代品,那就是scan」

scan是通过游标逐步遍历的,因此不会长时间阻塞Redis

「用用zscan遍历zset,hscan遍历hash,sscan遍历set的原理和scan命令类似,因为hash,set,zset的底层实现的数据结构中都有dict。」

「如果一个key对应的value非常大,那么这个key就被称为bigkey。写入bigkey在分配内存时需要消耗更长的时间。同样,删除bigkey释放内存也需要消耗更长的时间」

如果在慢日志中发现了SET/DEL这种复杂度不高的命令,此时你就应该排查一下是否是由于写入bigkey导致的。

「如何定位bigkey?」

Redis提供了扫描bigkey的命令

可以看到命令的输入有如下3个部分

这个命令的原理就是redis在内部执行了scan命令,遍历实例中所有的key,然后正对key的类型,分别执行strlen,llen,hlen,scard,zcard命令,来获取string类型的长度,容器类型(list,hash,set,zset)的元素个数

使用这个命令需要注意如下两个问题

「如何解决bigkey带来的性能问题?」

我们可以给Redis中的key设置过期时间,那么当key过期了,它在什么时候会被删除呢?

「如果让我们写Redis过期策略,我们会想到如下三种方案」

定时删除策略对CPU不友好,当过期键比较多的时候,Redis线程用来删除过期键,会影响正常请求的响应

惰性删除读CPU是比较有好的,但是会浪费大量的内存。如果一个key设置过期时间放到内存中,但是没有被访问到,那么它会一直存在内存中

定期删除策略则对CPU和内存都比较友好

redis过期key的删除策略选择了如下两种

「惰性删除」 客户端在访问key的时候,对key的过期时间进行校验,如果过期了就立即删除

「定期删除」 Redis会将设置了过期时间的key放在一个的字典中,定时遍历这个字典来删除过期的key,遍历策略如下

为了避免主线程一直在删除key,我们可以采用如下两种方案

Redis是一个内存数据库,当Redis使用的内存超过物理内存的限制后,内存数据会和磁盘产生频繁的交换,交换会导致Redis性能急剧下降。所以在生产环境中我们通过配置参数maxmemoey来限制使用的内存大小。

「Redis的淘汰策略也是在主线程中执行的。但内存超过Redis上限后,每次写入都需要淘汰一些key,导致请求时间变长」

可以通过如下几个方式进行改善

Redis的持久化机制有RDB快照和AOF日志,每次写命令之后后,Redis提供了如下三种刷盘机制

「当aof的刷盘机制为always,redis每处理一次写命令,都会把写命令刷到磁盘中才返回,整个过程是在Redis主线程中进行的,势必会拖慢redis的性能」

当aof的刷盘机制为rysec,redis写完内存后就返回,刷盘作是放到后台线程中去执行的,后台线程每隔1秒把内存中的数据刷到磁盘中

当aof的刷盘机制为no,宕机后可能会造成部分数据丢失,一般不采用。

「一般情况下,aof刷盘机制配置为rysec即可」

在持久化一节中,我们已经提到 「Redis生成rdb文件和aof日志重写,都是通过主线程fork子进程的方式,让子进程来执行的,主线程的内存越大,阻塞时间越长。」

当机器的内存不够时,作系统会将部分内存的数据置换到磁盘上,这块磁盘区域就是Swap分区,当应用程序再次访问这些数据的时候,就需要从磁盘上读取,导致性能下降

「当Redis性能急剧下降时就有可能是数据被换到Swap分区,我们该如何排查Redis数据是否被换到Swap分区呢?」

每一行Size表示Redis所用的一块内存大小,Size下面的Swap表示这块大小的内存,有多少已经被换到磁盘上了,如果这2个值相等,说明这块内存的数据都已经被换到磁盘上了

我们可以通过如下方式来解决

我们总结一下Redis的慢作

Redis 的数据过期淘汰策略?

Redis 中数据过期策略采用定期删除+惰性删除策略。

定期删除策略:Redis 启用一个定时器定时监视所有的 key,判断key是39 }否过期,过期的话就删除。这种策略可以保证过期的 key 最终都会被删除,但是也存在的缺点:每次都遍历内存中所有的数据,非常消耗 CPU 资源,并且当 key 已过期,但是定时器还处于未唤起状态,这段时间内 key 仍然可以用。

惰性删除策略:在获取 key 时,先判断 key 是否过期,如果过期则删除。这种方式存在一个缺点:如果这个 key 一直未被使用,那么它一直在内存中,其实它已经过期了,会浪费大量的空间。

这两种策略天然的互补,结合起来之后,定时删除策略就发生了一些改变,不在是每次扫描全部的 key 了,而是随机抽取一部分 key 进行检查,这样就降低了对 CPU 资源的损耗,惰性删除策略互补了为检查到的key,基本上满足了所有要求。但是有时候就是那么的巧,既没有被定时器抽取到,又没有被使用,这些数据又如何从内存中消失?没关系,还有内存淘汰机制,当内存不够用时,内存淘汰机制就会上场。Redis 内存淘汰机制有以下几种策略:

noeviction:当内存不足以容纳新写入数据时,新写入作会报错。(Redis 默认策略)

allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的 Key。(使用)

allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个 Key。

volatile-lru:当内Redis会将设置了过期时间的key放到一个的字典里,默认每秒10次过期扫描。扫描方式:存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的 Key。这种情况一般是把 Redis 既当缓存,又做持久化存储的时候才用。

volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个 Key。

volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 Key 优先移除。

修改内存淘汰机制只需要在 redis.conf 配置文件中配置 maxmemory-policy 参数即可。

大家所推崇的 Redis 分布式锁,真的可以万无一失吗?

78 for (j = 0; j < server.dbnum; j++) {

基于数据库,如MySQL 基于缓存,如Redis 基于Zookeeper、etcd等。这里先容一下怎样应用缓存(Redis)完成散布式锁。应用Redis完成散布式锁最简略的是应用下令SETNX。SETNX(SET if Not eXist)的应用方法为:SETNX key value,只在键key不存在的情形下,将键key的值设置为value,若键key存在,则SETNX不做任何举措。SETNX在设置胜利时前往,设置失利时前往0。

是某个线程在猎取锁以后因为某些异样要素(比方宕机)而不能畸形的履行解锁纵,那末这个锁就开释不掉了。

无法做到万无一失,因为所有的设计都不是完美的。

这个不一定,因为所有的东西都不可能保证万无一失。

不可能,都是有bug的而且一旦有新的东西推出来,后边就会有的出来。

这个说不定,因为所有的东西都可能会出现故障。

基于数据库,如MySQL c->argv[2] = tryObjectEncoding(c->argv[2]); 基于缓存,如Redis 基于Zookeeper、etcd等。

redis丢失键值的几种情况

大致总结一下redis丢失键值的情况一般为以下几种情况:

1. 是否有大量过期key被清理17

分析:

原因:这种情况并不是真正的“丢失”键值,只是达到了设置的key的过期值

应对方案:根据项目情况设置合理的键值过期时间,或者设置为不过期,对不使用的key进行删除

分析:

原因:redis内存使用达到设置的可用内存的上限,redis自动清理部分key已节省空间给新的key使用

应对方案:适当的调大maxmemory

3. 主库故障后自动重启

分析:

原因:主库由于某种原因挂掉,但是在redis哨兵发现并启动切换之前被程序重启,如果主库有完整的备份策略,则丢失重启之前的一小段时间的数据,如果主库为了性能没有设置备份策略,则可能重启之后成为一个空的库,一段时间后,从库发现主库的runid发生变化,自动同步主库,导致数据丢失

应对11方案:

4. 网络分区的问题,可能导致短时间的写入数据丢失

分析:

原因:网络不稳定导致的短时写入失败或触发哨兵的自动切换(单独的主备方案触发切换期间会有数据丢失)

应对方案:保障网络环境稳定可达

ps:故障的排查更多的靠的精细度,如内存使用百分比的,对删除命令的,过期key的数量,slowlog的(大量key的查找和删除会被记录)等等

redis field 是什么意思 跟key是什么关系,比如lpush(key,field,value)应该怎么设置

先说redisredis是一个类似memcached的key/value存储系统,它支持存储的value类型相对较多,包括string(字符串)、list(链表)、set()和zset(有序)。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改作写入追加的记录文件(这点儿个人觉得redis比memcache在数据保存上要安全一些),并且30在此基础上实现了-sle(主从)同步。redis的存取性能很高,SET作每秒钟110000次,GET作每秒钟81000次(速度很爽!)。Redis针对不同的存储类型对象提供了不同的命令。redis目前提供四种数据类型:string,list,set及zset(sortedset)。string是最简单的类型,你可以理解成与Memcached一模一个的类型,一个key对应一个value,其上支持的作与Memcached的作类似。但它的功能更丰富。list是一个链表结构,主要功能是push、pop、获取一个范围的所有值等等。作中key理解为链表的名字。set是,和我们数学中的概念相似,对的作有添加删除元素,有对多个求交并等作。作中key理解为的名字。zset是set的一个升级版本,他在set的基础上增加了一个顺序属性,这一属性在添加修改元素的时候可以指定,每次指定后,zset会自动重新按新的值调整顺序。可以理解了有两列的mysql表,一列存value,一列存顺序。作中key理解为zset的名字。下面提供redis命令:适合全体类型的命令EXISTSkey判断一个键是否存在;存在返回1;否则返回0;DELkey删除某个key,或是一系列key;DELkey1key2key3key4TYPEkey返回某个key元素的数据类型(none:不存在,string:字符,list,set,zset,hash)KEYSpattern返回匹配的key列表(KEYSfoo:查找foo开头的keys)RANDOMKEY随机获得一个已经存在的key,如果当前数据库为空,则返回空字符串RENAMEoldnamenewname更改key的名字,新键如果存在将被覆盖RENAMENXoldnamenewname更改key的名字,如果名字存在则更改失败DBSIZE返回当前数据库的key的总数EXPIRE设置某个key的过期时间(秒),(EXPIREbruce1000:设置bruce这个key1000秒后系统自动删除)注意:如果在还没有过期的时候,对值进行了改变,那么那个值会被清除。TTL查找某个key还有多长时间过期,返回时间秒SELECTindex选择数据库MOVEkeydbindex将指定键从当前数据库移到目标数据库dbindex。成功返回1;否则返回0(源数据库不存在key或目标数据库已存在同名key);FLUSHDB清空当前数据库中的所有键FLUSHALL清空所有数据库中的所有键处理字符串的命令SETkeyvalue给一个键设置字符串值。SETkeynamedatalengthdata(SETbruce10paitoubing:保存key为burce,字符串长度为10的一个字符串paitoubing到数据库),data不可超过1G。GETkey获取某个key的value值。如key不存在,则返回字符串“nil”;如key的值不为字符串类型,则返回一个错误。GETSETkeyvalue可以理解成获得的key的值然后SET这个值,更加方便的作(SETbruce10paitoubing,这个时候需要修改bruce变成1234567890并获取这个以前的数据paitoubing,GETSETbruce101234567890)MGETkey1key2…keyN一次性返回多个键的值SETNXkeyvalueSETNX与SET的区别是SET可以创建与更新key的value,而SETNX是如果key不存在,则创建key与value数据MSETkey1value1key2value2…keyNvalueN在一次原子作下一次性设置多个键和值MSETNXkey1value1key2value2…keyNvalueN在一次原子作下一次性设置多个键和值(目标键不存在情况下,如果有一个以上的key已存在,则失败)INCRkey自增键值INCRBYkeyinteger令键值自增指定数值DECRkey自减键值DECRBYkeyinteger令键值自减指定数值处理lists的命令RPUSHkeyvalue从List尾部添加一个元素(如序列不存在,则先创建,如已存在同名Key而非序列,则返回错误)LPUSHkeyvalue从List头部添加一个元素LLENkey返回一个List的长度LRANGEkeystartend从自定的范围内返回序列的元素(「边界作」 :list底层是用quicklist实现的,quicklist保存了链表的头尾节点,因此对链表的头尾节点进行作,时间复杂度为O(1),如LPOP、RPOP、LPUSH、RPUSHLRANGEtestlist02;返回序列testlist前012元素)LTRIMkeystartend修剪某个范围之外的数据(LTRIMtestlist02;保留012元素,其余的删除)LINDEXkeyindex返回某个位置的序列值(LINDEXtestlist0;返回序列testlist位置为0的元素)LSETkeyindexvalue更新某个位置元素的值LREMkeycountvalue从List的头部(count正数)或尾部(count负数)删除一定数量(count)匹配value的元素,返回删除的元素数量。LPOPkey弹出List的个元素RPOPkey弹出List的一个元素RPOPLPUSHsrckeydstkey弹出_srckey_中一个元素并将其压入_dstkey_头部,key不存在或序列为空则返回“nil”处理(sets)的命令(有索引无序序列)SADDkeymember增加元素到SETS序列,如果元素(membe)不存在则添加成功1,否则失败0;(SADDtestlist3/none)SREMkeymember删除SETS序列的某个元素,如果元素不存在则失败0,否则成功1(SREMtestlist3/None)SPOPkey从中随机弹出一个成员SMOVEsrckeydstkeymember把一个SETS序列的某个元素移动到另外一个SETS序列(SMOVEtestlisttest3/ntwo;从序列testlist移动元素two到test中,testlist中将不存在two元素)SCARDkey统计某个SETS的序列的元素数量SISMEMBERkeymember获知指定成员是否存在于中SINTERkey1key2…keyN返回key1,key2,…,keyN中的交集SINTERSTOREdstkeykey1key2…keyN将key1,key2,…,keyN中的交集存入dstkeySUNIONkey1key2…keyN返回key1,key2,…,keyN的并集SUNIONSTOREdstkeykey1key2…keyN将key1,key2,…,keyN的并集存入dstkeySDIFFkey1key2…keyN依据key2,…,keyN求key1的集。例子:key1=x,a,b,ckey2=ckey3=a,dSDIFFkey1,key2,key3=>x,bSDIFFSTOREdstkeykey1key2…keyN依据key2,…,keyN求key1的集并存入dstkeySMEMBERSkey返回某个序列的所有元素SRANDMEMBERkey随机返回某个序列的元素处理有序(sortedsets)的命令(zsets)ZADDkeyscoremember添加指定成员到有序中,如果目标存在则更新score(分值,排序用)ZREMkeymember从有序删除指定成员ZINCRBYkeyincrementmember如果成员存在则将其增加_increment_,否则将设置一个score为_increment_的成员ZRANGEkeystartend返回升序排序后的指定范围的成员ZREVRANGEkeystartend返回降序排序后的指定范围的成员ZRANGEBYSCOREkeyminmax返回所有符合score>=min和score=min和score形式的数据,通过key进行任何作。ttserver可以将数据持久化保存,memcached全部是保存在内存中,memcached会自动删除过期数据,最长不超过30天。memcached在和一些api配合时,能自动进行数据的出入序列化,读取反序列化。ttserver有主从的功能,作日志等,这完全是数据库才有的东西。据说memcached正在对整体架构做调整,到时候支持plugin机制.会把网络,处理,内存存储剥离开来.以后要做基于磁盘的key-value存储就可以写一个存储引擎就成了。memcached的二次开发又步入一个小。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 12345678@qq.com 举报,一经查实,本站将立刻删除。

联系我们

工作日:9:30-18:30,节假日休息