资讯详情

redis使用详细教程

redis使用详细的教程

  • 一、Nosql概述
    • 1.数据库发展史
      • 1)单机mysql的年代
      • 2)Memcached(分布式高速缓存系统) mysql 垂直拆分(读写分离)
      • 3)分库分表 水平拆分 MySQL集群
      • 4)最近的年代
    • 2.为什么要用?nosql?
    • 3.什么是nosql?
    • 4.nosql特点是什么?
    • 5.nosql的四大分类
  • 二、redis入门
    • 1.什么是redis?
    • 2.redis能干什么?
    • 3.特性
    • 4.学习中需要用到的东西
    • 5.安装
    • 6.性能测试
    • 7.基础知识
      • 基本命令
      • Redis 是单线程的
  • 三、redis五大数据类型
    • 1.String 字符串
      • 1.1 判断是否存在追加,获得长度
      • 1.2 字符串类型为整数增减
      • 1.3 截取和替换
      • 1.4 设置时间
      • 1.5 多个值的set 和获取get以及对象存储
      • 1.6 先获取后设置
      • 应用场景
    • 2.List
    • 3.Set
    • 4.Hash
    • 5.Zset(有序集合)
  • 四、三种特殊数据类型
    • 1.Geospatal 地理位置
      • 1.1 geoadd 添加地理位置
      • 1.2 geopos 获取地理位置定位
      • 1.3 geodist 计算两个人之间的距离
      • 1.4 georadius 以经纬度为中心,在半径内找到元素
      • 1.5 georadiusbymember:以元素为中心,搜索半径内的元素
      • 1.6 geohash:以字符串表示返回的经纬度
    • 2.Hyperloglog 计数
    • 3.Bitmap 位存储
  • 五、事务
  • 六、Jedis连接工具和SpringBoot整合Redis
    • 1.Jedis连接工具
    • 2.SpringBoot整合Redis
  • 七、持久化
    • 1.RDB
      • 1.1 什么是RDB?
    • 2.AOF
  • 八、订阅发布
  • 九、主从复制
  • 十、哨兵模式
  • 十一、缓存穿透和雪崩

一、Nosql概述

1.数据库发展史

1)单机mysql的年代

在这里插入图片描述 在20世纪90年代,一个基本的网站通常没有太多的访问,单个数据库就足够了 当时静态网站用的比较多。 那么,整个应用系统的瓶颈是什么呢?

  1. 数据量太大,机器无法安装(数据库保存数据是一个持久的操作,需要保存在硬盘上)
  2. 数据索引问题,如果一张表有数百万的数据,肯定需要索引,但索引太多,机器不能安装
  3. 服务器无法承受访问量(读写) 只要上述问题开始出现,就必须升级。

2)Memcached(分布式高速缓存系统) mysql 垂直拆分(读写分离)

memcached这是一种缓存技术,它可以将您的数据放入内存中,从而通过内存访问加速,因为内存是最快的,缓存技术的主要目的是加速!

在memcached保养了一个大的hashtable在内存中,表的结构是key和value memcached的key一般是字串,不能重复 memcached的value(字符串、数值、数组、对象、布尔、二进制数据、图片和视频)

80%的网站都在阅读。每次直接查询数据库都很麻烦,数据库无法携带。因此,我们希望减轻数据库的压力,并使用缓存来确保效率! 这个时代的发展过程:优化数据库结构和索引(优化数据库底层)–> 文件缓存(IO,在文件中保存数据肯定比数据库好) --> Memcached(当时最流行的技术)

针对单机mysql,为了解决高并发解决高并发阅读的压力cache缓存可以很好地解决这个问题。 数据库可以垂直拆分,比如一个读两个写。写作内容通过主从复制同步更新到另外两个数据库。

3)分库分表 水平拆分 MySQL集群

随着技术和业务的不断发展,对性能的要求越来越高 本质:数据库(读写) 早些年MyISAM:表对效率影响很大!高并发会导致严重的锁问题 转战Innodb:行锁 慢慢开始用分库分表来解决写作压力! mysql集群满足了当年的需求

