Redis入门

Redis入门

概述

Redis是什么?

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

  • redis是一个key-value存储系统。
  • Redis 是一个高性能的key-value数据库。
  • Redis支持主从同步。

Redis能干什么?

  • 内存存储、持久化,内存中的数据是断电即失的,所以说持久化很重要(rdb、aof)
  • 效率高,可以用于高速缓存
  • 发布订阅系统(MQ消息队列等)
  • 地图信息分析
  • 计时器、计数器等

学习中需要用的东西

在这里插入图片描述

在这里插入图片描述

  • 下载地址(通过官网下载即可,Windows版通过Github下载)

安装

Windows安装

  1. 下载安装包 https://github.com/MicrosoftArchive/redis/releases
    在这里插入图片描述

  2. 压缩包解压到指定自定义目录即可

在这里插入图片描述

  1. 双击运行redis-server.exe即可启动Redis

在这里插入图片描述

  1. 使用redis-cli.exe连接数据库
    在这里插入图片描述

Redis在Windows的安装确实简单,Redis官方推荐使用Linux环境

在这里插入图片描述

Linux安装

  1. 下载压缩包 https://redis.io/download

在这里插入图片描述

  1. 将压缩包复制到Linux中(推荐/usr/local或者/opt目录下),使用tar -zxvf 压缩文件名解压即可

在这里插入图片描述
在这里插入图片描述

  1. 基本环境的安装

    yum install gcc-c++		#安装gcc环境
    make					#使用make编译文件
    make install			#使用make install确认安装(可以不执行)
    
  2. redis的默认安装路径/usr/local/bin

在这里插入图片描述

  1. 将解压目录中的redis.conf配置文件复制到/usr/local/bin/myconf目录下(myconf目录为新建目录,命名随意)

在这里插入图片描述

  1. redis不是默认后台启动的,修改配置文件改为后台启动

    vi redis.conf		#编辑redis配置文件
    

    找到daemonize no修改为daemonize yes即可

在这里插入图片描述

  1. 启动redis服务

    redis-server myconf/redis.conf		#使用redis-server命令并显式的指定配置文件启动redis服务
    

在这里插入图片描述

使用ps -ef | grep redis可以查看redis已经启动成功,运行在6379端口

  1. 使用redis-client进行测试

在这里插入图片描述

  1. 如何关闭redis服务

    redis-client连接状态是执行shutdown指令

在这里插入图片描述

执行后提示not connected代表已经断开连接,也就是redis-server已经停止

可以使用ps再次查看进程验证

基础知识

  • redis有16个数据库

在这里插入图片描述

默认使用的是第0个

可以使用select进行切换

在这里插入图片描述

  • redis是单线程的

    Redis是很快的,官方表示Redis是基于内存操作,CPU不是Redis的性能瓶颈,Redis的瓶颈在于机器的内存和网络等带宽,既然单线程可以实现功能并且不影响性能,就是没必要使用多线程。(后来支持多线程的原因是在读写内存时会产生内存阻塞,比如删除一个大文件会卡)

    Redis是C语言写的,官方提供的数据为100000+的QPS,这不比同样使用key-value的Memecache差!

    Redis单线程为什么还这么快?

    1. 误区一:高性能的服务器一定是多线程的?
    2. 误区二:多线程(CPU上下文切换)一定比单线程效率高?

    核心:redis是将所有的数据全部放在内存中,所以说使用单线程去操作效率就是最高的。(对于内存系统来说如果没有CPU上下文操作,效率就是最高的。)

五大数据类型

官方解释:

​ Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 它支持多种类型的数据结构,如 字符串(strings)散列(hashes)列表(lists)集合(sets)有序集合(sorted sets) 与范围查询, bitmapshyperloglogs地理空间(geospatial) 索引半径查询。 Redis 内置了 复制(replication)LUA脚本(Lua scripting)LRU驱动事件(LRU eviction)事务(transactions) 和不同级别的 磁盘持久化(persistence), 并通过 Redis哨兵(Sentinel)和自动 分区(Cluster)提供高可用性(high availability)。

Redis-key

