Redis01

1、NoSQL

  NoSQL 是 Not Only SQL 的缩写,意即"不仅仅是 SQL"的意思,泛指非关系型的数据库。强调 Key-Value Stores 和文档数据库的优点。

NoSQL 产品是传统关系型数据库的功能阉割版本,通过减少用不到或很少用的功能,来大幅度提高产品性能

  • 不遵循 SQL 标准。 (添加 insert 修改 update )
  • 不支持 ACID。
  • 远超于 SQL 的性能。

2、NoSQL 起源

过去,关系型数据库(SQL Server、Oracle、MySQL)是数据持久化的唯一选择,但随着发展,关系型数据库存在以下问题。

问题 1:不能满足高性能查询需求

我们使用:Java、.Net 等语言编写程序,是面向对象的。但用数据库都是关系型数据库。存储结构是面向对象的,但是数据库却是关系的,所以在每次存储或者查询数据时,我们都需要做转换。类似 Hibernate、Mybatis 这样的 ORM 框架确实可以简化这个过程,但是在对高性能查询需求时,这些 ORM 框架就捉襟见肘了。

问题 2:应用程序规模的变大

网络应用程序的规模变大,需要储存更多的数据、服务更多的用户以及需求更多的计算能力。为了应对这种情形,我们需要不停的扩展。

扩展分为两类:一种是纵向扩展,即购买更好的机器,更多的磁盘、更多的内存等等。另一种是横向扩展,即购买更多的机器组成集群。在巨大的规模下,纵向扩展发挥的作用并不是很大。首先单机器性能提升需要巨额的开销并且有着性能的上限,在 Google 和 Facebook 这种规模下,永远不可能使用一台机器支撑所有的负载。鉴于这种情况,我们需要新的数据库,因为关系数据库并不能很好的运行在集群上

mysql 表 里面50000

mysql mysql mysql

3、NoSQL 的使用

  • 对数据高并发的读写
  • 海量数据的读写
  • 对数据高可扩展性的
  • 秒杀活动

NoSQL 不适用场景

  • 需要事务支持
  • 基于 sql 的结构化查询存储,处理复杂的关系,需要及时查询。

用不着 sql 的和用了 sql 也不行的情况,考虑用 NoSql

4、【熟悉】常见的 NoSQL 及区别

1,常见的 NoSQL 数据库

name:uiui,age:uiou89,hjdhj:9090

varchar1 varchar2

2,区别

1,Memcached

  • 很早出现的 NoSql 数据库
  • 数据都在内存中,一般不持久化
  • 支持简单的 key-value 模式,支持类型单一
  • 一般是作为缓存数据库辅助持久化的数据库(MySQL)

2,Redis

  • 几乎覆盖了 Memcached 的绝大部分功能
  • 数据都在内存中,支持持久化,主要用作备份恢复
  • 除了支持简单的 key-value 模式,还支持多种数据结构的存储,比如 list、set、hash、zset 等。
  • 一般是作为缓存数据库辅助持久化的数据库

3,MongoDB

  • 高性能、开源、模式自由(schema free)的文档型数据库
  • 数据都在内存中, 如果内存不足,把不常用的数据保存到硬盘
  • 虽然是 key-value 模式,但是对 value(尤其是 json)提供了丰富的查询功能
  • 支持二进制数据及大型对象
  • 可以根据数据的特点替代 RDBMS,成为独立的数据库。或者配合 RDBMS,存储特定的数

5、【熟悉】Redis 简介

1,Redis 简介

Ø Redis 是一个开源的 key-value 存储系统。

Ø 和 Memcached 类似,它支持存储的 value 类型相对更多,包括 string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和 hash(哈希类型)。

Ø 这些数据类型都支持 push/pop、add/remove 及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。

Ø 在此基础上,Redis 支持各种不同方式的排序。

Ø 与 memcached 一样,为了保证效率,数据都是缓存在内存中。

Ø 区别的是 Redis 会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件。

Ø 并且在此基础上实现了 master-slave(主从)同步。

2,端口 6379

先介绍下 redis 的作者 Salvatore Sanfilippo(Antirez),意大利人,就是下图这位。

Antirez 现在已经 40 多岁了,依然奋斗在代码一线,为开源社区做贡献。Antirez 出生在非英语系国家,所以英语一直是他的短板。他曾经写过一篇博文,《英语伤痛 15 年》,以自己的实际经历鼓励非英语系国家的程序员突破英语障碍。或说回来,在他的另一篇博文《Redis as an LRU cache》中,写到了为什么选用 6379 端口:

