利用Docker学习Redis笔记(一)

Redis

参考B站狂神说视频写的笔记,喜欢的可以去B站搜索狂神说

菜鸟成长之路,不喜勿喷,想交流的评论一起交流

Nosql概述

单机MySql

在这里插入图片描述

更多的使用静态的HTML~服务器根本没有压力,单机Mysql完全够用

这个情况下:网站的瓶颈:

1.数据量如果太大,一个机器放不下了!

2.数据的索引 单表数据超过300万就要建立索引

(B+Tree),一个机器内存也存不下了

3.访问量(读写混合),一个服务器承受不了

只要出现其中之一,网站就必须要升级了

缓存

Memcached(缓存)+MySQL+垂直拆分(读写分离)

在这里插入图片描述

每次查询数据库会很麻烦,所以我们希望减轻数据压力

发展过程:优化数据结构和索引—>文件缓存(IO)---->Memcached

分库分表+水平拆分+MYSQL集群

每个集群存一部分数据

本质:数据库(读,写)

MyISAM:表锁(100万条数据 查一个数据锁一张表)

高并发下就会出现严重的问题

Innodb:行锁

慢慢就开始使用分库分表来解决写的压力!

在这里插入图片描述

到如今

MYSQL关系型数据库就不够用了!数据量很多,变化很快

图形 JSON

MYSQL有的使用它来存储比较大的文件,博客,图片。。。数据库表很大,效率低

有一种数据库用来专门处理这种数据

MYSQL压力就变小了

大数据的IO压力 下 表几乎没办法更大

如今的服务器架构

在这里插入图片描述

Nosql = Not Only SQL

泛指非关系型数据库,随着web2.0诞生,传统型的关系型数据库很难对付web2.0时代!尤其是超大规模的高并发场景

关系型数据库: 表格 行 列

NoSQL特点

1.方便扩展(数据之间没有关系,很好扩展)

2.大数据量高性能

​ Redis一秒可以写8万次,读取11万条数据

​ NoSQL的缓存记录集,是一种细粒度的缓存,性能比较高

3.数据类型多类型

​ 不需要事先设计数据库!:随取随用

4.传统RDBMS和NOSQL区别

传统的RDBMS
    -结构化组织
    -SQL
    -数据和关系都存在单独的表中
    -操作  数据定义语言
    -严格的一致性
    -基础的事务操作
NoSQL
    -不仅仅是数据
    -没有固定的查询语言
    -键值对存储,列存储,文档存储,图形数据库(社交关系)
    -最终一致性
    -CAP定理和BASE理论  (异地多活)
    -高性能,高可用,高可扩
    -。。。

大数据了解3V+3高

在这里插入图片描述

阿里巴巴演进分析

此处省略,有兴趣的可以去百度看看O

NoSql的四大分类

KV键值对

  • 新浪:Redis
  • 美团:Redis+Tair
  • 阿里、百度:Redis+Memecache

文档型数据库bson格式(和json一样)

  • MongoDB

    ​ 是一个基于分布式文件存储的数据库,C++编写,主要处理大量的文档

    ​ MongoDB是一个介于关系型数据库与非关系型数据库的中间产品,MongoDB是非关系型数据库中功能最丰富功能最像关系型数据库的!!

  • ConthDB

列存储数据库

  • HBase(大数据)
  • 分布式文件系统

图形关系数据库

  • 存储关系的拓扑图,朋友圈社交网络之间的关系,广告推荐。。。。
  • Neo4j,InfoGrid

Redis入门

概述

Redis是什么

远程字典服务,支持网络,C语言编写,KV数据库

Redis能做什么

1.内存存储、持久化(内存是断电即失rdb、aof)

2.效率高,可用于高速缓存

3.发布订阅系统

4.地图信息分析

5.计时器、计数器(浏览量!)

6……

特性

1.多样的数据类型

2.持久化

3.集群

4.支持事务

……

Linux安装redis

1.下载安装包

2.解压Redis的安装包

[root@bogon opt]# tar -zxvf redis-6.0.9.tar.gz 

在这里插入图片描述

