文章目录
特点
内存
单线程
KV
IO多路复用器《-》redis
redis只是通过多路复用器获取到IO事件,程序自己要读写IO
获取IO事件-》计算-》R/W
都是串行的(因为是单线程,一次只能处理一个线程)
——》IO的输出其实是有间隔的
输出是有间隔的:
比较memcache和redis
memcache:json存在string里
客户端请求数据的时候,只能请求到所有的json数据
redis:会建立本地方法,存在list
客户端请求的时候,只需要告诉服务器需要哪个数据index,不用操作全量
单线程:
假设2个client一起来请求,那么redis处理时候肯定是串行的
串行化,操作是原子
如何利用多核CPU
5种Value类型和应用场景
string
二进制安全:必须将数据变成字节数组交给redis
不管客户端什么编码集,redis数据不会乱
127.0.0.1:6379> help @string help查看所有api
127.0.0.1:6379> set k1
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> set k1 hello
OK
127.0.0.1:6379> get k1
"hello"
127.0.0.1:6379> strlen k1 获取长度
(integer) 5
127.0.0.1:6379> append k1 ooxx
(integer) 9
127.0.0.1:6379> get k1
"helloooxx"
127.0.0.1:6379> set k3 99
OK
127.0.0.1:6379> incr k3 还可以做数字计算
(integer) 100
setbin
开辟字节,把左边index=1的位置设置为1
setbit k1 1 1
动态扩宽字节数量
统计1的个数
0~-1 所有字节的1
0~0 第一个字节上的1
逻辑运算
bintop or 结果key 要参与的key...
k1: 0100 0001 = @
k2: 0100 0010 = B
k1 and k2 : 0100 0000 = @ ???
k1 or k2 : 0100 0011 = C
场景
- 统计一年365天,用户登陆天数
每天是一个bit, 一个人就46个字节
- 京东,在过节时候只要用户登陆了就送礼物,双十一之前要被多少件礼物。(一共2E用户)
活跃用户数才是备货的参考。
假设20200101,用户2,8登陆了
20200102,用户8登陆了
那么活跃人数就是 这俩日期key的or运算
- 12306
list
双向链表.key指向链表头尾
list放入是有序的,不会排序
127.0.0.1:6379> lpush key1 a b c d e 倒着放进去的,从左边往右压
(integer) 5
127.0.0.1:6379> lrange key1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379> rpush key2 a b c d e 从右边压进去
(integer) 5
127.0.0.1:6379> lrange key2 0 -1 从左遍历就是正序
1) "a"
2) "b"
3) "c"
4) "d"
5) "e"
-》
放入和取出同向:栈
放入和取出异向:队列
数组
删除
注意,ltrim是删除start-stop之外的数据。保留 start-stop
127.0.0.1:6379> ltrim key1 0 -1 全部保留
OK
127.0.0.1:6379> lrange key1 0 -1
1) "e"
2) "d"
3) "c"
4) "b"
5) "a"
127.0.0.1:6379> ltrim key1 1 2 保留index = 1 ~2
OK
127.0.0.1:6379> lrange key1 0 -1
1) "d"
2) "c"
场景:
分页
hash
redis本身就是map,用hash是为了减少key
map<key, map<id, value>>
127.0.0.1:6379> hset sean id 123 key为sean,value 为 id-123 的键值对
(integer) 1
127.0.0.1:6379> hset sean age 18 key为sean,value 为 age-18 的键值对
(integer) 1
127.0.0.1:6379> keys *
1) "sean"
2) "rank"
127.0.0.1:6379> hgetall sean 可以取得所有的键值对
1) "id"
2) "123"
3) "age"
4) "18"
127.0.0.1:6379> hkeys sean 也可以只取字段
1) "id"
2) "age"
127.0.0.1:6379> hvals sean 也可以只取value
1) "123"
2) "18"
127.0.0.1:6379> hget sean age 也可以根据字段取value
"18"
127.0.0.1:6379> hincrby sean age -1 可以做数值运算
(integer) 17
127.0.0.1:6379> hget sean age
"17"
场景
商品详情页,当维度比较多的时候
聚合场景
set
集合耗时,尽量别用
去重,无序
127.0.0.1:6379> sadd k1 ooxx xxoo oxox xoxo ooxx
(integer) 4
127.0.0.1:6379> smembers k1
1) "xoxo"
2) "xxoo"
3) "ooxx"
4) "oxox"
127.0.0.1:6379> srandmember k1
"ooxx"
127.0.0.1:6379> srandmember k1 3 返回一个无序的集合,数量为3
1) "xoxo"
2) "ooxx"
3) "oxox"
127.0.0.1:6379> srandmember k1 -3 负数表示允许重复
1) "oxox"
2) "ooxx"
3) "ooxx"
127.0.0.1:6379> srandmember k1 8 8>当前集合数时,只能返回4个
1) "xoxo"
2) "xxoo"
3) "ooxx"
4) "oxox"
127.0.0.1:6379> srandmember k1 -8 负数表示允许重复,必然返回一个数量为8的集合。(可能会导致一个元素出现多次)
1) "ooxx"
2) "oxox"
3) "ooxx"
4) "ooxx"
5) "oxox"
6) "oxox"
7) "xoxo"
8) "oxox"
127.0.0.1:6379> sadd k1 a b c d e
(integer) 5
127.0.0.1:6379> sadd k2 c d e f g
(integer) 5
127.0.0.1:6379> sunion k1 k2 并集
1) "f"
2) "b"
3) "d"
4) "a"
5) "g"
6) "c"
7) "e"
127.0.0.1:6379> sinter k1 k2 交集
1) "d"
2) "e"
3) "c"
127.0.0.1:6379> sdiff k1 k2 左差集
1) "b"
2) "a"
127.0.0.1:6379> sdiff k2 k1 右差集
1) "g"
2) "f"
场景
抽奖-生产随机集合
推荐系统(推荐好友,推荐商品)
共同好友
sorted set / zset
同一批数据,一定要给出一个score才能知道到底咋排
为啥排序-为了知道一个rank排名
127.0.0.1:6379> zadd k1 4 apple 3.2 banana 1.6 orange
(integer) 3
127.0.0.1:6379> zrange k1 0 -1
1) "orange"
2) "banana"
3) "apple"
127.0.0.1:6379> zrange k1 0 -1 withscores
1) "orange"
2) "1.6000000000000001"
3) "banana"
4) "3.2000000000000002"
5) "apple"
6) "4"
127.0.0.1:6379> zrevrange k1 0 1 withscores 反转,从大到小
1) "apple"
2) "4"
3) "banana"
4) "3.2000000000000002"
场景
排行榜 :
score 为1时,也有一个字典排序。然后随着score变化,实时排序
评论:
score为评论点赞数或者评论时间
+动态分页
底层数据结构
127.0.0.1:6379> type k1 查看类型
zset
127.0.0.1:6379> object encoding k1 查看底层存储类型
"ziplist"
127.0.0.1:6379> zadd k1 99 ajflkjsfaslfnalskdjfawlmfisjfqhlfksfkjasfalsjfklajelnalskldfajlsfjalsfjajf
(integer) 1
127.0.0.1:6379> object encoding k1 让number变的很大,底层存储结构也会改变
"skiplist"
127.0.0.1:6379>
多了很多层,随机造层,牺牲空间。
造层(构造):随机造层(抛硬币),从最低层开始
第一层问第0层元素,你有没有上一层,有的话就造,然后改下临近的指针
插入元素:查找层
问:会不会造太多层:
有一个MAXLEVEL = 64 最大层数
redis持久化内存
用来回复
rdb, aof