4)最近的时代

mysql关系数据库不够,因为数据量大,变化快 Mysql有些人用他来存储一些更大的文件、博客、图片!如果有一个数据库来处理这些数据,如果数据库很大,效率很低,mysql压力变得很小。(研究如何处理这些问题)

2.为什么要用?nosql?

个人信息、社交网络、地理位置、用户自身数据、用户日志等爆炸性增长。 我们需要在这个时候使用它Nosql解决这些问题的数据库

3.什么是nosql?

nosql = not only sql 不仅仅是sql,一般指非关系数据库web2.随着互联网的诞生,传统的关系数据库很难处理2.0时代,特别是超大规模高并发社区, 暴露了很多问题,所以nosql在今天的大数据库下发展迅速。

用户的个人信息、社交网络和地理位置。这些数据类型的存储不需要固定格式!水平扩展不需要额外的操作!

4.nosql特点是什么?

  1. 方便扩展(数据之间没有关系,很好扩展)
  2. 高性能的大数据量(redis每秒可写8万次,读11万次,nosql缓存记录级,是细粒度缓存,性能较高)
  3. 数据类型多样(不需要事先设计数据库,随用随取)

5.nosql的四大分类

  • KV键值对
  • 文档数据库
  • 存储数据库
  • 图形数据库

二、redis入门

1.什么是redis?

Redis(Remote Dictionary Server ),即远程字典服务 使用开源ANSI C语言编写、支持网络、基于内存或可持续的日志,Key-Value提供多种语言的数据库API。

2.reds能干什么?

  1. 内存存储、持久化、内存中是断电即失,所以说持久化很重要(rdb,aof)
  2. 效率高,可以用于高速缓存
  3. 发布订阅系统
  4. 地图信息分析
  5. 计时器、计数器(浏览量)

3.特性

1.多样的数据类型 2. 持久化 3. 事务

4.学习中需要用到的东西

1、官网:https://redis.io/ 2、中文网:http://www.redis.cn/

5.安装

https://blog.csdn.net/weixin_43099842/article/details/124965690?spm=1001.2014.3001.5501

6.性能测试

redis-benchmark是一个压力测试工具!

官方自带的性能测试工具!

redis-benchmark 命令参数,即可测试

首先需要保证redis-server服务开启,并且可以连通

参数如下: 使用下面语句测试 [huizi@localhost bin]$ ./redis-benchmark -h localhost -p 6379 -c 100 -n 100000

7.基础知识

redis默认有16个数据库,从0开始到15个,默认是第0个

可以在配置文件中查看

基本命令

select:切换数据库

dbsize:查看数据库大小

keys *::获取当前数据多有的key

flushdb:清除当前数据库

flushall:清除所有数据库内容

Redis 是单线程的

Redis是很快的,官方表示,Redis是基于内存操作的,所以CPU并不是Reids的性能瓶颈,Reids的瓶颈是根据机器的内存和网络带宽(请求都需要经过网络)来的。

既然可以使用单线程来实现,所以就使用了单线程!

Redis 是 C 语言写的,官方提供的数据为 100000+ 的QPS(每秒请求数),完全不比同样是 key-value的Memcache差!

1、误区1:高性能的服务器一定是多线程的?不一定

2、误区2:多线程(CPU会上下文切换,这是耗时的操作!)一定比单线程效率高!是不对的。

需要去了解 CPU、内存、硬盘的速度!

三、redis五大数据类型