3.进入Redis

[root@bogon opt]# cd redis-6.0.9/

在这里插入图片描述

4.基本的环境安装

[root@bogon redis-6.0.9]# yum install gcc-c++

make

我以前已经安装过了,这里就省略了

镜像安装

教程网络很多跟着做就行

docker start redis#这个地方名字些什么我们启动的时候些什么

连接客户端语句

docker exec -it myredis redis-cli

关闭myredis服务

docker stop redis

查看当前涉及到redis的进程

[root@bogon docker]# ps -ef|grep redis

工具使用

redis-benchmark压力测试工具

序号选项描述默认值
1-h指定服务器主机名127.0.0.1
2-p指定服务器端口6379
3-s指定服务器 socket
4-c指定并发连接数50
5-n指定请求数10000
6-d以字节的形式指定 SET/GET 值的数据大小2
7-k1=keep alive 0=reconnect1
8-rSET/GET/INCR 使用随机 key, SADD 使用随机值
9-P通过管道传输 请求1
10-q强制退出 redis。仅显示 query/sec 值
11–csv以 CSV 格式输出
12-l生成循环,永久执行测试
13-t仅运行以逗号分隔的测试命令列表。
14-IIdle 模式。仅打开 N 个 idle 连接并等待。

我们简单测试一下

#测试是否连接正常
[root@bogon docker]# docker exec -it myredis redis-cli
127.0.0.1:6379> ping
PONG

#测试100个并发连接   100000请求
docker exec -it myredis redis-benchmark -h localhost -p 6379 -c 100 -n 100000

分析

====== SET ======
  100000 requests completed in 3.56 seconds		#10万个请求3.56s
  100 parallel clients		#100个并发客户端
  3 bytes payload		#每次写入3个字节
  keep alive: 1			#只有一台服务器来处理这些请求,单机性能
  host configuration "save": 
  host configuration "appendonly": yes
  multi-thread: no

6.49% <= 1 milliseconds		#第一毫秒处理了
44.88% <= 2 milliseconds
80.50% <= 3 milliseconds
93.31% <= 4 milliseconds
98.07% <= 5 milliseconds
99.48% <= 6 milliseconds
99.73% <= 7 milliseconds
99.80% <= 8 milliseconds
99.85% <= 9 milliseconds
99.88% <= 10 milliseconds
99.90% <= 11 milliseconds
99.90% <= 12 milliseconds
99.92% <= 15 milliseconds
99.92% <= 16 milliseconds
99.94% <= 17 milliseconds
99.98% <= 18 milliseconds
100.00% <= 18 milliseconds
28074.12 requests per second		#每秒处理多少请求

基础的知识

redis默认的有16个数据库

默认使用的是第0个数据库

可以使用select切换数据库

127.0.0.1:6379> select 3	#切换数据库
OK
127.0.0.1:6379[3]> DBSIZE	#查看数据库大小
(integer) 0
127.0.0.1:6379[3]> set name wangqinghua
OK
127.0.0.1:6379[3]> DBSIZE	#只针对于3号数据库,其他数据库没有
(integer) 1

查看当前数据库所有的key

127.0.0.1:6379[3]> keys *
1) "name"
127.0.0.1:6379[3]> get name
"wangqinghua"

清除当前的数据库

127.0.0.1:6379[3]> flushdb
OK
127.0.0.1:6379[3]> keys *
(empty array)

清除全部数据库的内容

127.0.0.1:6379> select 3
OK
127.0.0.1:6379[3]> flushall
OK
127.0.0.1:6379[3]> select 0
OK
127.0.0.1:6379> keys *		#本来我们测试性能的时候插入了,但是在3							 数据库执行了flushall清空了全部
(empty array)

Redis是单线程的!

Redis是基于内存操作的,CPU不是Redis的瓶颈,Redis的瓶颈是根据机器的内存和网络的带宽,既然可以使用单线程来做,就使用了单线程!
Redis是C语言写的,官方提供的是100000+的QPS,完全不比同样是使用KV的Memecache差

Redis单线程怎么还这么快?

误区1.高性能的服务器一定是多线程的么?

