redis -- 字符串

1.增

set key value :

如果key已经持有其他值,SET就覆写旧值,无视类型。

返回值:

总是返回 OK ,因为 SET 不可能失败。

setnx key value :

如果key已经存在了,就不做任何操作。

返回:

1或者0


setex key seconds value

将值value关联到key,并将key的生存时间设为seconds(以秒为单位)。如果key存在,就覆写旧值。

返回值:

设置成功时返回OK

seconds参数不合法时,返回一个错误。


mset key value [key value ....]

一个原子操作,新值覆盖旧值

返回值:
总是返回 OK(因为 MSET不可能失败)


msetnx key value[key value..]

msetnx 是原子操作,如果一个key不存在,就全部不执行

返回值:1或者0




2.删

del key


3.改

setrange key offset value:

把key的第offset个字符开始,设置为value,如果key不存在,就创建

返回值:
SETRANGE修改之后,字符串的长度。

append key value

在key的基础上,追加value,如果key不存在,就和set 是一样的

返回值:
追加 value之后, key中字符串的长度。


mset key value [key value ....]

一个原子操作,新值覆盖旧值

返回值:
总是返回 OK(因为 MSET不可能失败)


getset key value:

设置新值,返回key的旧值。

如果key不存在,返回nil


decr key :

将key的值减一。

如果可以不存在,就以0减一,如果key的value为str,就报错,


decrby key decrement :减去decrement

如果key不存在,按照0开始算。如果key的value 是字符串,则报错。


incr key

incrby key increment 

同上


4.查

get key


mget  key [key....]

如果其中一个key 不存在,则该key返回nil


getrange key start end 

key 不存在 返回“” ,如果超出字符串的长度,就返回字符串本身


strlen key :

不存在key,返回0


exists key:

不存在key,返回0



知识点:

设计模式(Design pattern): 将SETNX用于加锁(locking)

SETNX可以用作加锁原语(locking primitive)。比如说,要对关键字(key)foo加锁,客户端可以尝试以下方式:

SETNX lock.foo <current Unix time + lock timeout + 1>

如果SETNX返回1,说明客户端已经获得了锁,key设置的unix时间则指定了锁失效的时间。之后客户端可以通过DEL lock.foo来释放锁。

如果SETNX返回0,说明key已经被其他客户端上锁了。如果锁是非阻塞(non blocking lock)的,我们可以选择返回调用,或者进入一个重试循环,直到成功获得锁或重试超时(timeout)。

处理死锁(deadlock)

上面的锁算法有一个问题:如果因为客户端失败、崩溃或其他原因导致没有办法释放锁的话,怎么办?

这种状况可以通过检测发现——因为上锁的key保存的是unix时间戳,假如key值的时间戳小于当前的时间戳,表示锁已经不再有效。

但是,当有多个客户端同时检测一个锁是否过期并尝试释放它的时候,我们不能简单粗暴地删除死锁的key,再用SETNX上锁,因为这时竞争条件(race condition)已经形成了:

  • C1和C2读取lock.foo并检查时间戳,SETNX都返回0,因为它已经被C3锁上了,但C3在上锁之后就崩溃(crashed)了。
  • C1向lock.foo发送DEL命令。
  • C1向lock.foo发送SETNX并成功。
  • C2向lock.foo发送DEL命令。
  • C2向lock.foo发送SETNX并成功。
  • 出错:因为竞争条件的关系,C1和C2两个都获得了锁。

幸好,以下算法可以避免以上问题。来看看我们聪明的C4客户端怎么办:

  • C4向lock.foo发送SETNX命令。
  • 因为崩溃掉的C3还锁着lock.foo,所以Redis向C4返回0
  • C4向lock.foo发送GET命令,查看lock.foo的锁是否过期。如果不,则休眠(sleep)一段时间,并在之后重试。
  • 另一方面,如果lock.foo内的unix时间戳比当前时间戳老,C4执行以下命令:

GETSET lock.foo <current Unix timestamp + lock timeout + 1>

  • 因为GETSET的作用,C4可以检查看GETSET的返回值,确定lock.foo之前储存的旧值仍是那个过期时间戳,如果是的话,那么C4获得锁。
  • 如果其他客户端,比如C5,比C4更快地执行了GETSET操作并获得锁,那么C4的GETSET操作返回的就是一个未过期的时间戳(C5设置的时间戳)。C4只好从第一步开始重试。
注意,即便C4的 GETSET操作对 key进行了修改,这对未来也没什么影响。
(这里是不是有点问题?C4的确是可以重试,但C5怎么办?它的锁的过期被C4修改了。——译注)

Warning:

为了让这个加锁算法更健壮,获得锁的客户端应该常常检查过期时间以免锁因诸如DEL等命令的执行而被意外解开,因为客户端失败的情况非常复杂,不仅仅是崩溃这么简单,还可能是客户端因为某些操作被阻塞了相当长时间,紧接着DEL命令被尝试执行(但这时锁却在另外的客户端手上)。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值