Redis回顾与总结(持续更新中)

前一段时间公司某项目使用了Redis作为缓存服务器,年前不忙了总结回顾一下,同时整理一下学习笔记。(不断更新中...) 

--------------------------------------------------------------- 

一、Redis常用数据类型及命令

./bin/redis-cli:在Linux下登录redis

1、String类型

setnx: setnx key value

nx代表not exists,如果已经存在返回0,如果不存在则设置.

setex: setex key 10 value

ex代表expire date,10s后get key将返回0.

setrange: setrange key 2 value

将key对应的值从第二个字符后面用value替换.

mset: mset test1 value1 test2 value2

m代表multi,同时设置test1和test2两个key.

msetnx: msetnx key1 value1 key2 value2

同时设置多个key,如果都不存在则设置成功,如果有一个存在则所有key的设置回滚.

getset: getset key value1

设置key的值为value1,返回key的旧值.

getrange: getrange key 0 5 或 getrange key -5 -1

获取指定key的value值的子字符串.字符串左起下标为0范围为正,字符串右起下标-1范围为负.

mget: mget key1 key2 key3 

一次获取多个key.

incr: incr key 

键key必须是整数.不存在的key值设为1.

incrby: incrby key 5 

键key的值加5.

decr:  decr key 

键key必须是整数.不存在的key值设为-1.

decrby: decr key 5 

键key的值减5.

append: append key value 

追加value到key值的末尾.

strlen: strlen key

取指定key的value值长度.

2、List类型

list是一个每个子元素都是string类型双向链表,key理解为链表的名字.

可以通过push、pop从链表头部或者尾部添加删除元素.

lpush:lpush key value

从链表头部添加元素

lpop:lpop key

从链表头部删除元素,返回删除的元素.

rpush:rpush key value

从链表尾部添加元素

rpop:rpop key

从链表尾部删除元素,返回删除的元素.

lrange:lrange key 0 -1

从key所在list的头元素到末尾元素

linsert:linsert key [before|after] target value

在key所在list的target元素前后插入value,如果列表不存在或者target元素不存在则失败

lset:lset key -1 value

将list尾部倒数第一个元素置为value

lrem:lrem key 2 value

删除从链表头起2个与value相同的元素,如果负数则从链表尾算起

ltrim:ltrim key 0 1

保留指定key范围内的数据

rpoplpush: rpoplpush list1 list2 

将list1尾部元素移至list2头部,该操作是原子的.

llen:llen key

返回list对应的长度

lindex:lindex key 0

返回key所在list第0个元素的值.

3、Set类型:

Set是每个元素都是string的无序集合,key为set名字

sadd:sadd key value

向名称为key的set中添加元素

smembers:smembers key

列出名称为key的set中所有元素

srem:srem key value

删除名为key的set中的value元素

spop:spop key

随机删除一个元素,并返回删除的元素

sdiff:sdiff key1 key2

返回key1中存在但是key2中不存在的元素

sdiffstroe:sdiffstore key3 key1 key2

返回key1中存在但是key2中不存在的元素,并将结果存入key3

sinter:sinter key1 key2

返回key1与key2的交集

sinterstore:sinterstore key3 key1 key2

返回key1与key2的交集,并将结果存入key3

sunion:sunion key1 key2

返回key1和key2的并集.

sunionstore:sunionstore key3 key1 key2

取key1和key2的并集,将结果存入key3.

smove:smove key1 key2 value

将value从key1的set中移除并放入key2.

scard:scard key

返回key的set中的元素个数

sismember:sismember key value

测试value是否是key所在set的元素,1 - 是,0 - 否.

srandmember:srandmember key

随机返回key中的一个元素,但是不删除该元素.

4、Sorted Set类型

在set基础上增加一个顺序属性,也是string类型元素的集合。

内部实现采用hashtable和skip list,key为sortedset名字。

zadd:zadd key 1 value

向名为key的sorted set中写入value,排序号为1,多次写入时以最后一次写入的排序号为准.

zrem:zrem key value

删除key所在sorted set中的value

zincrby:zincrby key increment value

在key中value元素的排序号增加increment,如果value不存在,则插入value,且排序号为increment。

zrank:zrank key value

获取名为key的sorted set中的value元素的下标(注意不是score的值)

即按score从小到大排序后该元素的下标.

zrevrank:zrevrank key value

获取名为key的sorted set中的value元素的下标,按score从大到小排序.

zrange:zrange key 0 -1 withscores

获取Key所在的sorted set中从0到-1的所有元素(-1即代表末尾第一个元素).

按score从小到大排序.

zrevrange:zrevrange key 0 -1 withscores

获取Key所在的sorted set中从0到-1的所有元素(按score从大到小排序).

zrangebyscore:zrangebyscore key 1 10 withscores

获取score值为1到10之间的元素.

zcount:zcount key 2 6

返回集合中score在2到6区间内元素的个数.

zcard:zcard key

返回集合中全部元素个数.

zscore:zscore key value

返回集合中value元素的排序号score.

