redis简介
redis是一个开源,高性能,基于key-value的缓存存储系统,通过多种键值数据类型来适应不同应用场景的缓存与存储需求。
redis是Remote Dictionary Server(远程字典服务器)的缩写,允许其他应用使用TCP协议读写字典的内容。目前redis提供5种键值数据类型。
- string(字符串类型)
- hash(散列/哈希类型)
- list(列表类型)
- set(集合类型)
- zset(有序集合类型)
redis优点
为啥要用reids呢?mysql不行嘛?
- 快! redis 非常快,每秒可执行大约 110000 次的设置(SET)操作,每秒大约可执行 81000 次的读取/获取(GET)操作。(下图是我本机测试的,当然每台电脑不一样看性能的,使用redis-benchmark -n 100000 -q 测试)
原子性! 所有 Redis 操作都是原子操作,这确保如果两个客户端并发访问,Redis 服务器能接收更新的值,因为redis是单线程的。
丰富的数据类型! redis 支持开发人员常用的大多数数据类型,例如列表,集合,排序集和散列等等。这使得 Redis 很容易被用来解决各种问题,因为我们知道哪些问题可以更好使用地哪些数据类型来处理解决。
实用工具! Redis 是一个多实用工具,可用于多种用例,如:缓存,消息队列(Redis 本地支持发布/订阅),应用程序中的任何短期数据,例如,web应用程序中的会话,网页命中计数等。
redis基本命令
KEYS pattern(符合规则的键名列表)
KEYS pattern
其中pattern支持glob风格通配符的格式,另外由于KEYS命令需要遍历redis中所有的key,而且redis又是单线程的,当key较多时会影响性能,生产环境建议别用喔。
EXISTS key(判断key是否存在)
EXISTS key
如果key存在则返回整数类型1,否则返回0
DEL key…(删除键)
DEL key…
可以删除一个或多个key,返回值是删除键的个数。
TYPE key(获得key的类型)
TYPE key
如果key不存在返回none,否则返回五种数据类型其中一个。
redis五种基本数据结构
Redis 有 5 种基础数据结构,它们分别是:string(字符串)、list(列表)、hash(字典)、set(集合) 和 zset(有序集合)。
string(字符串)
string简介
字符串类型是redis中最基本的数据类型,它能够存储任何形式的字符串,一个字符串类型的最大容量是512MB。从源码的 sds.h/sdshdr 文件 中可以看到 Redis 底层对于字符串的定义 SDS,即 Simple Dynamic String 结构:
1 | /* Note: sdshdr5 is never used, we just access the flags byte directly. |
为了对内存做到极致的优化,不同长度的字符串使用不同的结构体来表示。
SDS 与 C 字符串的区别
为什么不考虑直接使用 C 语言的字符串呢?因为 C 语言这种简单的字符串表示方式 不符合 Redis 对字符串在安全性、效率以及功能方面的要求。我们知道,C 语言使用了一个长度为 N+1 的字符数组来表示长度为 N 的字符串,并且字符数组最后一个元素总是 ‘\0’。(下图就展示了 C 语言中值为 “Redis” 的一个字符数组)。
直接使用c字符串会有哪些问题呢?
获取字符串长度为 O(N) 级别的操作 → 因为 C 不保存数组的长度,每次都需要遍历一遍整个数组;
不能很好的杜绝 缓冲区溢出/内存泄漏 的问题 → 跟上述问题原因一样,如果执行拼接 or 缩短字符串的操作,如果操作不当就很容易造成上述问题;
C 字符串 只能保存文本数据 → 因为 C 语言中的字符串必须符合某种编码(比如 ASCII),例如中间出现的 ‘\0’ 可能会被判定为提前结束的字符串而识别不了;
string基本命令
赋值和取值
1 | 127.0.0.1:6379> SET key value |
当键不存在时会放回空结果(nil)
递增整数
1 | 127.0.0.1:6379> set num 0 |
当字符串是整数类型的时候,可以通过incr方法递增,并返回递增后的值,如果不是整数类型则会报错。
递减整数
1 | 127.0.0.1:6379> decr num |
decr递减,其他事项如上面一样。
增加指定的整数
1 | 127.0.0.1:6379> incrby num 100 |
incrby跟递增一样,只是可以指定增加的整数。
减少指定的整数
1 | 127.0.0.1:6379> decrby num 100 |
decrby跟递减一样,只是可以指定减少的整数。
增加指定浮点数
1 | 127.0.0.1:6379> incrbyfloat num 100.123 |
incrbyfloat同上上,只是加的变成浮点数了。。
向尾部追加值
1 | 127.0.0.1:6379> set key TOM |
append作用是向尾部追加value,如果key不存在则设置值为value,返回值是追加后字符串的长度。
获取字符串长度
1 | 127.0.0.1:6379> strlen key |
返回键值的长度,如果键不存在则返回0
同时获得/设置多个值
1 | 127.0.0.1:6379> MSET key1 value1 key2 value2 key3 value3 |
MSET/MGET 跟SET/GET一样,只是可以同时设置/获取多个键值。
位操作
一个字节由8位二进制组成,在reids中提供了4个命令来直接对二进制位进行位操作。
1 | 127.0.0.1:6379> SET bit bar |
GETBIT 命令可以获得一个字符串类型指定位置的二进制位的值(0/1),索引从0开始。
1 | 127.0.0.1:6379> GETBIT bit 0 |
SETBIT命令可以设置字符串类型指定位置的二进制位的值(0/1),返回值是该位置的旧值。
1 | 127.0.0.1:6379> SETBIT bit 6 0 |
BITCOUNT命令可以获得字符串类型中二进制位位1的个数。当然也可以只统计指定范围的。
1 | 127.0.0.1:6379> BITCOUNT bit |
BITOP命令可以对多个字符串类型进行位运算,并将结果存储在指定key中,BITOP命令支持AND、OR、XOR、NOT等位运算操作。
1 | 127.0.0.1:6379> BITOP OR result bit1 bit2 |
BITPOS命令可以对指定键的第一个位是0或者1的位置,例如bit1为bar,返回值为1,则表示“bar”中第一个值为1的二进制偏移量为1。
1 | 127.0.0.1:6379> BITPOS bit1 1 |
hash(哈希/散列)
redis的hash类型相当于java中的HashMap,内部实现也差不多一样的,都是通过数组+链表的链地址法解决哈希冲突的。散列类型适合存储对象。
hsah基本命令
赋值和取值
在哈希列表中使用HSET和HGET来设置/获取字段值。
HSET key field value 设置值
HGET key field 获取值
另外HSET命令不区分是INSERT还是UPDATE操作,当执行的是INSERT操作时会放回1,执行时UPDATE操作会返回0,当键本身不存在,HSET命令也会自动创建的拉。
1 | 127.0.0.1:6379> HSET student:1 name xiaoming |
跟字符串一样,可以通过HMSET和HMGET来同时设置/获取多个字段值。
1 | 127.0.0.1:6379> HMSET student:1 age 18 sex male |
判断字段是否存在
HEXISITS key field 用来判断一个字段是否存在,如果存在则返回1,否则返回0。
1 | 127.0.0.1:6379> HEXISTS student:1 name |
当字段不存在时赋值
HSETNX key field value HSETNX与HSET类似,区别在于字段如果已经存在了,HSETNX将不执行任何操作。
1 | 127.0.0.1:6379> HSETNX student:1 name xiaohong |
删除字段
HDEL key field… HDEL可以删除一个或多个字段,返回值时删除字段的个数。
1 | 127.0.0.1:6379> HDEL student:1 name |
只获得字段名或者字段值
HKEYS key 获得键中所有字段名
HVALS key 获得键中所有字段值
1 | 127.0.0.1:6379> HMSET student:1 name xiaoming age 18 sex male |
list(列表)类型
list简介
redis的list相当于java中的LinkedList,它内部时基于双向链表实现的。这意味着它插入和删除特别快,但是随机访问比较慢。
1 | typedef struct listNode { |
list基本命令
向两端添加元素
LPUSH key value… 向列表左边添加元素,返回新列表长度
RPUSH key value… 向列表右边添加元素,返回新列表长度
1 | 127.0.0.1:6379> LPUSH num 1 |
向两端弹出元素
LPOP key 从列表左边弹出一个元素,返回元素值,如果列表为空则返回nil
RPOP key 从列表右边弹出一个元素,返回元素值,如果列表为空则返回nil
1 | 127.0.0.1:6379> LPUSH num 1 2 3 4 5 |
获得列表中元素个数
LLEN key 获得列表长度,如果列表不存在则返回0
1 | 127.0.0.1:6379> LLEN num |
获得列表片段
LRANGE key start stop 获得列表从start到stop(包括stop)的片段,redis起始索引从0开始。LRANGE命令支持负索引,例如-1表示最右边第一个元素,-2表示最右边第二个元素。
注意事项:
- 如果start索引位置比stop索引位置靠后则会返回空列表。
- 如果stop大于实际索引范围则会返回列表最右边的元素
1 | 127.0.0.1:6379> LPUSH num 1 2 3 4 5 6 7 8 9 |
删除列表中指定值
LREM key count value 删除列表中前count个值为value的元素,返回值是实际删除元素个数,根据count值的不同,执行起来也不一样
- 当count>0,列表会从左到右开始删除前count个value值元素。
- 当count<0,列表会从右到左开始删除前|count|个value值元素。
- 当count=0.列表会删除所有值为value的元素。
set(集合)类型
set简介
redis集合相当于java中的HashSet,内部键值对是无序,唯一的。在redis内部实现中是使用value为空的散列表实现的,所有这些操作时间复杂度是O(1),而且多个集合类型之间还可以进行并集,交集,差集等操作。
set基本命令
添加/删除元素
SADD key member.. 添加一个或多个元素,如果元素已经存在则忽略,返回成功加入元素个数
SREM key member.. 删除一个或多个元素,返回删除成功的元素个数。
1 | 127.0.0.1:6379> SADD set Hello |
获得集合中的所有元素
SMEMBERS key 返回集合中所有的元素
1 | 127.0.0.1:6379> SMEMBERS set |
集合间运算
SDIFF key… 对多个集合进行差集运算。集合A与集合B的差集表示为A-B,代表属于A且不属于B的元素集合,例如:
1 | 127.0.0.1:6379> SADD set1 1 2 3 4 5 |
SINTER key… 对多个集合进行交集运算。集合A与集合B的交集表示为A∩B,代表属于A且属于B的元素集合,例如:
1 | 127.0.0.1:6379> SINTER set1 set2 |
SUNION key… 对多个集合进行并集运算。集合A与集合B的并集表示为A∪B,代表属于A或属于B的元素集合,例如:
1 | 127.0.0.1:6379> SUNION set1 set2 |
zset(有序列表)类型
zset简介
zset有序列表,它比较特殊算的上是redis中最高级的类型了,内部实现是通过【跳跃表】来实现的。一方面他是集合,保证了唯一性,另一方面它每个value都有score值,用来实现排序权重。
zset基本命令
添加元素
ZADD key score member [score member…]
ZADD用来向有序集合中加入一个元素和元素分数,如果元素值存在则会用新分数替换已有分数,返回值是新加入到集合中的元素个数。
其中score可以是整数,浮点数。
1 | 127.0.0.1:6379> ZADD score 87 Tom 67 Peter 100 Xiaoming |
获得元素分数
ZSCORE key member
获得元素分数
1 | 127.0.0.1:6379> ZSCORE score Xiaoming |
获得在某个范围的元素列表
ZRANGE key start stop [WITHSOCRES]
ZRANGE命令会按照元素分数从小到大顺序返回索引从start到stop之间的所有元素(包含stop)。同时如果想要获得元素的元素分数可以在 ZRANGE命令尾部加上WITHSCORES。
1 | 127.0.0.1:6379> ZRANGE score 0 -1 |
获得指定分数范围的元素
ZRANGEBYSCORE key min max [WITHSCORES] [LIMIT offset count]
ZRANGEBYSCORE命令按照元素分数从小到大的顺序返回,分数在min和max之间(包含max)的元素。另外如果不想包括端点值可以在前面加(
后面那两个可选参数跟数据库一样的就不在写了。
1 | 127.0.0.1:6379> ZRANGEBYSCORE score 80 +inf |
1 | 127.0.0.1:6379> ZINCRBY score 10 Tom |
增加某个元素的分数
ZINCRBY key incrment member
ZINCRBY 可以增加一个元素的分数,返回值是更改后的分数。
redis命名推荐
在redis中对键的命名没有强制的要求,但比较好的命名是—对象类型:对象ID:对象属性,例如使用user:1:friends来存储ID为1的用户好友列表。另外键的命名一定要有可读性有意义,例如u:1:f虽然可以节省内存空间但是可读性很明显不好,孰重孰轻还是要分的清的。