127.0.0.1:16379> ping
PONG
127.0.0.1:16379> set name zhangsan	#设置一个key的值
OK
127.0.0.1:16379> get name			#获取指定key的值
"zhangsan"
127.0.0.1:16379> set age 18
OK
127.0.0.1:16379> set sex 0
OK
127.0.0.1:16379> keys *				#查看当前数据库中所有的key
1) "name"
2) "sex"
3) "age"
127.0.0.1:16379> del sex			#删除当前库中的指定key
(integer) 1
127.0.0.1:16379> keys *
1) "name"
2) "age"
127.0.0.1:16379> move name 1		#移动key到指定数据库中
(integer) 1
127.0.0.1:16379> keys *
1) "age"
127.0.0.1:16379> select 1
OK
127.0.0.1:16379[1]> keys *
1) "name"
127.0.0.1:16379[1]> flushall		#清空所有数据库中的key
OK
127.0.0.1:16379[1]> select 0
OK
127.0.0.1:16379> keys *
(empty array)

String

90%的Java程序员使用redis只会使用一个String类型!

127.0.0.1:16379> set key1 v1		#设置值
OK
127.0.0.1:16379> get key1			#获取值
"v1"
127.0.0.1:16379> exists key1		#判断值是否存在
(integer) 1
127.0.0.1:16379> append key1 hello	#追加字符串,如果指定的key不存在,则等于set key
(integer) 7
127.0.0.1:16379> get key1			
"v1hello"
127.0.0.1:16379> strlen key1		#获取字符串长度
(integer) 7
############################################################################################
127.0.0.1:16379> set count 100
OK
127.0.0.1:16379> get count
"100"
127.0.0.1:16379> incr count			#值自增1
(integer) 101
127.0.0.1:16379> incr count
(integer) 102
127.0.0.1:16379> decr count			#值自减1
(integer) 101
127.0.0.1:16379> get count
"101"
127.0.0.1:16379> incrby count 10	#自增指定步长
(integer) 111
127.0.0.1:16379> decrby count 5		#自减指定步长
(integer) 106
############################################################################################
127.0.0.1:16379> set key1 "hello, zadaya!"
OK
127.0.0.1:16379> get key1
"hello, zadaya!"
127.0.0.1:16379> getrange key1 0 3		#截取字符串(0 3 代表截取0,1,2,3)
"hell"
127.0.0.1:16379> getrange key1 0 -1
"hello, zadaya!"
127.0.0.1:16379> set key2 "abcdefg"
OK
127.0.0.1:16379> get key2
"abcdefg"
127.0.0.1:16379> setrange key2 2 xyz	#从指定位置替换字符串
(integer) 7
127.0.0.1:16379> get key2
"abxyzfg"
############################################################################################
#setex(set with expire)			#设置过期时间
#setnx(set if not exist)		#不存在再设置		--在分布式锁中会常常使用
127.0.0.1:16379> setex key3 30 "v3-30s"			#设置一个key并设置了过期时间
OK
127.0.0.1:16379> ttl key3
(integer) 20
127.0.0.1:16379> get key3
"v3-30s"
127.0.0.1:16379> ttl key3						#key已过期(-1为永不过期)
(integer) -2
127.0.0.1:16379> setnx key3 "value3-nx"			#执行结果为1代表该key不存在,设置key成功
(integer) 1
127.0.0.1:16379> keys *
1) "key3"
2) "key2"
3) "key1"
127.0.0.1:16379> setnx key3 "value3-nx-new"		#可以看到执行结果为0,设置key失败
(integer) 0
127.0.0.1:16379> get key3
"value3-nx"
############################################################################################
#mset	#批量设置key值 	
#mget	#批量获取key值
127.0.0.1:16379> keys *
(empty array)
127.0.0.1:16379> mset k1 v1 k2 v2 k3 v3 k4 v4
OK
127.0.0.1:16379> keys *
1) "k4"
2) "k3"
3) "k2"
4) "k1"
127.0.0.1:16379> mget k1 k3 k4 k5
1) "v1"
2) "v3"
3) "v4"
4) (nil)
127.0.0.1:16379> msetnx k1 vv1 k5 vv5		#虽然k5不存在,但k1存在,所以这次操作失败,说明msetnx是一个原子性操作
(integer) 0
############################################################################################
127.0.0.1:16379> mset user:1:name zhangsan user:1:age 2		#可以通过巧妙设置key值来实现对象属性的存储
OK
127.0.0.1:16379> mget user:1:name user:1:age
1) "zhangsan"
2) "2"
127.0.0.1:16379> 
############################################################################################
#getset			#先获取旧值再设置新值
127.0.0.1:16379> getset total 100
(nil)
127.0.0.1:16379> getset total 200
"100"
127.0.0.1:16379> getset total 300
"200"
############################################################################################
#sdiff		#差集		#获取源set与多个set间元素的差集
#sinter		#交集		#获取源set与多个set间元素的交集
#sunion		#并集		#获取源set与多个set间元素的交集
127.0.0.1:16379> sadd set1 a b c
(integer) 3
127.0.0.1:16379> sadd set2 b c d
(integer) 3
127.0.0.1:16379> sdiff set1 set2		#set1相较set2的差集是a
1) "a"
127.0.0.1:16379> sdiff set2 set1		#set2相较set1的差集是d
1) "d"
127.0.0.1:16379> sinter set1 set2		#set1与set2的交集
1) "c"
2) "b"
127.0.0.1:16379> sunion set1 set2		#set1与set2的并集
1) "a"
2) "b"
3) "d"
4) "c"
#应用场景:朋友圈扩展、共同关注对象、商品推荐等等