误区2.多线程(CPU上下文切换)一定比单线程效率高么?

核心 :

redis是将所有的数据全部放在内存中的,所以说使用单线程效率最高(如果是多线程,需要上下文切换),对于内存系统来说,没有上下文切换就是效率最高的,多次读写在一个CPU上,在内存系统看来,单线程的Redis就是最佳方案

五大数据类型

官网文档

Redis是一种开放源代码(BSD许可)的内存中数据结构存储,用作数据库,缓存和消息代理。它支持数据结构,例如字符串,哈希,列表,集合,带范围查询的排序集合,位图,超日志,带有半径查询和流的地理空间索引。Redis具有内置的复制,Lua脚本,LRU驱逐,事务和不同级别的磁盘持久性,并通过Redis Sentine(哨兵模式)l和Redis Cluster自动分区提供高可用性。

Redis-Key

什么是Redis-Key

判断键值是否存在

127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set name wanghua
OK
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> key *
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> exists name		#存在这个键值么
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> move name 1		#移除这个	1代表当前库
(integer) 1
127.0.0.1:6379> keys *
1) "age"

设置key的过期时间(单位是S)

我们可以联想到我们的单点登录

127.0.0.1:6379> set name wang
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> get name
"wang"
127.0.0.1:6379> expire name 10  #设置我们这个键值对的过期时间
(integer) 1
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name		#查看当前key的剩余时间
(integer) 3
127.0.0.1:6379> ttl name
(integer) 2
127.0.0.1:6379> ttl name
(integer) 0
127.0.0.1:6379> get name		#已经没了
(nil)

查看key的类型(type)

127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> set name wang
OK
127.0.0.1:6379> keys *
1) "name"
2) "age"
127.0.0.1:6379> type name
string
127.0.0.1:6379> type age
string

String(字符串)

127.0.0.1:6379> set key1 v1		#设置值
OK
127.0.0.1:6379> get key1
"v1"
127.0.0.1:6379> keys *			#获得所有key
1) "key1"
127.0.0.1:6379> exists key1			#是否存在
(integer) 1
127.0.0.1:6379> APPEND key1 "hello"		#像一个key中追加字符串
(integer) 7
127.0.0.1:6379> get key1			#追加成功
"v1hello"
127.0.0.1:6379> STRLEN key1			#获取字符串长度
(integer) 7
127.0.0.1:6379> APPEND key1 "wanghuahua"
(integer) 17
127.0.0.1:6379> STRLEN key1
(integer) 17
127.0.0.1:6379> get key1
"v1hellowanghuahua"
127.0.0.1:6379> keys *
1) "key1"
#给一个不存在的key追加值会怎么样呢?
127.0.0.1:6379> APPEND name "wangtaotao"	
(integer) 10		#返回长度
#实验发现给一个不存在的key追加值会创建出来一个key
127.0.0.1:6379> keys *	
1) "name"
2) "key1"
127.0.0.1:6379> get name
"wangtaotao"
127.0.0.1:6379> 
#######################################################
#Redis中自增自减操作(我们的浏览量怎么做)
127.0.0.1:6379> set views 0
OK
127.0.0.1:6379> get views
"0"
127.0.0.1:6379> incr views		#自增1
(integer) 1
127.0.0.1:6379> incr views
(integer) 2
127.0.0.1:6379> get views
"2"
127.0.0.1:6379> decr views		#自减1
(integer) 1
127.0.0.1:6379> get views
"1"
####怎么设置步长呢?
127.0.0.1:6379> incrby views 10		#设置增长量
(integer) 11
127.0.0.1:6379> incrby views 10
(integer) 21
127.0.0.1:6379> get views
"21"
127.0.0.1:6379> decrby views 10		#设置自减量
(integer) 11
127.0.0.1:6379> get views
"11"	
#######################################################

字符串范围