用一张图片来翻译一下,6379 就是这个意思:

而 Merz 全名 Alessia Merz,是意大利的一位广告女郎,就是下面这位:

在 Antirez 看来,这个名字是愚蠢的代名词,所以就选了这个 6379

这个还真不知道有没有其它原因(自行脑补)

3,Redis 数据结构的多样性

4,Redis 的应用场景

1、数据缓存(提高访问性能)

查询概率》》 增删改的概率

将一些数据在短时间之内不会发生变化,而且它们还要被频繁访问,为了提高用户的请求速度和降低网站的负载,降低数据库的读写次数,就把这些数据放到缓存中。

2、会话缓存

session cache,主要适用于 session 共享 (string 类型)

3、排行榜/计数器

(NGINX+lua+redis 计数器进行 IP 自动封禁)(zset)

4、消息队列

(构建实时消息系统,聊天,群聊) (list)

5· 粉丝 (set)

  1. 用于存储对象 (hash)

redis的基本数据类型  包括什么 每种数据类型的使用场景

面试题

string :会话信息

list:消息

set:粉丝 共同好友

zset :排行榜

hash: 存储对象

6、【掌握】Redis 的安装及启动停止

  1. 下载 redis

2.将文件上传到 linux

3.开始安装

a.安装的时候先安装 redis 所依赖的环境

yum -y install gcc-c++

2、开始解压 redis

c. 编译,进入 redis 解压目录,执行 make 命令编译

d.安装

make PREFIX=/usr/yyl/soft/redis install

(如果命令执行不成功,换为 make install PREFIX=/usr/yyl/soft/redis )

e.启动 redis

进入安装目录(/usr/yyl/soft/redis)的 bin 下面,并启动 redis

出现上图

即为安装成功

redis 启动成功,但是这种启动方式需要一直打开窗口,不能进行其他操作,不太方便。

按 ctrl + c 可以关闭窗口

修改配置文件

1. 拷贝配置文件到安装目录 bin 下

cp /usr/yyl/redis/redis-5.0.14/redis.conf  /usr/yyl/soft/redis/bin/redis.conf

2. 修改 redis.conf 文件

redis.conf (136)文件将里面的 daemonize no 改成 yes #设置后台启动

no 改为 yes #如果不想设置后台启动就不改

3. requirepass yyl #配置密码 如果需要 客户端连接的话需要设置密码 如果不需要连接就不要设置

4. # bind 127.0.0.1 #注释掉绑定本机,才可以远程连接访问

5.启动 redis

./redis-server ./redis.conf

连接redis

  • 方式1:使用密码进行连接

  • 方式2:完整的命令  

redis-cli -h host -p port -a password 远程连接 redis 服务

当redis在本机并且端口是6379的时候-h 和-p可以省略不写

关闭 redis:

  • 方式1:./redis-cli shutdown

  • 方式2:./redis-cli -p 6379 -a yyl -h 127.0.0.1 shutdown

配置服务启动(使用 systemctl 的方法)

服务启动的时候 daemonize 改为 no

在/lib/systemd/system 目录下创建一个脚本文件 redis.service,里面的内容如下:

service 启动的时候

[Unit]
Description=Redis
After=network.target
[Service]
ExecStart=/usr/lhf/soft/redis/bin/redis-server /usr/lhf/soft/redis/bin/redis.conf
ExecStop=/usr/lhf/soft/redis/bin/redis-cli -h 192.168.182.34 -p 6379 -a lhf shutdown
[Install]
WantedBy=multi-user.target

刚刚配置的服务需要让 systemctl 能识别,就必须刷新配置

systemctl daemon-reload 刷新配置

systemctl enable redis 开机自启

systemctl status redis redis 状态

systemctl start redis 开启 redis

systemctl stop redis 关闭 redis

systemctl disable redis 禁止开机自启

ping 测试连接

quit 关闭连接(connection)

auth 简单密码认证

测试100个并发连接,10000个请求

redis-benchmark -h localhost -p 6379 -c 100 -n 10000

 

 

查询数据库一共有多少:config get databases

选中某一个数据库

设值,取值

获取所有的 key

7、Key

默认 16 个数据库,类似数组下标从 0 开始,初始默认使用 0 号库

dbsize 查看当前数据库的 key 的数量

