1. 关于Redis
1.1 简介
Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
1.1 数据模型
作为Key-value型数据库,Redis也提供了键(Key)和键值(Value)的映射关系。但是,除了常规的数值或字符串,Redis的键值还可以是以下形式之一:
· Lists (列表)
· Sets (集合)
· Sorted sets (有序集合)
· Hashes (哈希表)
键值的数据类型决定了该键值支持的操作。Redis支持诸如列表、集合或有序集合的交集、并集、差集等高级原子操作;同时,如果键值的类型是普通数字,Redis则提供自增等原子操作。
1.3 优缺点
丰富的数据结构,超越了一般的Key-Value数据库,组合使用各种结构,限制Redis用途的只会是你自己的想象力, Redis在互联网上的11种常见用例。
1.4 Redis的性能
下面是官方的bench-mark数据:
· The test was done with 50 simultaneous clients performing 100000 requests.
· The value SET and GET is a 256 bytes string.
· The Linux box is running Linux 2.6, it’s Xeon X3320 2.5Ghz.
· Text executed using the loopback interface (127.0.0.1).
Results: about 110000 SETs per second, about 81000 GETs per second.
2. 数据结构
2.1 Key
Key 可以是任意类型,最后都存成byte[]
Key 不能太长,比如1024字节,但作者也不追求太短,要表达清楚意思才好,作者建议用":"分隔表名,用"."作为单词间的连接。
KEYS显示所有的key,支持通配符 "KEYS a*" , "keys a?c",但不建议在生产环境大数据量下使用。
SORT,对集合按数字或字母顺序排序后返回,或者存到另一个List,还可以关联到外部Key等。因为会耗用CPU,有时会安排到slave上执行。
EXPIRE/EXPREAT/PERSIST/TTL/,关于Key超时的操作,默认以秒为单位,也有p字头的以毫秒为单位的版本。
其他命令: EXISTS,DEL,RENAME/RENAMENX(仅当new key不存在时),MOVE/MIGRATE(实例内从此db到彼db/从此实例到彼实例),RANDOMKEY,TYPE/Object(Key的类型/对象编码类型,空置时间),DUMP/RESTORE(value值的持久化)
2.2 String
最普通的key-value,除了支持最基本的get/set, Redis也很喜欢添加一些简便的指令,在服务端做起来是举手之劳,客户端便方便很多。
incr/decr/incrby/incrbyfloat, 如果key还不存在时创建key并设原值为0。
setEx/pSetEx, Set + Expire 的简便写法,p字头以毫秒为单位。
setNx, key不存在时才put进去。
getset, 设置新值,返回旧值。
mget/mset/msetex, 一次get/set多个key。
getbit/setbit/bitop/bitcount bitmap玩法,比如统计今天的访问用户,每个用户有一个offset,今天进来的话就把那个位为1。
append/setrange/getrange,只对特定的数据格式比如字段定长的有用,json格式就没用。
2.3 Hash
Key-HashMap结构,相比2.2中的JSON格式Value,可以只读取/更新对象的某些属性,有些属性超长就让它一边呆着不动。。
另一个用法是用来建索引。比如User对象,除了id有时还要按name来查询,可以建一个Key为user:index:name的Hash,在插入User对象时(set user:101 {"id":101,"name":"calvin"}), 顺便往这个hash插入一条(hset user:index:name calvin 101),这时calvin作为hash里的一个key,值为101。按name查询的时候,用hget user:index:name calvin 就能从名为calvin的key里取出id。
2.4 List
Redis里可以当双向链表来用,还提供blocking版本的pop函数,可以当Message Queue来用。
不过List并没有JMS的ack机制,如果消费者把job给Pop走了又没处理完就死机了怎么办? 解决方法之一是加多一个sorted set,以分发时间为score,用户把job做完了之后要去消掉它。
除了List标准的双向POP/PUSH外,还支持对队列内容的直接操作,比如LREM/LSET/LINSERT/LINDEX。
另外经常用LTRIM限制List的大小,比如只保留最新的20条消息。LRANGE不同于POP直接弹走元素,只是返回列表内一段下标的元素。LLEN获取列表的长度。
2.5 Set
Set就是Set,还提供一些交集,并集,差集的集合操作。
2.6 Sorted Set
有序集,元素放入集合的时候要同时提供该元素的分数。
ZRANGE/ZREVRANGE 按排名的上下限返回元素,正数与倒数。
ZRANGEBYSCORE/ZREVRANGEBYSCORE 按分数的上下限返回元素,正数与倒数。
ZREMRANGEBYRANK/ZREMRANGEBYSCORE 按排名/按分数删除元素。
ZCOUNT 统计分数上下限之间的元素个数。
ZSCORE/ZINCRBY 显示元素的分数/增加元素的分数。
ZADD/ZREM/ZCARD/ZINTERSTORE/ZUNIONSTORE 集合操作与SET相同,少了个差集的操作。
2.7 事务
用Multi/Exec/Discard实现, 隔离级别是这边事务一天不提交,那边另一个事务还是看到旧的值。 还有个Watch指令,起到CAS的效果,如果事务提交时,Key的值已被别的事务改变,事务会被打断。
2.8 Lua Script
Redis2.6内置的Lua Script支持,可以在Redis的Server端一次过运行大量逻辑。
整个Script默认是在一个事务里的。
Script里涉及的所有Key尽量用变量,从外面传入,使Redis一开始就知道你要改变哪些key。
EVAL每次传输一整段Script比较费带宽,可以先用SCRIPT LOAD载入script,返回哈希值。然后用EVALHASH执行。
内置的LUA库里还很贴心的带了CJSON,可以处理JSON字符串。
3.redis数据存储
redis的存储分为内存存储、磁盘存储和log文件三部分,配置文件中有三个参数对其进行配置。
save seconds updates,save配置,指出在多长时间内,有多少次更新操作,就将数据同步到数据文件。这个可以多个条件配合,比如默认配置文件中的设置,就设置了三个条件。
appendonly yes/no ,appendonly配置,指出是否在每次更新操作后进行日志记录,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为redis本身同步数据文件是按上面的save条件来同步的,所以有的数据会在一段时间内只存在于内存中。
appendfsync no/always/everysec ,appendfsync配置,no表示等操作系统进行数据缓存同步到磁盘,always表示每次更新操作后手动调用fsync()将数据写到磁盘,everysec表示每秒同步一次。
4.redis主从配置
redis支持master-slave的主从配置,配置方法是在从机的配置文件中指定slaveof参数为主机的ip和port即可。
5.redis学习资料
《The Little Redis Book》最好的入门小册子,可以先于一切文档之前看,免费版,会不时更新。