#######################################################
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> set key1 "hello,wangtaotao"
OK
127.0.0.1:6379> get key1
"hello,wangtaotao"
127.0.0.1:6379> GETRANGE key1 0 3	#截取字符串[0,3]的内容
"hell"
127.0.0.1:6379> GETRANGE key1 0 -1	#相当于获取全部了setget
"hello,wangtaotao"
####替换
127.0.0.1:6379> keys *
1) "key1"
2) "key2"
127.0.0.1:6379> get key2
"abcdefg"
127.0.0.1:6379> SETRANGE key2 1 xx	#指定我们的下标1替换为
(integer) 7
127.0.0.1:6379> get key2
"axxdefg"
#######################################################
#setex (set with expire) #设置过期时间
#setnx (set if not expire) #不存在在设置(在分布式锁中会常常使用)
127.0.0.1:6379> clear
127.0.0.1:6379> setex key3 30 "hello"	#设置了一个key3有过期时											间,30s过期
OK
127.0.0.1:6379> ttl key3			#查看该key过期时间
(integer) 25
127.0.0.1:6379> ttl key3
(integer) 22
127.0.0.1:6379> get key3
"hello"
127.0.0.1:6379> setnx myvalue "redis"	#如果myvalue不存在,则											myvalue创建	
(integer) 1
127.0.0.1:6379> get key3
(nil)
127.0.0.1:6379> setnx myvalue "MongoDB"	#如果myvalue存在,则创												建失败	
(integer) 0				#返回0  说明我们没有修改成功
127.0.0.1:6379> get myvalue
"redis"

批量获取/设置

#######################################################
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3	#同时设置多个值
OK
127.0.0.1:6379> keys *
1) "k2"
2) "k3"
3) "k1"
127.0.0.1:6379> mget k1 k2 k3		#同时获取多个值
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4	#存在不创建,不存在创建?
(integer) 0		#返回0==>原子性操作,要么全成功,要么全失败
127.0.0.1:6379> get k4
(nil)
#######################################################

对象

#######################################################
#设置user对象
#这里的key的设计是:
	user:{id}:{filed}
127.0.0.1:6379> mset user:1:name zhangsan user:1:age 2
OK
127.0.0.1:6379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
#######################################################

组合命令

############################################################
#先get在set  getset
#如果不存在则返回null,再去赋值
#存在的话,先返回原来的值,再去赋成新的值
127.0.0.1:6379> getset db redis
(nil)
127.0.0.1:6379> get db
"redis"
127.0.0.1:6379> getset db MongoDB
"redis"
127.0.0.1:6379> get db
"MongoDB"
############################################################

String的类似使用场景:

  • 计数器
  • 统计浏览量
  • 粉丝数
  • 对象缓存存储

List

基本数据类型:列表

在Redis里面,List可以当做栈、队列、阻塞队列等等

所有的List命令都是以L开头

添加数据

############################################################
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> LPUSH list one		#将一个或多个插入列表头部
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list three
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
127.0.0.1:6379> LRANGE list 0 1			#后面的先拿出来
1) "three"
2) "two"
#从右边插入,插到了最后边的位置
127.0.0.1:6379> RPUSH list right
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
############################################################

移出数据POP

############################################################
LPOP   RPOP
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
######移出list第一个元素
127.0.0.1:6379> LPOP list 
"three"
#####移出list最后一个元素
127.0.0.1:6379> RPOP list
"right"
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
############################################################
LINDEX
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
127.0.0.1:6379> LINDEX list 1	#通过下标获得list中的某一个值
"one"
127.0.0.1:6379> LINDEX list 0
"two"
############################################################

其他操作