flushdb 清空当前库

flushall 通杀全部库

keys * 获取当前库中的所有key

select 0 选择第一个库

move key 1 将当前的数据库 key 移动到某个数据库,目标库有,则不能移动

randomkey 从当前数据库中随机返回

type key 类型

del key 删除 key

exists key 判断是否存在 key

expire key 10 为给定的key设置过期时间 单位是秒

pexpire key 1000 给定的key设置过期时间 单位:毫秒

persist key 删除key的过期时间

ttl key 查看还有多少秒过期,-1 表示永不过期,-2 表示已过期

8、常见的数据类型

string类型

1、简介

String是Redis最基本的类型,你可以理解成与Memcached一模一样的类型,一个key对应一个value。

String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象。

String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M

2、常用命令

set   <key><value>添加键值对 
    *NX:当数据库中key不存在时,可以将key-value添加数据库
    *XX:当数据库中key存在时,可以将key-value添加数据库,与NX参数互斥
    *EX:key的超时秒数
    *PX:key的超时毫秒数
 set name cxx 

 append <key><value> #将给定的<value> 追加到原值的末尾

get   <key>查询对应键值   
 get name

setex <key><过期时间><value>#设置键值的同时,设置过期时间,单位秒。

setex name 30 lhf

getset <key><value> 以新换旧,设置了新值同时获得旧值。
eg:getset name new_cxx  #给 name 的 value 设置新值,返回旧值

mset key1 key2 批量设置key   
msetnx <key1><value1><key2><value2>  ..... 
同时设置一个或多个 key-value 对,当且 仅当所有给定 key 都不存在 如果有一个存在就会不成功。
  注意:有一个失败则都失败 

mget key1 key2 批量获取

setnx key value 不存在就插入(not exists)

setrange <key><起始位置index><value> #从 index 开始替换 value

getrange <key><起始位置><结束位置>

getrange name 0 -1 #字符串分段 0 -1 是全部 0 -2 ==n-1

incr  <key> 

将 key 中储存的数字值增1
只能对数字值操作,如果为空,新增值为1
incr age 递增

decr  <key>

将 key 中储存的数字值减1
只能对数字值操作,如果为空,新增值为-1
decr age #递减

incrby / decrby <key><步长>将 key 中储存的数字值增减。自定义步长。

incrby age 10 递增

decrby age 10 递减

原子性操作
所谓 原子操作是指不会被线程调度机制打断的操作;
这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
(1)在单线程中, 能够在单条指令中完成的操作都可以认为是"原子操作",因为中断只能发生于指令之间。
(2)在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。
Redis单命令的原子性主要得益于Redis的单线程。

组合命令

strlen <key> #获得值的长度

3、数据结构

String的数据结构为简单动态字符串(Simple Dynamic String,缩写SDS)。是可以修改的字符串,内部结构实现上类似于Java的ArrayList,采用预分配冗余空间的方式来减少内存的频繁分配.

如图中所示,内部为当前字符串实际分配的空间capacity一般要高于实际字符串长度len。当字符串长度小于1M时,扩容都是加倍现有的空间(2倍),如果超过1M,扩容时一次只会多扩1M的空间。需要注意的是字符串最大长度为512M。

list类型

1、简介

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差。

v3 v2 v1 v4 v5

2、常用命令

lpush/rpush <key><value1><value2><value3> .... 从左边/右边插入一个或多个值。

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   #获取list中的值!
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"

lpop/rpop <key> 从左边/右边吐出一个值。值在键在,值光键亡。

lpop
rpop

127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"
3) "one"
4) "right"
127.0.0.1:6379> lpop list #移除list的第一个元素
"three"
127.0.0.1:6379> rpop list
"right"
127.0.0.1:6379> lrange list 0 -1 #移除list的最后一个元素
1) "two"
2) "one"

rpoplpush <key1><key2> 从<key1>列表右边吐出一个值,插到<key2>列表左边。

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"

lrange <key><start><stop>

按照索引下标获得元素(从左到右)

lrange mylist 0 -1 0左边第一个,-1右边第一个,(0 -1表示获取有)

127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "hello1"

lindex <key><index>按照索引下标获得元素(从左到右)

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"

llen <key>获得列表长度

llen

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> lpush list four
(integer) 4
127.0.0.1:6379> llen list #返回列表的长度
(integer) 4
127.0.0.1:6379> 