127.0.0.1:6379> keys *    # 查看当前数据库所有的key
(empty list or set)
127.0.0.1:6379> set name zxh    # set一个key-value
OK
127.0.0.1:6379> set age 1
OK
127.0.0.1:6379> keys *
1) "age"
2) "name"
127.0.0.1:6379> exists name        # 判断key是否存在
(integer) 1
127.0.0.1:6379> exists name1
(integer) 0
127.0.0.1:6379> move name 1        # 移除key,1表示第0个数据库,从小到大 这个和select有区别
(integer) 1
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> get age        # 根据key获取值
"1"
127.0.0.1:6379> set name zxh
OK
127.0.0.1:6379> expire name 10    # 设置key的过期时间
(integer) 1
127.0.0.1:6379> ttl name    # 查看当前key的剩余时间
(integer) 7
127.0.0.1:6379> ttl name
(integer) 6
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name
(integer) 5
127.0.0.1:6379> ttl name
(integer) 1
127.0.0.1:6379> ttl name
(integer) -2
127.0.0.1:6379> get name
(nil)
127.0.0.1:6379> keys *
1) "age"
127.0.0.1:6379> type age    # 查看当前key的类型

1.String 字符串

字符串常用命令

1.1 追加、判断是否存在、获取长度

set key value:设置值

get key value:获取值

keys *:获取所以的key

append key value:追加字符串,如果当前key不存在,就相当于set一个key

strlen key:获取字符串的长度

exists key:判断某一个key是否存在

127.0.0.1:6379> keys *
1) "name"
127.0.0.1:6379> EXISTS name     #判断key是否存在,不存在就是新建
(integer) 1
127.0.0.1:6379> append name hello   # 追加数值
(integer) 10
127.0.0.1:6379> get name
"huizihello"
127.0.0.1:6379> 
127.0.0.1:6379> STRLEN name    # 获取key的value字符串长度
(integer) 10

1.2 字符串类型为整数的增/减量

可能用作浏览量等等

incr key:自增 +1 decr key:自减 -1 incrby key increment:设置步长,指定增量! decrby key decrement:设置步长,指定减量!

127.0.0.1:6379> set view 0
OK
127.0.0.1:6379> INCR view
(integer) 1
127.0.0.1:6379> get view
"1"
127.0.0.1:6379> INCR view
(integer) 2
127.0.0.1:6379> get view
"2"
127.0.0.1:6379> DECR view
(integer) 1
127.0.0.1:6379> get viewe
(nil)
127.0.0.1:6379> get view
"1"
127.0.0.1:6379> INCRBY view 2
(integer) 3
127.0.0.1:6379> get view
"3"
127.0.0.1:6379> DECRBY view 3
(integer) 0

1.3 截取和替换

getrange key start end:字符串截取,比如 [0,5] 左右都是一个闭区间

setrange key offset value:字符串的替换,替换指定下标的字符

127.0.0.1:6379> getrange name 0 3   # 左右都是闭区间
"huiz"
127.0.0.1:6379> setrange name 4 i   
(integer) 10
127.0.0.1:6379> get name
"huizihello"

1.4 设置时间

setex key seconds value:设置过期时间

ttl key:查看剩余时间

setnx key value:判断是否存在,再创建

127.0.0.1:6379> setnx age 19    # 如果key存在就不创建
(integer) 0
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> setnx sex 1   # 如果key不存在就创建
(integer) 1
127.0.0.1:6379> keys *
1) "age"
2) "sex"
3) "name"
4) "view"
127.0.0.1:6379> 

1.5 多个值的set 和获取get以及对象存储

mset [key value…]:同时设置多个k-v

mget [key …]:同时获取多个k-v

msetnx [key value…]:设置多个k-v,msetnx是一个原子操作,要么一起成功,要么一起失败,用于分布式锁

127.0.0.1:6379> mset k1 v1 k2 v2 k3 v3 # 同时设置多个k-v
OK
127.0.0.1:6379> keys *
1) "k1"
2) "k2"
3) "age"
4) "name"
5) "sex"
6) "k3"
7) "view"
127.0.0.1:6379> mget k1 k2 k3  # 同时获取多个key
1) "v1"
2) "v2"
3) "v3"
127.0.0.1:6379> msetnx k1 v1 k4 v4  # 设置多个key,要么成功,要么失败
(integer) 0

