Redis最为常用的数据类型:
字符串(String)
哈希(hash)
字符串列表(list)
字符串集合(set)
有序的字符串集合(sorted set)
String(字符串)
redis中最为基础的数据类型,在redis中是以二进制的方式来存储的,所以存入和获取数据相同。
value 最多可以容纳的数据长度是 512M。
-
_
存储String常用的命令:1. 赋值:set 、get 、getset(先设置这个键的值再获取这个键的值)
2. 删除:del
3. 数值增减 : incr、decr
4. 扩展命令:
incrby、decrby :增加或者减少指定的值
append:追加值,返回字符串长度
-
应用场景 : 最常用的一种数据类型, 普通的key - value 存储都可以归为此类。value也可以为数字。
如:常规计数:微博关注数、粉丝数 如:计数器:使用 INCRBY 完成统计“点击数”,由于单线程,可以避免并发问题。
Hash(哈希)
可以看成一个具有String key 和 String value 的类型,也就是键值对类型。所以适合存储 值对象的信息,如用户名、密码、年龄等等
-
每一个hash可以存储4294967295个键值对。
-
存储Hash常用的命令:
-
赋值:hset:设置一个key - value
hmset:设置多个key - value
-
取值:hget:获取一个属性的值
hmget:获取多个属性的值
hgetall:获取所有的属性和属性的值
-
删除:hdel:删除具体值
del:删除整个集合
-
增加数字:hincrby:增加指定定的数字
-
扩展命令:hexists:判断指定key中的某个属性是否存在,存在返回1
hlen:获取属性的数量
keys:获得所有的key
hvalues:获取所有的value
-
-
使用场景:
1. 存储部分变更的数据,如用户数据
2. 验证前端请求是否重复,可以通过redis进行过滤:每次请求将requset Ip、参数、接口等
hash作为key存储,当用户请求过来的时候现在redis中检索有没有这个key,进而验证是不
是一定时间内过来的重复提交。
List(列表)
简单的字符串列表,可以从 头部 或 尾部 向redis列表添加元素。
列表最大的长度为 2^32-1 ,即每个列表支持超过40亿个元素。
-
-
列表类型的两个特性:
1. 列表中的元素是有序的,这就意味着可以通过下标获取某个元素或者某个范围内的元素列表。2. 列表中的元素是可以重复的。
- 从插入和删除角度:如果是在链表的两头插入和删除元素,这是非常高效的。如果插入和删除的操作是作用在链表的中间,那么效率就会比较低了。
-
-
存储数据的方式:
1. arraylist(数组的方式):所以根据”索引“去”查询“是比较快的,但是“新增”和“删除”比较慢,因为涉及到“位移”操作。
2. LinkedList方式(双向链表的方式):对每个元素都记录了前后的“指针”,“插入”和“删除”的时候只是改变元素的“指针”指向即可,所以速度“快”。
3. 双向链表添加数据
4. 双向链表删除数据
-
-
存储List常用的命令:
1. 两端添加:lpush、rpush
2. 查看列表:lrange
3. 两端弹出:lpop、rpop
4. 获取列表元素个数:llen
5. 扩展命令
<1> pushx :当指定的参数中 key “存在”的时候,可以向关联的list头
部插入一个具体的值,如果”不存在”,就不会进行插入
<2> lrem(lremove):
正数:从头开始删除
负数:从尾部、开始 0 : 删除所有
<3> lset : 设置链表中某个index的角标的元素的值
lset mylist 3 mmm : 在第三个角标的时候给他设置值为 mmm
<4> insert:插入元素
linsert mylist before b 11: 在 b 元素之前插入 11
linsert mylist after b 22 : 在 b 元素之后插入 22
<5> rpoplpush:完成插入和弹出操作
<6> rpoplpush 使用场景:list列表经常用于一些消息队列的一些服务,多个程序间消息
的交互。
如: 此时假设一个应用程序正在执行 “lpush” 向链表中去添加新的元素,将这样的程序称为'生
产者' ,另外一个程序正在执行 “rpop” 操作,从链表中取出元素,称为'消费者'与此同时 “消费
者” 元素在取出元素后立刻“崩溃”,由于该消息已经被取出但是没有被正常处理,此时可以认为该
消息已经丢失了,可能会导致业务数据丢失或者业务数据的不一致等现象发生,此时我们可以使用
“rpoplpush” 命令使消费者在主消息队列中取出元素之后再将它插入到一个 “备份”的队列中,
直到消费者完成正常的逻辑处理之后再将消息从备份中删除,这样可以提供一个守护的线程。当备
份中的消息过期之后,可以将消息重新放回到主消息队列当中,以便其他的消费者可以继续去使用。
-
-
应用场景:1. twitter 的关注列表、粉丝列表等都可以用 Redis 的 list结构来实现
2. 抢购:使用redis的原子操作来实现这个“单线程”,首先我们把库存存在good_things:1这个列表中,如果有10件库存,就往列表中push10个数。抢购开始后,每来一个用户,就或从good_things:1中pop一个数,表示抢购成功,列表为空时,表示商品已经被抢完。pop操作是原子性的,此时如果有很多用户同时到达,也是依次执行的。
3. 最新列表:获取前N个最新登录的用户列表
// 获取当前登录人
ret = r.lpush("login:last_login_times", uid)
//限制列表中输在的数据数量
ret = redis.ltrim("login:last_login_times", 0, N-1)
// 获取前N个最新登录的用户Id列表
last_login_list = r.range("login:last_login_times", 0, N-1)
Set(字符集合)
-
-
与list集合的不同:Set集合不允许出现重复的元素,也就是说重复添加多个相同的元素只会保留该元素的一份copy。
功能上: 在服务器端可以完成多个set之间的聚合计算操作,如 unions,difference,这些都是需要在服务器端完成的,因此可以省掉大量的开销。
Set包含的最大元素数量是 4294967295
-
-
存储Set常用的命令:- 添加/删除元素:sadd 、srem
-
获得指定元素:
smembers:获取set中的数据 sismember:判断参数中有没有指定的元素在set里面
-
集合中的差集运算:
sdiff:返回集合当中相差的成员(与key的顺序有关系) sinter:返回交集(都有的数据) sunion:返回并集
-
扩展命令:
scard :获取具体数量 srandmember : 随机返回 set中的成员 sdiffstore:将相差的值存到一个新的集合上 sinterstore:两个集合的交集将他们存到新的集合 sunion: 两个并集的交集将他们存到新的集合
-
-
使用场景:-
使用redis的set类型去跟踪一些具有唯一性的数据,
如:访问某一博客的唯一IP地址的信息,我们只需要在每次访问者访问该博客的时候,将访问者的IP存入到redis当中,然后set类型 会自动的保证IP地址的唯一性
如:set查询该用户名是否被注册,效率极高
如:投票系统中,如果在限制用户一天只能只能投票一次,可以将今天日期作为 set 的key,存取用户额投票行为,从而保证投票唯一。
-
用于维护数据之间的关联关系(利用set类型的服务端聚合)
- 如:所有购买某一个电子设备的ID被存储到一个指定的set当中,而购买另外一个电子产品的客户的ID被存储到另外的一个set当中,而如果此时我们想获取由哪些客户同事购买了这两种产品,那么就可以使用它的一个“交集”的操作来完成。
- 如:将关注人 和 粉丝 存在不同的集合中。redis为集合提供求交集、并集、差集等操作,可方便实现如共同关注、共同喜好等功能,对上面的所有集合操作,还可使用不同命令结果返回给客户端或者存集到一个新的集合中。
-
Sorted-set(有序的set集合):
- 和set集合共同点:都不允许重复的成员出现在set当中
-
-
和set集合的主要区别:- Sorted-Set 中的每一个成员都会有一个“分数”进行关联,而redis正是通过了这个分数来为集合中的成员进行从小到大的排序
- 尽管 Sorted-Set中的成员必须是唯一的,但是分数是可以重复的,那么在 Sorted - Set中“添加、删除、更新”一个成员都是非常快速的操作。
实践复杂度:由成员中的个数到对数。由于Sorted-Set集合中一个位置是有序的,因此访问集合“中部”的这些成员也是非常高效的。redis这一特征在其他很多数据库中都是很难实现的,也就是说在该“点”要想达到和redis一样的高效,在其他数据库中进行“建模”是非常困难的。
-
添加:
zadd : 返回添加的元素的个数 ,如果存在了再添加此元素,会执行“覆盖”。
-
获得元素:
zscore:获取某一元素 zcard:获取具体成员数量
-
删除元素:
zrem :删除某一元素
-
范围查询:
zrange:withsscores 参数:表示将分数也显示出来 zrevrange (更改排序方式):大 ->小
-
排序:
zremrangebyrank : 根据范围删除 zremrangebyscore:根据分数范围删除元素
-
扩展命令:
zrangebyscore : 查找某一分数范围内的元素,withscores表示同时也显示分数。 zincrby:设置指定成员增加多少分数 zcount:获取分数在某个区间的个数
-
-
应用场景:-
排行榜:以“登录次数”为权重,获取登录次数最多的用户将登录次数和用户统一存储在一个sorted set里
zadd login:login_times 5 1 zadd login:login_times 1 2 //当用户登录时,对该用户的登录次数自增1 ret = r.zincrby("login:login_times", 1, uid) //那么如何获得登录次数最多的用户呢,逆序排列取得排名前N的用户 ret = r.zrevrange("login:login_times", 0, N-1)
-
游戏排行榜:获取前100名高分用户,或者获取用户全球排名等
// 将分数写入数据库中 ZADD leaderboard <score> <username> // 实现分数从高到低排名,然后获取0-99,也就是100名游戏玩家 ZREVRANGE leaderboard 0 99 // 获取某用户的全球排名 ZRANK leaderboard <username>
-
Keys的通用操作
-
-
命令:获得所有的keys:keys *
以 ”my“ 开头的keys:keys my?
删除某个指定的keys :del key1 key2
判断某key是否存在:exists my1
获取key : get my1
重命名:rename my1 my2
设置过期时间 : expire my2 1000 (秒)
查看某key过期时间:ttl my1
-
查看key类型: type my1
redis特性
-
-
多数据库:一个redis实例可以包含多个数据库,可以指定连接某个数据库
一个redis实例最多可提供16个数据库,0-15 默认连接:0
-
命令:切换“1”号数据库:select 1
将1号数据库中的“myset”key移动到“0”数据库: move myset 0
-
-
事物:-
事物中所有命令都将会被串行化顺序执行,在执行过程中,redis不会再对其他客户端提供任何服务,从而保证事物的“原子性”
-
-
命令:- 开启事物:mutli,此后的命令都会被存放到一个队列当中,直到执行 exec,这些命令都会被原子化执行了
- 提交:exec,相当于关系型数据库中的commit
- discard:回滚,相当于关系型数据库中的roll-back
-
-
-
-
注意:- 如果在开启事物之前,如果客户端和服务端出现通讯故障导致服务器断开,那么执行的这些语句都将不会被服务器提交。
- 而如果网络中断是发生在exec(执行)之后的,那个这个十五中的所有命令都会被服务器提交。
-
演示一:开启两个窗口
-
演示二:回滚
redis持久化:
redis的高性能是由于所有的数据都存储在内存当中,要是保证在重启之后数据不丢失,就需要将数据从内存同步到硬盘上,这个过程就是redis的持久化操作。
-
持久化方式:
-- RDB方式 -- AOF方式
-
-
持久化的使用方式:- RDB持久化:默认支持,无需配置
指的是在指定的时间间隔内将内存中数据集快照写入到磁盘,即:指定多少s可将数据写入到磁盘一次。
AOF方式:以日志的形式记录服务器所处理的每一个操作。在redis服务器启动之初,他会读取该文件来重新去构建我们的数据库,从而来保证我们数据库中的数据是完整的。
无持久化:通过配置来禁用redis服务器的持久化功能。这样我们将可以认为redis就是一个“缓存”的机制。
同时使用RDB和AOF