############################################################
#######获取list长度
127.0.0.1:6379> LPUSH list one
(integer) 1
127.0.0.1:6379> LPUSH list two
(integer) 2
127.0.0.1:6379> LPUSH list threre
(integer) 3
127.0.0.1:6379> LLEN list
(integer) 3
#####移除指定的值
#取关   踢出粉丝
127.0.0.1:6379> LPUSH list threre
(integer) 4
127.0.0.1:6379> LREM list 1 one #移出多少个指定的数据 精确匹配
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "threre"
2) "threre"
3) "two"
127.0.0.1:6379> LREM list 1 threre		#我们先移出一个
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1
1) "threre"
2) "two"
127.0.0.1:6379> LPUSH list threre
(integer) 3
127.0.0.1:6379> LRANGE list 0 -1
1) "threre"
2) "threre"
3) "two"
127.0.0.1:6379> LREM list 2 threre		#添加后一次性移出两个
(integer) 2
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
############################################################
########只获取/保留一部分
##Java中有trim去空格   修剪list:截断
127.0.0.1:6379> RPUSH mylist hello
(integer) 1
127.0.0.1:6379> RPUSH mylist hello1
(integer) 2
127.0.0.1:6379> RPUSH mylist hello2
(integer) 3
127.0.0.1:6379> RPUSH mylist hello3
(integer) 4
###通过下标截取指定的长度   list被修改了原地操作,只剩下了截取的元素
127.0.0.1:6379> LTRIM mylist 1 2
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello1"
2) "hello2"
############################################################
##			rpoplpush    移除列表最后一个元素并添加到新的列表
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "hello1"
(integer) 2
127.0.0.1:6379> RPUSH mylist "hello2"
(integer) 3
#移除列表最后一个元素并添加到目标的列表  目标列表不存在则自动创建
127.0.0.1:6379> RPOPLPUSH mylist myotherlist	
"hello2"
127.0.0.1:6379> LRANGE mylist 0 -1  #查看原来列表
1) "hello"
2) "hello1"
127.0.0.1:6379> LRANGE myotherlist 0 -1	#查看目标列表
1) "hello2"
############################################################
##			lset将列表指定下标的值替换成另一个值,相当于更新
##			如果不存在该列表或下标则会报错,存在才会修改
127.0.0.1:6379> exists list
(integer) 0
127.0.0.1:6379> lset list 0 item	#列表吧不存在能set值么
(error) ERR no such key				#报错不能
127.0.0.1:6379> LPUSH list value1
(integer) 1
127.0.0.1:6379> LRANGE list 0 -1	#我们创建了这个列表
1) "value1"
127.0.0.1:6379> lset list 0 item	#我们现在有值能这样set么
OK
127.0.0.1:6379> LRANGE list 0 -1	#可以set,相当于修改
1) "item"
127.0.0.1:6379> lset list 1 other	#列表中不存在的下标能set么
(error) ERR index out of range		#不能够set
############################################################
##		linsert将某个具体的值插入的列表指定元素前面或者后面
127.0.0.1:6379> RPUSH mylist "hello"
(integer) 1
127.0.0.1:6379> RPUSH mylist "world"
(integer) 2
127.0.0.1:6379> LINSERT mylist before "world" "other"	#在													其前面插入
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "other"
3) "world"
127.0.0.1:6379> LINSERT mylist after "world" "hhh"	#在													其后面插入
(integer) 4
127.0.0.1:6379> LRANGE mylist 0 -1
1) "hello"
2) "other"
3) "world"
4) "hhh"
############################################################

小结

实际上是一个链表,有before Node after,left,right 都可以插入

  • 如果key不存在,创建新链表
  • 如果key存在,新增内容
  • 如果移除了所有的值,空链表也代表不存在
  • 在两边插入或者改动,效率最高!!!中间元素,相对效率低一点

消息排队!!:LPUSH RPOP 左边进,右边出 队列

​ LPUSH LPOP 左边进,左边出 栈

Set(集合类型)

**特点:**set中的值是不能重复的

​ set中的值是无序的

set集合操作基本上以S开头

添加取出