zremrangebyrank:zremrangebyrank key 1 3

删除key所在集合中的1到3下标的元素(根据score从小到大排序)

zremrangebyscore:zremrangebyscore key 1 3

删除key所在集合中排序号score为1到3的元素.

5、hash类型

在redis 2.0中引入了hash数据结构。

当hash中包含超过指定元素个数并且最大的元素没有超过临界时,hash将以一种特殊的压缩编码方式zipmap来存储(大大减少内存使用)。如果元素个数或大小超出了限制,redis会在内部自动将zipmap替换成正常的hash实现。在redis配置文件中可以修改:

hash-max-zipmap-entries 64 //使用zipmap的feild最多64个

hash-max-zipmap-value 512  //使用zipmap的value最大512字节

hset:hset key field value

向key中的field设置value值.

hsetnx:hsetnx key field value

field不存在则创建,field存在则返回0,nx是not exists的意思.

hmset:hmset key field1 value1 field2 value2

同时设置多个field的value.

hget:hget key field

获取key所在hash结构的field值,field不存在则返回空值.

hmget:hmget key field1 field2

同时获取多个field的值.

hincrby:hincrby key field value

给key的field加上value的值.(field必须是数字型)

hexists:hexists key field

检测field是否存在.(1-存在,0-不存在)

hlen:hlen key

返回指定hash的field数量.

hdel:hdel key field

删除指定key所在hash的field.

hkeys:hkeys key

返回该key所在hash的所有field名称.

hvals:hvals key

返回该key所在hash的所有value值.

hgetall:hgetall key

返回该key所在hash的所有field和value.(在list中按先field后value的顺序出现)

6、数据类型排序

sort key [asc|desc|alpha]

asc和desc针对数值型,默认升序,alpha针对字典类型.

sort list by name*

将list里面的元素与name拼接后对key为name的各元素排序,排序结果返回list中对应元素.

sort ml by name* get name* alpha

将list里面的元素与name拼接后对key为name的各元素排序,排序结果返回name拼接后key的value.

http://www.cnblogs.com/redcreen/archive/2011/02/15/1955226.html redis排序详解

7、redis事务

redis是单线程处理所有client请求。

redis只能保证一个client发起的事务中的命令可以连续的执行,而中间不会插入其他client的命令。

一般redis在接收一个命令后会立即处理并返回处理结果,但进入事务上下文后,后面的命令并不立即执行,而是先放到一个队列中。当从此连接受到exec命令后,redis会顺序的执行队列中的所有命令。并将所有命令的运行结果打包到一起返回给client,然后此连接就结束事务下文。

multi:开启事务上下文。

exec:执行事务上下文。

discard:清空事务命令队列并退出事务上下文(回滚)。

redis事务中的一个命令如果失败了,并不会回滚其他命令。

由于事务上下文的命令只排队并不立即执行,所以事务中的写操作不能依赖事务中的读操作结果。

redis从2.1支持乐观锁实现CAS(check and set)操作,可以显示使用watch对某个key加锁。

乐观锁:大多数基于数据版本version的记录机制实现的。

所谓数据版本,即为数据加一个版本标识version列。更新时对此版本号加1,此时将提交数据的版本号与数据库表对应记录的当前版本号进行对比,如果提交数据的版本号大于数据库表当前版本号,则予以更新,否则认为是过期数据。

watch的key对整个连接有效,如果连接断开,则监视和事务都会被自动清除。

当被watch的key在multi之前被修改,则整个事务将跳出,exec命令将返回nil。

execdiscardunwatch命令都会消除连接中所有监视。

事务处理:

watch

multi

exec/discard/unwatch

8、Key操作、服务器管理

keys:keys *

返回满足给定pattern的所有key.

exists:exists key

存在某key返回1,不存在某key返回0.

del:del key

删除key.

expire:expire key 10

设置该key在10秒后过期(单位为秒).

在超过该时间后,Key被自动的删除.如果该Key在超时之前被修改,与该键关联的超时将被移除.

关于redis过期[转自网络]

redis里,把设置了expire time的key叫做:volatile keys,意思就是不稳定的key。

在小于2.1.3的redis版本里,只能对key设置一次expire。

redis2.1.3和之后的版本里,可以多次对key使用expire命令,更新key的expire time。

redis对过期键采用了lazy expiration:在访问key的时候判定key是否过期,如果过期,则进行过期处理。其次,每秒对volatile keys 

进行抽样测试,如果有过期键,那么对所有过期key进行处理。

ttl:ttl key

获取key的有效时常(单位秒),-1代表该键不存在或没有超时设置.ttl为time to live缩写.

move:move key dbnum

将该key移动到dbnum所在数据库中.

persist:persist key

如果Key存在过期时间,该命令会将其过期时间消除,使该Key不再有超时,而是可以持久化存储。

randomkey:randomkey

随机返回当前数据库中的一个key.

rename:rename key newkeyname

将key重命名为newkeyname

type:type key

返回值的类型(string,list,zset等)

ping:ping

测试到redis服务器连接,正常返回pong