可以使用 user:1:name 这种key方式来表示 user1对象的name属性,用来代替json字符串

# 如果保存 user1:{name:zhangsan,age:18} json表示的对象 那么可以下面这么做。足以看出redis是非常强大的
127.0.0.1:6379> mset user:1:name zhansgan user:1:age 18
OK
127.0.0.1:6379> keys *
1) "age"
2) "k2"
3) "user:1:name"
4) "name"
5) "view"
6) "user:1:age"
7) "k1"
8) "sex"
9) "k3"
127.0.0.1:6379> 

1.6 先获取后设置

getset key value:先获取之前存放的值,再设置,如果存在就是覆盖

127.0.0.1:6379> getset age 18 
"18"
127.0.0.1:6379> get age
"18"
127.0.0.1:6379> get age 17
(error) ERR wrong number of arguments for 'get' command
127.0.0.1:6379> getset age 17
"18"
127.0.0.1:6379> get age
"17"

应用场景

String类似的使用场景:value除了是我们的字符串还可以是我们的数字!

  • 计数器
  • 统计多单位的数量
  • 粉丝数
  • 对象缓存存储

2.List

在redlis中的List类型,可以玩成栈、队列、阻塞队列 看下面的图 左端进,右端出 ---->队列 左端进,左端出 ---->栈 所有的List命令基本都是l开头的

##################################################

lpush key value [value…]:将一个或多个值,插入到列表的头部(也就是左端)

lrange key start end:取list中的值!先进后出,后进先出,可以看出一条水平线,从左端依次塞入,做左端依次拿出

rpush key value [value…]:从将一个或多个值,从列表的右端放入

##################################################

lpop key:移除列表的第一元素,从左端移除

rpop key:移除列表的最后一个元素,从右端移除

##################################################

lindex key index:通过下标获取列表的值

llen key:获取列表的长度/大小

##################################################

lrem key count value:移除列表中指定个数的指定的值,精准匹配

##################################################

ltrim key start end:通过下标指定长度,截取列表的值,并且用截取的列表改变原列表

##################################################

rpoplpush resouce destination:移除原列表最后一个元素,将它移动到新的列表中(做左端放入)

##################################################

lset key index value:替换列表中指定下标的值

linsert key before|after pivot value:在指定的值前面或者后面插入值

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> RPUSH list four
(integer) 4
127.0.0.1:6379> LRANGE list 0 -1
1) "three"
2) "two"
3) "one"
4) "four"
###########################################################################################################
127.0.0.1:6379> lpop list 
"three"
127.0.0.1:6379> rpop list
"four"
127.0.0.1:6379> LRANGE list 0 -1
1) "two"
2) "one"
###########################################################################################################
127.0.0.1:6379> lindex list 0
"two"
127.0.0.1:6379> llen list
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "one"
3) "one"
4) "one"
###########################################################################################################
127.0.0.1:6379> lrem list 3 one
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "one"
###########################################################################################################
127.0.0.1:6379> ltrim list 0 1
OK
127.0.0.1:6379> lrange list 0 -1
1) "one"
2) "one"
###########################################################################################################
127.0.0.1:6379> RPOPLPUSH list mylist
"one"
127.0.0.1:6379> keys *
1) "mylist"
2) "list"
127.0.0.1:6379> EXISTS mylist
(integer) 1
127.0.0.1:6379> lrange list 0 -1
1) "one"
###########################################################################################################
127.0.0.1:6379> lset mylist 0 two
OK
127.0.0.1:6379> LRANGE mylist 0 -1
1) "two"
###########################################################################################################
127.0.0.1:6379> LINSERT list before one hello
(integer) 2
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "one"
127.0.0.1:6379> LINSERT list after one hello1
(integer) 3
127.0.0.1:6379> lrange list 0 -1
1) "hello"
2) "one"
3) "hello1"

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

如果key 不存在,创建新的链表

如果key存在,新增内容

如果移除了所有值,空链表,也代表不存在!