linsert <key> <before/after> <value><newvalue> 在<value>的后面插入<newvalue>插入值

linsert # 将某个具体的value插入到列中某个元素的前面或者后面!

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" "every"
(integer) 3
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "every"
3) "world"
127.0.0.1:6379> linsert mylist after "world" "new"
(integer) 4
127.0.0.1:6379> lrange mylist 0 -1
1) "hello"
2) "every"
3) "world"
4) "new"

lrem <key><n><value> 从左边删除n个对应的value值(从左到右)

lrem k3 3 "test" #从左边开始删除k3里面的3个“test”

lrem

127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "four"
3) "three"
4) "two"
5) "one"
127.0.0.1:6379> lrem list 1 one #移除list集合中指定个数的value,精确匹配
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "four"
3) "three"
4) "two"
127.0.0.1:6379> lrem list 1 four
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "four"
2) "three"
3) "two"
127.0.0.1:6379> lpush list four
(integer) 4
127.0.0.1:6379> lrem list 2 four
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "three"
2) "two"

trim

lset<key><index><value>将列表key下标为index的值替换成value

lset  将列表中指定下标的值替换为另外一个值,更新操作

127.0.0.1:6379> exists list # 判断这个列表是否存在
(integer) 0
127.0.0.1:6379> lset list 0 item # 如果不存在列表我们去更新就会报错
(error) ERR no such key
127.0.0.1:6379> lpush list value1
(integer) 1
127.0.0.1:6379> lrange list 0 0
1) "value1"
127.0.0.1:6379> lset list 0 item # 如果存在,更新当前下标的值
OK
127.0.0.1:6379> lrange list 0 0
1) "item"
127.0.0.1:6379> lset list 1 other # 如果不存在,则会报错!
(error) ERR index out of range

3、数据结构

List的数据结构为快速链表quickList。

首先在列表元素较少的情况下会使用一块连续的内存存储,这个结构是ziplist,也即是压缩列表。

(它将所有的元素紧挨着一起存储,分配的是一块连续的内存)。

当数据量比较多的时候才会改成quicklist。

因为普通的链表需要的附加指针空间太大,会比较浪费空间。比如这个列表里存的只是int类型的数据,结构上还需要两个额外的指针prev和next。

Redis将链表和ziplist结合起来组成了quicklist。也就是将多个ziplist使用双向指针串起来使用。这样既满足了快速的插入删除性能,又不会出现太大的空间冗余。

小结:

  • 他实际上是一个链表,before Node after ,left,right 都可以插入值
  • 如果key不存在,创建新的链表。
  • 如果kev存在,新增内容
  • 如果移除了所有值,空链表,也代表不存在!
  • 在两边插入或者改动值,效率最高!中间元素,相对来说效率会低一点~
  •   消息排队!消息队列  (Lpush Rpop), 栈(Lpush Lpop)!

set类型  无序不重复

1、简介

set对外提供的功能与list类似是一个列表的功能,特殊之处在于set是可以自动排重的,当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。

2、常用命令

sadd <key><value1><value2> .....

将一个或多个 member 元素加入到集合 key 中,已经存在的 member 元素将被忽略

smembers <key>取出该集合的所有值。

sismember <key><value>判断集合<key>是否为含有该<value>值,有1,没有0

sadd,smembers,sismember

127.0.0.1:6379> sadd myset "hello" # set集合中添加元素
(integer) 1
127.0.0.1:6379> sadd myset "lhf"
(integer) 1
127.0.0.1:6379> sadd myset "lovelhf"
(integer) 1
127.0.0.1:6379> smembers myset # 查看指定set的所有值
1) "hello"
2) "lhf"
3) "lovelhf"
127.0.0.1:6379> sismember myset hello # 判断某一个值是不是在set集合中! 1 为成功
(integer) 1
127.0.0.1:6379> sismember myset world # 判断某一个值是不是在set集合中! 0 为失败
(integer) 0

scard<key>返回该集合的元素个数。

scard #获取set集合中内容元素个数!

127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> sadd myset "lovelhf2"
(integer) 1
127.0.0.1:6379> scard myset
(integer) 4
127.0.0.1:6379> smembers myset
1) "hello"
2) "lhf"
3) "lovelhf2"
4) "lovelhf"
127.0.0.1:6379> 

srem <key><value1><value2> .... 删除集合中的某个元素。

srem 