以上所有操作使用的数据结构都是相同的

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

  • 计数器,计时器
  • 统计访客数等
  • 对象的缓存

List

基本的数据类型,列表(底层双链表)

在这里插入图片描述

使用redis LIst我们可以实现栈、队列

127.0.0.1:16379> lpush list1 one			#从left侧push一个值到指定list中
(integer) 1
127.0.0.1:16379> lpush list1 two
(integer) 2
127.0.0.1:16379> lpush list1 three
(integer) 3
127.0.0.1:16379> lrange list1 0 -1			#获取指定list的0到-1位置的所有元素(-1代表最后一个)
1) "three"
2) "two"
3) "one"
127.0.0.1:16379> rpush list1 four five		#从right侧push一个值到指定list中
(integer) 5
127.0.0.1:16379> lrange list1 0 -1			
1) "three"
2) "two"
3) "one"
4) "four"
5) "five"
############################################################################################
127.0.0.1:16379> lpop list1 2				#从left侧pop出2个元素
1) "three"
2) "two"
127.0.0.1:16379> rpop list1 1				#从right侧pop出1个元素
1) "five"
127.0.0.1:16379> lrange list1 0 -1
1) "one"
2) "four"
############################################################################################
127.0.0.1:16379> rpush list2 one two three four five six seven eight
(integer) 8
127.0.0.1:16379> lindex list2 3			#索引指定位置的元素
"four"
127.0.0.1:16379> lindex list2 0
"one"
############################################################################################
127.0.0.1:16379> llen list2				#获取list的长度
(integer) 8
127.0.0.1:16379> lrange list2 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
5) "five"
6) "six"
7) "seven"
127.0.0.1:16379> lrem list2 2 one		#移除list中指定个数的value元素(这里指定移除2个,但list中只有1个)
(integer) 1
127.0.0.1:16379> ltrim list2 2 5		#截断list,通过下标截取指定长度保留
OK
127.0.0.1:16379> lrange list2 0 -1
1) "three"
2) "four"
3) "five"
4) "six"
############################################################################################
127.0.0.1:16379> exists list2
(integer) 1
127.0.0.1:16379> exists list3
(integer) 0
127.0.0.1:16379> lset list2 3 4			#设置list指定下标的值
OK
127.0.0.1:16379> lrange list2 0 -1
1) "one"
2) "two"
3) "three"
4) "4"
5) "five"
6) "six"
7) "seven"
8) "eight"
127.0.0.1:16379> 

Set

Set中的值是不能重复的

127.0.0.1:16379> sadd myset1 hello				#向指定set中添加值
(integer) 1
127.0.0.1:16379> sadd myset1 zadaya
(integer) 1
127.0.0.1:16379> smembers myset1				#获取set中所有元素
1) "zadaya"
2) "hello"
127.0.0.1:16379> sismember myset1 hello			#判断set中是否包含指定元素
(integer) 1
127.0.0.1:16379> sismember myset1 hel
(integer) 0
############################################################################################
127.0.0.1:16379> scard myset1					#获取set中的元素个数
(integer) 2
127.0.0.1:16379> smembers myset1
1) "world"
2) "zadaya"
3) "hello"
127.0.0.1:16379> srem myset1 zadaya				#移除set中指定元素
(integer) 1
127.0.0.1:16379> smembers myset1
1) "world"
2) "hello"
############################################################################################
#set无序不重复集合,实现随机抽取功能
127.0.0.1:16379> sadd myset2 a b c d e f g h i g k l m n
(integer) 13
127.0.0.1:16379> srandmember myset2 3			#从set中随机抽取指定个数的元素
1) "b"
2) "k"
3) "f"
127.0.0.1:16379> srandmember myset2 3
1) "m"
2) "b"
3) "h"