echo:echo shensy

在命令行打印shensy

select:select 0~15

选择数据库,redis默认数据库为0~15.

dbsize:dbsize

返回当前数据库中key的数目.

info:info

获取服务器信息和统计.

config get:config get *

获取服务器配置信息.

flushdb:flushdb

删除当前数据库中全部key.

flushall:flushall

删除所有数据库中的全部key.

quit:quit

退出服务器连接.

二、redis配置

1、持久化

(1)快照snapshotting

快照是默认的持久化方式.

将内存中的数据以快照的方式写入二进制文件中,默认文件名为dump.rdb.

正常shutdown数据库时自动会将内存中的数据写入磁盘。

可以配置n秒内如果超过m个key被修改就自动做快照。

save 60 1000 #60秒内1000个key被修改就自动做快照

client也可以使用save或bgsave命令通知redis做一次快照持久化。

save操作是在主线程中保存快照,由于redis用一个主线程来处理所有client请求,这种方式会阻塞所有client请求,不推荐使用。

每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步变更数据。如果数据量大,写操作比较多,必然会引起大量的磁盘io操作。

(2)append-only file方式(aof)

采用快照方式定时持久化如果应用down掉会有数据丢失。

如果要求数据不丢失的话,采用aof方式。

redis每收到一个写命令都追加到文件中(默认appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

当然os会缓存write做的修改,所以使用aof方式还是可能会丢失部分修改。

但可以通过配置文件指定redis通过fsync方法强制os写入磁盘的时间:

appendonly yes #启用aof持久化方式

appendfsync always #收到写命令就立即写入磁盘

appendfsync everysec #每秒钟持久化一次

appendfsync no  #完全依赖os,性能最好,但持久化没有保证

aof方式带来的另一个问题是持久化文件会越来越大.为了压缩aof持久化文件,redis提供了bgrewriteaof命令.

bgrewriteaof:采用与快照类似的方式将内存中的数据以命令方式写入.

注意重写aof文件的操作没有读取旧的aof文件,而是将整个内存中的数据库内容用命令方式重写了一个新的aof文件,这和快照有点类似。

2、分布式master-salve

未发布redis-cluster前,redis的replication又有诸多不便.

redis的master/slave特点

(1)master可以有多个slave,多个slave除了连接到相同的master外,也可以连接到其他slave。

(2)主从复制不会阻塞master。一个或多个slave与master进行初次同步数据时,master可以继续处理client发来的请求,但slave在初次同步时会阻塞不能处理client请求。不是初次同步时,slave会以非阻塞的方式完成数据同步,在同步期间,如果有客户端提交查询请求,Redis则返回同步之前的数据。

(3)主从复制可以用来提高系统的可伸缩性,可以用多个slave专门用于client的读请求,比如sort用slave来处理,也可以用来做简单的数据冗余.

(4)可以在master上禁用数据持久化,在slave上配置数据持久化。

(5)如果master宕机,slave可以读但不能写。手工执行slave of no one或SLAVEOF host port将从实例提升为主实例.如果之间有链接瞬段,或者对slave重新执行slaveof命令,会导致slave机器从头开始同步一次master的数据,造成较大的开销.

原理

在Slave启动并连接到Master之后,它将主动发送一个SYNC命令。

此后Master将启动后台存盘进程,同时收集所有接收到的用于修改数据集的命令,在后台进程执行完毕后,Master将传送整个数据库文件到Slave,以完成一次完全同步。而Slave服务器在接收到数据库文件数据之后将其存盘并加载到内存中。此后,Master继续将所有已经收集到的修改命令,和新的修改命令依次传送给Slaves,Slave将在本次执行这些数据修改命令,从而达到最终的数据同步。

如果Master和Slave之间的链接出现断连现象,或者对slave重新执行slaveof命令,Slave将自动重连Master,但是在连接成功之后,一次从头开始的完全同步将被自动执行。

3、Pipeline批量发布请求

利用pipeline方式从client打包多个指令一起发出去,不需要等待单条命令的服务器端响应返回,而是将多条命令处理结果打包一起返回。

pipeline方式打包命令,redis必须先在处理完全部指令前缓存起所有命令处理结果,因此打包的命令越多则消耗的内存也就越多。所以并不是打包命令越多越好。

4、其它配置项

一篇不错的文章,对各个配置项都作了介绍:

http://netstu.5iunix.net/archives/201203-339/

三、redis特性与应用场景(转自网络)

四、官方性能测试

五、与memcached比较

附参考资料:

redis官网:http://redis.io/commands

Redis学习手册(目录)

http://www.cnblogs.com/stephen-liu74/archive/2012/04/16/2370212.html

redis中文站点

http://redis.cn/ 

Redis下过期时间详解:

http://jiorry.iteye.com/blog/961172

Redis 的6种过期策略:

http://www.blogjava.net/iamct/archive/2011/12/22/367015.html

Redis手动failover:

http://ylw6006.blog.51cto.com/470441/1080211

猜你喜欢

转载自shensy.iteye.com/blog/1782002