127.0.0.1:6379> srem myset "hello" #移除set集合中的某一个元素
(integer) 1
127.0.0.1:6379> scard myset
(integer) 3
127.0.0.1:6379> smembers myset
1) "lhf"
2) "lovelhf2"
3) "lovelhf"

spop <key>随机从该集合中吐出一个值。

spop

127.0.0.1:6379> smembers myset
1) "lhf"
2) "lovelhf2"
3) "lovelhf"
127.0.0.1:6379> spop myset #随机删除一些set集合中的元素
"lovelhf2"
127.0.0.1:6379> spop myset
"lovelhf"
127.0.0.1:6379> smembers myset
1) "lhf"

srandmember <key><n> 随机从该集合中取出n个值。不会从集合中删除 。

srandmember

127.0.0.1:6379> smembers myset
1) "lhf"
2) "lovelhf2"
3) "lovelhf"
127.0.0.1:6379> srandmember myset #随机抽选出一个元素
"lhf"
127.0.0.1:6379> srandmember myset
"lovelhf2"
127.0.0.1:6379> srandmember myset 2 #随机抽选出指定个数的元素
1) "lhf"
2) "lovelhf2"
127.0.0.1:6379> srandmember myset 2
1) "lovelhf2"
2) "lovelhf"

smove k1 k2 k1中的存在的值

smove <source><destination>value 把集合中一个值从一个集合移动到另一个集合

smove

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 "lhf"
(integer) 1
127.0.0.1:6379> sadd myset2 "set2"
(integer) 1
127.0.0.1:6379> smove myset  myset2  lhf #将一个指定的值,移动到另外一个set集合中!
(integer) 1
127.0.0.1:6379> smembers myset
1) "hello"
2) "world"
127.0.0.1:6379> smembers myset2
1) "lhf"
2) "set2"

微博,B站,共同关注(并集)

数字集合类:

         -差集 sdiff

        -交集 sinter

        -并集 sunion

sinter <key1><key2> 返回两个集合的交集元素。

sunion <key1><key2> 返回两个集合的并集元素。

sdiff <key1><key2> 返回两个集合的差集元素(key1中的,不包含key2中的)

sidff 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) "a"
2) "b"
127.0.0.1:6379> sinter key1 key2 #交集 共同好友就可以这样实现
1) "c"
127.0.0.1:6379> sunion key1 key2 # 并集
1) "c"
2) "a"
3) "e"
4) "b"
5) "d"

 微博,A用户将所有关注的人放在一个set集合中!将它的粉丝也放在一个集合中!

共同关注,共同爱好,二度好友,推荐好友!(六度分隔理论)

3、 数据结构

Set数据结构是dict字典,字典是用哈希表实现的。

Java中HashSet的内部实现使用的是HashMap,只不过所有的value都指向同一个对象。Redis的set结构也是一样,它的内部也使用hash结构,所有的value都指向同一个内部值。

hash类型

1、简介

hash是一个string类型的field和value的映射表,hash特别适合用于存储对象。

类似Java里面的Map<String,Object>

用户ID为查找的key,存储的value用户对象包含姓名,年龄,生日等信息,如果用普通的key/value结构来存储

主要有以下2种存储方式:

通过第三种方式:( key(用户ID) + field(属性标签)) 就可以操作对应属性数据了,既不需要重复存储数据,也不会带来序列化和并发修改控制的问题

2、常用命令

hset <key><field><value>给<key>集合中的 <field>键赋值<value>

hget <key1><field> 从<key1>集合<field>取出 value

hmset <key1><field1><value1><field2><value2>... 批量设置hash的值

hset hget hmset hmget hgetall
127.0.0.1:6379> hset myhash fie1 lhf #set一个具体 key-vlaue
(integer) 1
127.0.0.1:6379> hget myhash fie1 #获取一个字段值
"lhf"
127.0.0.1:6379> hmset myhash fie1 hello fie2 world #set多个key-vlaue
OK
127.0.0.1:6379> hmget myhash fie1 fie2 #获取多个字段值
1) "hello"
2) "world"
127.0.0.1:6379> hgetall myhash #获取全部的数据
1) "fie1"
2) "hello"
3) "fie2"
4) "world"

  删除 hdel

127.0.0.1:6379> hgetall myhash
1) "fie1"
2) "hello"
3) "fie2"
4) "world"
127.0.0.1:6379> hdel myhash fie1 #删除hash指定阿key字段,对应的value值也就消失了
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "fie2"
2) "world"