Hash

Map集合,key-value中这个value就是一个Map集合,本质和String没有什么区别,内部依然是key-value方式存储

127.0.0.1:16379> hset mh1 name zhangsan age 16		#为指定hash设置字段和值
(integer) 2
127.0.0.1:16379> hget mh1 name						#获取指定hash指定字段的值
"zhangsan"
127.0.0.1:16379> hmget mh1 age age name				#批量获取指定hash指定字段的值
1) "16"
2) "16"
3) "zhangsan"
127.0.0.1:16379> hgetall mh1						#获取指定hash所有字段和值
1) "name"
2) "zhangsan"
3) "age"
4) "16"
127.0.0.1:16379> keys *
1) "mh1"
127.0.0.1:16379> hset mh1 email 123@163.com
(integer) 1
127.0.0.1:16379> hexists mh1 email					#验证指定hash是否包含某一字段
(integer) 1
127.0.0.1:16379> hexists mh1 emailxx
(integer) 0
############################################################################################
#只获取所有的field
#只获取所有的value
127.0.0.1:16379> hkeys mh1				#获取指定hash中所有field
1) "name"
2) "age"
3) "email"
127.0.0.1:16379> hvals mh1				#获取指定hash中所有value
1) "zhangsan"
2) "16"
3) "123@163.com"
############################################################################################
127.0.0.1:16379> hgetall mh1
1) "name"
2) "zhangsan"
3) "age"
4) "16"
5) "email"
6) "123@163.com"
127.0.0.1:16379> hincrby mh1 age 2		#指定hash中指定field(Integer类型)的自增指定步长
(integer) 18
127.0.0.1:16379> hincrby mh1 age -2
(integer) 16

应用场景:Hash适合存储对象,尤其是用户信息之类这种经常变动的信息

所以Hash适合存储对象,Sting更加适合字符串存储

Zset

Zset-有序集合,在Set的基础上增加了一个值作为排序字段(set k1 v1, zset k1 score1 v1)

127.0.0.1:16379> zadd zs1 1 one				#为指定zset新增1个值并指定其位置(排序字段)
(integer) 1
127.0.0.1:16379> zadd zs1 2 two 3 three		#为指定zset新增多个个值并指定其位置
(integer) 2
127.0.0.1:16379> zrange zs1 0 -1			#获取zset中某一段位置上的值
1) "one"
2) "two"
3) "three"
127.0.0.1:16379> 
############################################################################################
#排序命令一定是min~max,也就是两个参数分别是最小值和最大值,不可颠倒
127.0.0.1:16379> zadd salary 2500 xiaohong 5000 zhangsan 1500 lisi
(integer) 3
127.0.0.1:16379> zrange salary 0 -1
1) "lisi"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:16379> zrangebyscore salary -inf +inf		#按照排序值从小到大获取指定范围内的值(-INF:无穷小; +INF:无穷大)
1) "lisi"
2) "xiaohong"
3) "zhangsan"
127.0.0.1:16379> zrangebyscore salary 2000 5000		#按照排序值从小到大获取指定范围内的值(2000~5000)
1) "xiaohong"
2) "zhangsan"
127.0.0.1:16379> zrangebyscore salary 2000 5000 withscores	#获取指定范围内的值和其排序值
1) "xiaohong"
2) "2500"
3) "zhangsan"
4) "5000"
############################################################################################
127.0.0.1:16379> zrange zs1 0 -1
1) "one"
2) "two"
3) "three"
4) "four"
5) "five"
6) "six"
7) "seven"
8) "eight"
127.0.0.1:16379> zrem zs1 three				#从指定zset中移除指定元素
(integer) 1
127.0.0.1:16379> zrange zs1 0 -1 withscores
 1) "one"
 2) "1"
 3) "two"
 4) "2"
 5) "four"
 6) "4"
 7) "five"
 8) "5"
 9) "six"