############################################################
## 			sadd添加元素
##			smembers 查看set集合
##	Java中有contans  SISMEMBER查看set中是否包含指定值
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "taotao"
(integer) 1
127.0.0.1:6379> sadd myset "love taotao"
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "love taotao"
2) "hello"
3) "taotao"
#判断有没有指定的元素
127.0.0.1:6379> SISMEMBER myset hello	#不加""也可以
(integer) 1
127.0.0.1:6379> SISMEMBER myset world
(integer) 0
############################################################
##		SCARD获取set集合中元素的个数
127.0.0.1:6379> SCARD myset
(integer) 3
127.0.0.1:6379> sadd myset "taotao22222"
(integer) 1
127.0.0.1:6379> SCARD myset
(integer) 4
####		SREM移除set中的指定元素
127.0.0.1:6379> SREM myset hello
(integer) 1
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> SMEMBERS myset
1) "taotao22222"
2) "love taotao"
3) "taotao"
####		set无序不重复集合抽取随机
####		SRANDMEMBER随机抽取指定个数元素
127.0.0.1:6379> SMEMBERS myset
1) "taotao22222"
2) "love taotao"
3) "taotao"
127.0.0.1:6379> SRANDMEMBER myset
"love taotao"
127.0.0.1:6379> SRANDMEMBER myset
"taotao22222"
127.0.0.1:6379> SRANDMEMBER myset 2
1) "taotao22222"
2) "taotao"
############################################################
#			SPOP随机删除set中的元素
127.0.0.1:6379> SPOP myset
"taotao22222"
127.0.0.1:6379> SMEMBERS myset
1) "love taotao"
2) "taotao"
127.0.0.1:6379> SPOP myset
"taotao"
127.0.0.1:6379> SMEMBERS myset
1) "love taotao"
############################################################
##			SMOVE	将一个指定的值移动到另外一个set中
127.0.0.1:6379> sadd myset "hello"
(integer) 1
127.0.0.1:6379> sadd myset "world"
(integer) 1
127.0.0.1:6379> sadd myset "taotao"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> keys *
1) "myset2"
2) "myset"
#将"taotao"这个元素从myset移动到myset2中
127.0.0.1:6379> SMOVE myset myset2 "taotao"	
(integer) 1
127.0.0.1:6379> SMEMBERS myset
1) "hello"
2) "world"
127.0.0.1:6379> SMEMBERS myset2
1) "set2"
2) "taotao"
############################################################
##			微博、B站   共同关注!!(并集)
#数字集合类			
#		--差集	SDIFF返回前者不同于后者的元素
#		--交集	SINTER返回两者相同的元素		共同好友的实现
#		--并集	SUNION返回两者合在一起的元素
127.0.0.1:6379> sadd key1 a
(integer) 1
127.0.0.1:6379> sadd key1 b
(integer) 1
127.0.0.1:6379> sadd key1 c
(integer) 1
127.0.0.1:6379> sadd key2 c
(integer) 1
127.0.0.1:6379> sadd key2 d
(integer) 1
127.0.0.1:6379> sadd key2 e
(integer) 1
127.0.0.1:6379> SDIFF key1 key2
1) "b"
2) "a"
127.0.0.1:6379> SINTER key1 key2
1) "c"
127.0.0.1:6379> SUNION key1 key2
1) "d"
2) "a"
3) "c"
4) "b"
5) "e"
############################################################

微博

​ A用户将所有关注的人放在一个集合中!将他的粉丝也放到一个集合中

​ B用户将所有关注的人放在一个集合中!将他的粉丝也放到一个集合中

共同专注,爱好,粉丝A,B两个集合做SINTER交集计算就出来了

二度好友(六度分割理论)

Hash(哈希)

Map集合,key-map====key-<key,value>

本质上和String没有太大区别,还是简单的key-value

set myhash field taotao

hash操作基本以h开头

存取值

############################################################
##	hset单个赋值
##	hget单个取出
##	hmset多个赋值,存在的覆盖掉,不存在创建
##	hmget取出多个hash值
##	HGETALL	取出全部hash值
				#            key   value