hlen获取字段数

127.0.0.1:6379> hmset myhash fie1 hello fie2 world
OK
127.0.0.1:6379> hgetall myhash
1) "fie2"
2) "world"
3) "fie1"
4) "hello"
127.0.0.1:6379> hlen myhash  #获取hash表的字段数量
(integer) 2

hexists<key1><field>查看哈希表 key 中,给定域 field 是否存在。

127.0.0.1:6379> hexists myhash fie1 #判断hash中指定字段是否存在
(integer) 1
127.0.0.1:6379> hexists myhash fie3
(integer) 0

hkeys <key>列出该hash集合的所有field

127.0.0.1:6379> hkeys myhash
1) "fie2"
2) "fie1"

hvals <key>列出该hash集合的所有value

127.0.0.1:6379> hvals myhash
1) "world"
2) "hello"

hincrby <key><field><increment>为哈希表 key 中的域 field 的值加上增量 1 -1

hsetnx <key><field><value>将哈希表 key 中的域 field 的值设置为 value ,当且仅当域 field 不存在 .

hincrby  hsetnx 

127.0.0.1:6379> hset myhash fie3 5 #指定增量
(integer) 1
127.0.0.1:6379> hincrby myhash fie3 1
(integer) 6
127.0.0.1:6379> hincrby myhash fie3 -1
(integer) 5
127.0.0.1:6379> hsetnx myhash fie4 hello #如果不存在则可以设置
(integer) 1
127.0.0.1:6379> hsetnx myhash fie4 world #如果存在则不能设置
(integer) 0

 hash变更的数据 user name age 尤其是用户信息之类的,经常变动的信息! hash更适合于对象的存储,String更加适合字符串存储!

127.0.0.1:6379> hset user:1 name liuhongfei
(integer) 1
127.0.0.1:6379> hget user:1 name
"liuhongfei"

3、数据结构

Hash类型对应的数据结构是两种:ziplist(压缩列表),hashtable(哈希表)。当field-value长度较短且个数较少时,使用ziplist,否则使用hashtable。

zset类型(有序集合)

1、简介

Redis有序集合zset与普通集合set非常相似,是一个没有重复元素的字符串集合。

不同之处是有序集合的每个成员都关联了一个评分(score),这个评分(score)被用来按照从最低分到最高分的方式排序集合中的成员。集合的成员是唯一的,但是评分可以是重复了 。

因为元素是有序的, 所以你也可以很快的根据评分(score)或者次序(position)来获取一个范围的元素。

访问有序集合的中间元素也是非常快的,因此你能够使用有序集合作为一个没有重复成员的智能列表。

2、常用命令

zadd <key><score1><value1><score2><value2>…

将一个或多个 member 元素及其 score 值加入到有序集 key 当中。

127.0.0.1:6379> zadd myset 1 one #添加一个值
(integer) 1
127.0.0.1:6379> zadd myset 2 two 3 three #添加多个值
(integer) 2
127.0.0.1:6379> zrange myset 0 -1
1) "one"
2) "two"
3) "three"

zrange <key><start><stop> [WITHSCORES]

返回有序集 key 中,下标在<start><stop>之间的元素

带WITHSCORES,可以让分数一起和值返回到结果集。

zrangebyscore key min max [withscores] [limit offset count]

返回有序集 key 中,所有 score 值介于 min 和 max 之间(包括等于 min 或 max )的成员。有序集成员按 score 值递增(从小到大)次序排列。

zrevrangebyscore key max min [withscores] [limit offset count]

同上,改为从大到小排列。

127.0.0.1:6379> zadd salary 2500 xiaohong #添加三个用户
(integer) 1
127.0.0.1:6379> zadd salary 5000 zhangsan
(integer) 1
127.0.0.1:6379> zadd salary 500 liuhongfei
(integer) 1

ZRANGEBYSCORE key min max

127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf #显示全部的用户 从小到大排序
1) "liuhongfei"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf
1) "liuhongfei"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf +inf withscores #显示全部的用户 并且附带成绩
1) "liuhongfei"
2) "500"
3) "xiaohong"
4) "2500"
5) "zhangsan"
6) "5000"
127.0.0.1:6379> ZRANGEBYSCORE salary -inf 2500 withscores #显示工资小于2500员工的升序排列
1) "liuhongfei"
2) "500"
3) "xiaohong"
4) "2500"
127.0.0.1:6379> zrevrange salary 0 -1 #从大到小进行排序
1) "zhangsan"
2) "liuhongfei"