10) "6"
11) "seven"
12) "7"
13) "eight"
14) "8"
127.0.0.1:16379> zcount zs1 1 5				#获取zset指定区间成员数量
(integer) 4

应用场景:需要排序的数据比如成绩表、工资表,带权重的数据比如重要通知、消息提醒,还有排行榜等等

三种特殊数据类型

Geospatial 地理位置

#geoadd 添加地理位置
#参数 key value<经度 纬度 名称>
127.0.0.1:16379> geoadd china:city 116.40 39.90 beijing
(integer) 1
127.0.0.1:16379> geoadd china:city 121.47 32.23 shanghai 106.50 29.53 chongqing
(integer) 2
127.0.0.1:16379> geoadd china:city 114.8 22.54 shenzhen 120.16 30.24 hangzhou 108.94 34.26 xian
(integer) 3
############################################################################################
#geopos 获取指定城市的经纬度
127.0.0.1:16379> geopos china:city chongqing
1) 1) "106.49999767541885376"
   2) "29.52999957900659211"
127.0.0.1:16379> geopos china:city beijing shanghai
1) 1) "116.39999896287918091"
   2) "39.90000009167092543"
2) 1) "121.47000163793563843"
   2) "32.22999976626139329"
127.0.0.1:16379> 
#geodist 获取指定城市间的距离
127.0.0.1:16379> geodist china:city beijing shanghai
"966814.3446"
127.0.0.1:16379> geodist china:city beijing shanghai km		#可选参数[m|km|ft|mi]默认为m
"966.8143"
############################################################################################
#georadius 获取附近范围内的城市(类似某些软件获取附近的人等)
127.0.0.1:16379> georadius china:city 110 30 500 km			#必选参数[m|km|ft|mi]
1) "chongqing"
2) "xian"

Hyperloglog 基数统计

应用场景uv统计,比如用户访问数等

只做了解

Bitmaps 位图场景

位存储,应用场景只有两种状态(0、1)的都可以使用Bitmaps

只做了解

事务

Redis事务的本质:一组命令的集合,一个食物中的所有命令会被序列化,在事务执行过程中,会按照顺序依次执行,不会被外部打断。

--------事务任务队列 set set get del --------

  • 一次性
  • 顺序性
  • 排他性

Redis单条命令是保持原子性的,但是事务不保证原子性!!!

Redis没有隔离级别的概念!!!

Redis的事务

  • 开启事务(multi)
  • 命令入队(…)
  • 执行事务(exec)
  • 取消事务(discard)

正常执行事务

127.0.0.1:16379> multi				#开启事务
OK
127.0.0.1:16379(TX)> set k1 v1		#命令入队
QUEUED
127.0.0.1:16379(TX)> set k2 v2		#命令入队
QUEUED
127.0.0.1:16379(TX)> get k2			#命令入队
QUEUED
127.0.0.1:16379(TX)> set k3 v3		#命令入队
QUEUED
127.0.0.1:16379(TX)> keys *			#命令入队
QUEUED
127.0.0.1:16379(TX)> exec			#执行事务
1) OK
2) OK
3) "v2"
4) OK
5) 1) "k1"
   2) "k2"
   3) "k3"
###################################################
127.0.0.1:16379> multi
OK
127.0.0.1:16379(TX)> set k1 v1
QUEUED
127.0.0.1:16379(TX)> set k2 v2
QUEUED
127.0.0.1:16379(TX)> set k4 v4
QUEUED
127.0.0.1:16379(TX)> discard		#取消事务
OK
127.0.0.1:16379> get k4
(nil)

Redis的锁

乐观锁

使用watch命令,可以当做redis的乐观锁,如果加锁期间有其他线程加锁的对象进行了修改,则加锁的事务会执行失败

127.0.0.1:16379> set money 100
OK
127.0.0.1:16379> watch money			#开启监控,对money进行监控
OK
127.0.0.1:16379> multi
OK
127.0.0.1:16379(TX)> decrby money 20
QUEUED
127.0.0.1:16379(TX)> exec				#执行之前使用其他线程修改money的值,然后执行事务就会失败
(nil)
127.0.0.1:16379> multi
OK
127.0.0.1:16379(TX)> decrby money 20	#开启事务到执行事务时没有其他线程修改money,事务执行成功
QUEUED
127.0.0.1:16379(TX)> exec
1) (integer) 80
127.0.0.1:16379> unwatch				#关闭监控

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值