Redis 是典型的 NoSQL 数据库。
redis官网:Download | Redis
Redis 是一个开源的 key-value 存储系统。
和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string、list、set、zset、sorted set、hash。
这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。
在此基础上,Redis 支持各种不同方式的排序。
与 memcached一样,为了保证效率,数据都是缓存在内存中。
区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。
并且在此基础上实现了master-slave (主从)同步。
单线程 + IO 多路复用。
常用五大基本数据类型
key操作
keys *
:查看当前库所有 key 备注(超级常用)
exists key
:判断某个 key 是否存在
type key
:查看你的 key 是什么类型
del key
:删除指定的 key 数据
unlink key
:根据 value 选择非阻塞删除,仅将 keys 从 keyspace 元数据中删除,真正的删除会在后续异步操作
expire key 10
:为给定的 key 设置过期时间
ttl key
:查看还有多少秒过期,-1表示永不过期,-2表示已过期
select
:命令切换数据库
dbsize
:查看当前数据库的 key 的数量
flushdb
:清空当前库 备注(超级常用)
flushall
:通杀全部库 备注(超级常用)
字符串(String)
String 类型是二进制安全的。意味着 Redis 的 string 可以包含任何数据。比如 jpg 图片或者序列化的对象。
String 类型是 Redis 最基本的数据类型,一个 Redis 中字符串 value 最多可以是 512M。
set <key><value>
:添加键值对
get <key>
:查询对应键值列如:set k1 100
get k1
append <key><value>
:将给定的 <value> 追加到原值的末尾
strlen <key>
:获得值的长度列如:append k1 abc
strlen k1
setnx <key><value>
:只有在 key 不存在时,设置 key 的值
incr <key>
:将 key 中储存的数字值增 1,只能对数字值操作,如果为空,新增值为 1(具有原子性)
decr <key>
:将 key 中储存的数字值减 1,只能对数字值操作,如果为空,新增值为 -1
incrby/decrby <key><步长>
:将 key 中储存的数字值增减。自定义步长
mset <key1><value1><key2><value2>
:同时设置一个或多个 key-value 对
mget <key1><key2><key3>...
:同时获取一个或多个 value
msetnx <key1><value1><key2><value2>...
:同时设置一个或多个 key-value 对,当且仅当所有给定 key 都不存在
getrange <key><起始位置><结束位置>
:获得值的范围列如: getrange k1 0 1
setrange <key><起始位置><value>
:用 <value> 覆写 <key> 所储存的字符串值列如: setrange k1 0 99999999
setex <key><过期时间><value>
:设置键值的同时,设置过期时间,单位秒。列如: setex age 60 value90
getset <key><value>
:以新换旧,设置了新值同时获得旧值。gteset k1 100000
原子性
所谓 原子 操作是指不会被线程调度机制打断的操作;
这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
-
在单线程中, 能够在单条指令中完成的操作都可以认为是”原子操作”,因为中断只能发生于指令之间。
-
在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis 单命令的原子性主要得益于 Redis 的单线程。
数据结构
内部结构实现上类似于 Java 的 ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.
列表(List)
Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。
它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。
lpush/rpush <key><value1><value2><value3> ....
: 从左边/右边插入一个或多个值。
1 2 3 4 5 6 7lpush k1 v1 v2 v3 lrange k1 0 -1 输出:v3 v2 v1 ---- rpush k1 v1 v2 v3 rrange k1 0 -1 输出:v1 v2 v3
Copy
lpop/rpop <key>
:从左边/右边吐出一个值。值在键在,值光键亡。
rpoplpush <key1><key2>
:从 <key1> 列表右边吐出一个值,插到 <key2> 列表左边。
lrange <key><start><stop>
:按照索引下标获得元素(从左到右)
lrange mylist 0 -1 0
:左边第一个,-1右边第一个,(0 -1表示获取所有)
lindex <key><index>
:按照索引下标获得元素(从左到右)
llen <key>
:获得列表长度
linsert <key> before/after <value><newvalue>
:在 <value> 的前面/后面插入 <newvalue> 插入值
lrem <key><n><value>
:从左边删除 n 个 value(从左到右)
ltrim <key><start><end>
:按照索引截取下标元素(从左到右)
lset<key><index><value>
:将列表 key 下标为 index 的值替换成 value
数据结构
List 的数据结构为快速链表 quickList。
首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是 ziplist,也即是压缩列表。
它将所有的元素紧挨着一起存储,分配的是一块连续的内存。
当数据量比较多的时候才会改成 quicklist。
因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是 int 类型的数据,结构上还需要两个额外的指针 prev 和 next。
Redis 将链表和 ziplist 结合起来组成了 quicklist。也就是将多个 ziplist 使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。