zincrby <key><increment><value> 为元素的score加上增量

zrem <key><value>删除该集合下,指定值的元素

127.0.0.1:6379> zrange salary 0 -1
1) "liuhongfei"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:6379> zrem salary xiaohong #移除有序集合中的指定元素
(integer) 1
127.0.0.1:6379> zrange salary 0 -1
1) "liuhongfei"
2) "zhangsan"

zcard

127.0.0.1:6379> zcard salary #获取有序集合中的个数
(integer) 2

zcount <key><min><max>统计该集合,分数区间内的元素个数

127.0.0.1:6379> zadd myset 1 "hello"
(integer) 1
127.0.0.1:6379> zadd myset 2 world 3 liuhongfei
(integer) 2
127.0.0.1:6379> zcount myset 1 3 #获取指定区间的成员数量
(integer) 3
127.0.0.1:6379> zcount myset 1 2
(integer) 2

zrank <key><value>返回该值在集合中的排名,从0开始。

SortedSet(zset)是Redis提供的一个非常特别的数据结构,一方面它等价于Java的数据结构Map<String, Double>,可以给每一个元素value赋予一个权重score,另一方面它又类似于TreeSet,内部的元素会按照权重score进行排序,可以得到每个元素的名次,还可以通过score的范围来获取元素的列表。

其与的一些API,通过我们的学习吗,你们剩下的如果工作中有需要,这个时候你可以去查查看官方文档!
案例思路:set 排序 存储班级成绩表,工资表排序!
普通消息,1,重要消息2,带权重进行判断!
排行榜应用实现,取TopN测试!

zset底层使用了两个数据结构

(1)hash,hash的作用就是关联元素value和权重score,保障元素value的唯一性,可以通过元素value找到相应的score值。

(2)跳跃表,跳跃表的目的在于给元素value排序,根据score的范围获取元素列表。

对比有序链表和跳跃表,从链表中查询出51

(1) 有序链表

要查找值为51的元素,需要从第一个元素开始依次查找、比较才能找到。共需要6次比较。

(2) 跳跃表

从第2层开始,1节点比51节点小,向后比较。

41节点比51节点小,继续向后比较,后面就是NULL了,所以从41节点向下到第1层

在第1层,41节点比51节点小,继续向后,61节点比51节点大,所以从61向下

在第0层,51节点为要查找的节点,节点被找到,共查找4次。

3、各数据的使用场景

类型

简介

特性

场景

String(字符串)

二进制安全

可以包含任何数据,比如jpg图片或者序列化的对象,一个键最大能存储512M

---

Hash(字典)

键值对集合,即编程语言中的Map类型

适合存储对象,并且可以像数据库中update一个属性一样只修改某一项属性值(Memcached中需要取出整个字符串反序列化成对象修改完再序列化存回去)

存储、读取、修改用户属性

List(列表)

链表(双向链表)

增删快,提供了操作某一段元素的API

1、最新消息排行等功能(比如朋友圈的时间线) 2、消息队列

Set(集合)

哈希表实现,元素不重复

1、添加、删除、查找的复杂度都是O(1) 2、为集合提供了求交集、并集、差集等操作

1、共同好友 2、利用唯一性,统计访问网站的所有独立ip 3、好友推荐时,根据tag求交集,大于某个阈值就可以推荐

Sorted Set(有序集合)

将Set中的元素增加一个权重参数score,元素按score有序排列

数据插入集合时,已经进行天然排序

1、排行榜 2、带权重的消息队列

补充:redis的发布订阅

什么 是发布和订阅

Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。

Redis 客户端可以订阅任意数量的频道。

Redis的发布和订阅

客户端订阅频道发布的消息

频道发布消息 订阅者就可以收到消息

发布订阅的代码实现

1、 打开一个客户端订阅channel1

SUBSCRIBE channel1

2、打开另一个客户端,给channel1发布消息hello

publish channel1 hello

返回的1是订阅者数量

3、打开第一个客户端可以看到发送的消息

1.成功安装redis

2.熟记redis的五种基本数据类型

以及这几种数据类型的使用场景

3. java操作redis ping  

jedis.jar  添加键值对

<!-- https://mvnrepository.com/artifact/redis.clients/jedis -->
<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>4.2.3</version>
</dependency>

 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值