在两边插入或者改动值,效率最高! 中间元素,相对来说效率会低一点~

消息排队!消息队列 (Lpush Rpop), 栈( Lpush Lpop)!

3.Set

set中的值是不能重复的!set命令一般是以s开头

sadd key meber [member…]:在set集合中添加元素

smembers key:查看指定set集合的所有值

sismember key member:判断某一个值是否在集合中

scard key:获取指定set集合的大小

srem key member [member…]:移除set集合中指定的一个或多个元素

srandmember key count:随机获取set集合中的一个或者多个元素

spop key cout:随机删除一个或者多个元素

smove resouce destination member:将集合中指定的元素移动到另一个集合中

sdiff key [key…]:差集,保留在第一个集合中其他集合里没有的值

sinter key [key…]:交集

sunion key [key…]:并集

# sadd key meber [member...]:在set集合中添加元素

# smembers key:查看指定set集合的所有值
127.0.0.1:6379> sadd myset hello
(integer) 1
127.0.0.1:6379> sadd myset "hello"
(integer) 0
127.0.0.1:6379> SMEMBERS myset
1) "hello"

#sismember key member:判断某一个值是否在集合中
127.0.0.1:6379> SISMEMBER myset hello
(integer) 1
127.0.0.1:6379> SISMEMBER myset hello
(integer) 1
127.0.0.1:6379> SISMEMBER myset hello1
(integer) 0

#scard key:获取指定set集合的大小
127.0.0.1:6379> scard myset
(integer) 1

#srem key member [member...]:移除set集合中指定的一个或多个元素
127.0.0.1:6379> srem myset hello
(integer) 1
127.0.0.1:6379> smembers myset
(empty array)

#srandmember key count:随机获取set集合中的一个或者多个元素
127.0.0.1:6379> sadd myset huizi huizi1 huzi2 huizi3 huizi4
(integer) 5
127.0.0.1:6379> srandmember myset 1
1) "huzi2"
127.0.0.1:6379> srandmember myset 1
1) "huzi2"
127.0.0.1:6379> srandmember myset 1
1) "huizi1"

#spop key cout:随机删除一个或者多个元素
127.0.0.1:6379> spop myset 1
1) "huizi3"
127.0.0.1:6379> smembers myset
1) "huizi"
2) "huzi2"
3) "huizi1"
4) "huizi4"

#smove resouce destination member:将集合中指定的元素移动到另一个集合中
127.0.0.1:6379> smove myset myset2 huizi
(integer) 1
127.0.0.1:6379> smembers myset2
1) "huizi"

#sdiff key [key...]:差集,保留在第一个集合中其他集合里没有的值
# myset{huizi、huizi1、huizi2、huzi4}和myset2 {huizi} 差集为{huizi1、huizi2、huzi4}
127.0.0.1:6379> sdiff myset myset2
1) "huizi1"
2) "huzi2"
3) "huizi4"

#sinter key [key...]:交集
127.0.0.1:6379> sinter myset myset2
1) "huizi"

#sunion key [key...]:并集
127.0.0.1:6379> sadd myset2 huizi6
(integer) 1
127.0.0.1:6379> smembers myset2
1) "huizi6"
2) "huizi"
127.0.0.1:6379> sunion myset myset2
1) "huzi2"
2) "huizi4"
3) "huizi"
4) "huizi6"
5) "huizi1"

可以应用在共同关注,共同爱好,随机抽奖应用场景中。

4.Hash

hash类型:相当于map集合,原来存储的是 key-value,现在变成 key-map!本质和String类型没有太大区别,还是一个简单的k-v!

hset key field value:存放一个具体的 k-v

hget key field:获取key中某一个属性值

hmset key field value [field value…]:存放一个或多个 k-v

hmget key field [field…]:获取key中一个或多个属性值

hdel key field [field…]:删除key中一个或多个属性值

hgetall key:获取key的全部的数据,以键值对形式显示

hlen key:获取map的长度

hexists key field:判断map是否有对应的属性