127.0.0.1:6379> hset myhash field1 taotao
(integer) 1
127.0.0.1:6379> hget myhash field1
"taotao"
####我们的field1存在,理论上是要被覆盖的
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
127.0.0.1:6379> hmget myhash field1 field2
1) "hello"
2) "world"
127.0.0.1:6379> HGETALL myhash
1) "field1"
2) "hello"
3) "field2"
4) "world"
############################################################
###			hdel删除指定的key字段,对应的value值也就消失了
127.0.0.1:6379> hdel myhash field1
(integer) 1
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "world"
############################################################
##  	hlen获取hash表的字段数量
127.0.0.1:6379> hmset myhash field1 hello field2 world
OK
127.0.0.1:6379> HGETALL myhash
1) "field2"
2) "world"
3) "field1"
4) "hello"
127.0.0.1:6379> HLEN myhash
(integer) 2
############################################################
###		HEXISTS判断hash中指定字段存不存在
127.0.0.1:6379> HEXISTS myhash field1
(integer) 1
127.0.0.1:6379> HEXISTS myhash field3
(integer) 0
############################################################
###		HKEYS	只获得我们的field字段 
###		HVALS	只获得我们的value
127.0.0.1:6379> HKEYS myhash
1) "field2"
2) "field1"
127.0.0.1:6379> HVALS myhash
1) "world"
2) "hello"
############################################################
##  HINCRBY		自增 	-1相当于自减
##	hsetnx		不存在则设置,如果存在则不设置
127.0.0.1:6379> hset myhash field3 5
(integer) 1
127.0.0.1:6379> HINCRBY myhash field3 1
(integer) 6
127.0.0.1:6379> HINCRBY myhash field3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash field4 hello
(integer) 1
127.0.0.1:6379> hsetnx myhash field4 world
(integer) 0
############################################################

应用

hash存储变更的数据:user name age,hash更适合存储用户,String更加适合字符串存储

127.0.0.1:6379> hset user:1 name wangtaotao
(integer) 1
127.0.0.1:6379> hget user:1 name
"wangtaotao"
127.0.0.1:6379> hset user:1 age 18
(integer) 1
127.0.0.1:6379> hget user:1 age
"18"
127.0.0.1:6379> HGETALL user:1
1) "name"
2) "wangtaotao"
3) "age"
4) "18"

Zset(有序集合)

在set的基础上,增加了一个值

set:set k1 v1

zset:zset k1 score1 v1

方法

############################################################
###	 zadd  增加一个zset元素  可以添加多个值	
###  ZRANGE  查看zset指定范围元素
127.0.0.1:6379> keys *
(empty array)
127.0.0.1:6379> zadd myset 1 one
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 there
(integer) 2
127.0.0.1:6379> ZRANGE myset 0 -1
1) "one"
2) "two"
3) "there"

############################################################
##			添加三个用户的薪水
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 5000 zahngsan
(integer) 1
127.0.0.1:6379> zadd salary 100000 taotao
(integer) 1
###			从小到大
####	ZRANGEBYSCORE	排序  包括-无穷到正无穷
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "xiaohong"
2) "zahngsan"
3) "taotao"
####	ZRANGEBYSCORE	从大到小排序
127.0.0.1:6379> ZREVRANGE salary 0 -1
1) "taotao"
2) "zahngsan"

####  ZRANGEBYSCORE	排序 包括-无穷到正无穷 带上sources数据
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores
1) "xiaohong"
2) "2500"
3) "zahngsan"
4) "5000"
5) "taotao"
6) "100000"
####  ZRANGEBYSCORE  指定限制范围查询出来  带sources数据
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores
1) "xiaohong"
2) "2500"
############################################################
###        ZRANGE    移除元素
###			ZCARD 	  获取有序集合中的个数
127.0.0.1:6379> ZRANGE salary 0 -1
1) "xiaohong"
2) "zahngsan"
3) "taotao"
127.0.0.1:6379> ZREM salary xiaohong
(integer) 1
127.0.0.1:6379> ZRANGE salary 0 -1
1) "zahngsan"
2) "taotao"
127.0.0.1:6379> ZCARD salary
(integer) 2
############################################################
####	ZCOUNT	获取指定区间Zset的成员数量

flushdb
127.0.0.1:6379> zadd myset 1 hello 
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 taotao
(integer) 2
127.0.0.1:6379> ZCOUNT myset 1 3
(integer) 3
127.0.0.1:6379> ZCOUNT myset 1 2
(integer) 2
############################################################

案例思路:set的排序版

存储班级成绩,员工工资表!

带权重执行 普通消息!重要消息!加权操作!!1

排行榜应用场景 取TOP10功能


版权声明:本文为qq_22155255原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。