hkeys key:获取map所有的key

hvals key:获取map所有的value

hincrby key field increment:对map中的整数类型进行增量

hsetnx key field value:判断map中是否有对应的属性,如果没有进行存储

# hset key field value:存放一个具体的 k-v

# hget key field:获取key中某一个属性值

# hmset key field value [field value...]:存放一个或多个 k-v

# hmget key field [field....]:获取key中一个或多个属性值
127.0.0.1:6379> hset myhash field1 hello
(integer) 1
127.0.0.1:6379> hget myhash field
(nil)
127.0.0.1:6379> hget myhash field1
"hello"
127.0.0.1:6379> hmset myhash field2 hello2 field3 hello3
OK
127.0.0.1:6379> hmget myhash field field2
1) (nil)
2) "hello2"

# hdel key field [field...]:删除key中一个或多个属性值

# hgetall key:获取key的全部的数据,以键值对形式显示
127.0.0.1:6379> hdel myhash field1
(integer) 1
127.0.0.1:6379> hgetall myhash
1) "field2"
2) "hello2"
3) "field3"
4) "hello3"

# hlen key:获取map的长度

# hexists key field:判断map是否有对应的属性
127.0.0.1:6379> hlen myhash
(integer) 2
127.0.0.1:6379

# hkeys key:获取map所有的key

# hvals key:获取map所有的value
127.0.0.1:6379> hkeys myhash
1) "field2"
2) "field3"
127.0.0.1:6379> hvals myhash
1) "hello2"
2) "hello3"

# hincrby key field increment:对map中的整数类型进行增量
127.0.0.1:6379> hset myhash field5 5
(integer) 1
127.0.0.1:6379> hincrby myhash field5 1
(integer) 6

# hsetnx key field value:判断map中是否有对应的属性,如果没有进行存储
127.0.0.1:6379> hsetnx myhash field5 1
(integer) 0  # 表示已经存在
127.0.0.1:6379> hsetnx myhash field4 2
(integer) 1  # 表示不存在,然后进行存储

hash主要用于存储用户信息之类的,经常变动的信息!hash更适合对象的存储,String类型更适合字符串存储!

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

5.Zset(有序集合)

Zset就是在set集合上,增加了一个值,比如:set k1 v1,现在是zset k1 score1 v1

我们就可以针对score1 这个值进行一些操作:比如排序

zadd key score member [score member…]:添加一个或者多个元素

zrange key start end [withscores]:指定区间获取set集合的元素,可以设置是否显示score字段

zrangebyscore key min max [withscores]:根据指定的score进行升序排列

zrevrange key start stop [withscores]:根据指定的score进行降序排列

zrem key member [member…]:删除一个或者多个元素

zcard key:获取set集合的长度/大小

zcount key min max:统计个数,按照score属性的区间进行,在[min,max]之间的个数

# zadd key score member [score member...]:添加一个或者多个元素

# zrange key start end [withscores]:指定区间获取set集合的元素,可以设置是否显示score字段
127.0.0.1:6379> zadd myzset 1 one
(integer) 1
127.0.0.1:6379> zadd myzset 2 two 3 three
(integer) 2
127.0.0.1:6379> zrange myzset 0 -1
1) "one"
2) "two"
3) "three"
# zrangebyscore key min max [withscores]:根据指定的score进行升序排列

# zrevrange key start stop [withscores]:根据指定的score进行降序排列
127.0.0.1:6379> zadd salary 2500 xiaohong
(integer) 1
127.0.0.1:6379> zadd salary 3000 xiaowang
(integer) 1
127.0.0.1:6379> zadd salary 3100 xiaozhang
(integer) 1
127.0.0.1:6379> zrangebyscore salary -inf +inf
1) "xiaohong"
2) "xiaowang"
3) "xiaozhang"
127.0.0.1:6379> zrangebyscore salary -inf +inf withscores   # 带上 withscores 就带上scores了
1) "xiaohong"

        标签: sub4p插头连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台