认识redis

认识redis

认识redis

      • 1、什么是redis?
      • 2、redis能干什么
      • 3、Linux环境下的安装
        • redis 的基本操作命令
        • redis的知识
      • 4、redis的五大基本类型
        • Redis-key
        • String (字符串)
        • List(列表)
        • Set(集合)
        • Hash(哈希)
        • Zset(有序集合)
      • 5、redis三种特殊数据类型
        • Hyperloglog(基数统计)
          • 什么是基数?
          • 优点
          • 方法
        • Geospatial(地理位置)
          • 1.相关命令参数
          • 3.作用:(获得地理位置的信息)
        • BitMaps(位图)
          • 什么是bitmaps
          • 用法
          • 应用
      • 6、事务
        • redis是否是原子性的解释
        • redis事务的操作过程
        • 事务错误
        • 监控
          • 悲观锁
          • 乐观锁
      • 7、redis 持久化
        • RDB
          • 1.什么是RDB?
          • 2.RBD怎样持久化?
          • 3.dump.rbd触发机制
          • 优点:
          • 缺点:
        • AOF
          • 1.什么是AOF?
          • 2.AOF怎样持久化?
          • 3.数据恢复
          • 优点:
          • 缺点:

1、什么是redis?

  • Redis(Remote Dictionary Server ),即远程字典服务。

  • 是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。

2、redis能干什么

  • 高效率、用于高速缓冲
  • 内存存储,持久化(内存是断电即失,为了数据长时间保存,因此需要持久化)
  • 地图位置信息分析
  • 用于计数器等等

3、Linux环境下的安装

1.官网下载redis

2.解压安装包

tar -zxvf redis***

3.基本环境安装

yum install gcc-c++
#进入到redis目录下执行
make 
make install

4.redis默认的安装路径 /usr/local/bin
在这里插入图片描述

5.将redis的配置文件redis.conf 复制到程序安装目录下/usr/local/bin/kcongif下

img

6.设置后台启动,修改vim redis.conf配置文件

img

7.通过指定的配置文件启动redis服务

img

8.使用redis-cli连接指定的端口号测试,默认是6379

img

9.查看redis进程是否开启

ps -ef|grep redis

10.关闭redis服务

shutdown

redis 的基本操作命令

keys * :查看当前数据库中所有的key

flushdb:清空当前数据库中的键值对

flushall :清空所有数据库的键值对

redis的知识
  • redis默认有16个数据库

  • redis每秒可读11万条数据,每秒可写8万条数据

  • 使用select n可以切换到指定的数据库

  • dbsize可以查看当前数据库的大小,数据库的大小和key数量有关

  • 不同数据库之间,数据是不能互通的,即在数据库2中,无法直接访问数据库1中的key值

  • redis是单线程的,且是基于内存操作的

  • redis的性能是瓶颈是基于机器内存和带宽的,与cpu的性能无关

4、redis的五大基本类型

Redis-key
在redis中无论什么数据类型,在数据库中都是以key-value形式保存,通过进行对Redis-key的操作,来完成对数据库中数据的操作.
String (字符串)
List(列表)
  • redis列表时=是简单的字符串列表,按照插入的顺序排序,可以添加一些元素到列表的左边(头部)或者右边(尾部)
  • 经过规定可以将list变为队列、栈、消息队列
  • list中允许value的值重复、但是在set方法中不允许value的值重复
Set(集合)
  • - reids的set是string类型的无序集合,因为集合成员是唯一的,因此不能出现重复的元素

  • Redis中集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)

  • 集合最大成员数2^32 -1

Hash(哈希)
  • redis hash是一个是string 类型的field和value的映射表,Hash适合用于存储对象。

  • set是一种简化的hash,只要变动key,value的值就会默认的变动

常用的命令

命令 描述
hset key field value 将哈希表 key 中的字段 field 的值设为 value 。重复设置同一个field会覆盖,返回0
HMSET key field1 value1 [field2 value2…] 同时将多个 field-value (域-值)对设置到哈希表 key 中。
HSETNX key field value 只有当字段field不存在时,设置该字段
HSETNX key field value 查看当前hash表中,指定的字段值是否存在
HGET key field value 获取存储在hash表中的字段值
HMGET key field1 取所有给定字段的值
HDEL key field1 删除哈希表key中一个/多个field字段
HINCRBY key field n 为哈希表 key 中的指定字段的整数值加上增量n
HLEN key 获取哈希表中字段的数量
Zset(有序集合)

应用案例:

5、redis三种特殊数据类型

Hyperloglog(基数统计)
什么是基数?

a{1,2,3,4,4,5,6,7,8}

b{3,4,5,6,6,8.4,7}

a集合基数(不重复元素的个数)=8

b集合基数(不重复元素的个数)=5

优点
  • 输入元素的数量或者体积非常非常大时,计算基数所需的空间总是固定 的、并且是很小的。
方法
pfadd key element #添加指定元素到 HyperLogLog中
PFCOUNT key [key ...] #返回给定 HyperLogLog 的基数估算值
Geospatial(地理位置)
1.相关命令参数
genadd # 添加地理位置(地理经纬度)
127.0.0.1:6379> geoadd china:city 121.47 31.23 shanghai
(integer) 1
geopos # 获取指定城市的经度和纬度
GEOPOS china:city beijing chongqi
1) 1) "116.39999896287918091"
geodis # 获取两人之间的距离
GEODIST china:city beijing shanghai km 
georadius # 以给定的经纬度为中心, 找出某一半径内的元素
GEODIST china:city beijing shanghai km # 查看上海到北京的直线距离
"1067.3788"
georadlusbymember  # 找出位于指定元素周围的其他元素!
GEORADIUSBYMEMBER china:city beijing 1000 km
1) "beijing"
2) "xian"

知识扩展:

geo的底层原理是zset,可以用zset命令操作geo

3.作用:(获得地理位置的信息)
  • 百度地图定位
  • 附近人的获取
  • 打车计算距离
BitMaps(位图)
什么是bitmaps

bitmap就是通过最小的单位bit来进行0或者1的设置,表示某个元素对应的值或者状态。

用法
setBit key 0  1  #  给一个指定key的值得第offset位 赋值为value。
getbit key offset  # 返回一个指定key的二进制信息 
应用
  • 上班是否按时打卡
  • 用户签到

6、事务

MULTI 、 EXEC 、 DISCARD 和 WATCH 是 Redis 事务相关的命令。事务可以一次执行多个命令, 并且带有以下两个重要的保证:

  • 事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

    • 一次性
    • 顺序性
    • 排他性
  • 事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

redis是否是原子性的解释

单个 Redis 命令的执行是原子性的,但 Redis 没有在事务上增加任何维持原子性的机制,所以 Redis 事务的执行并不是原子性的。

redis事务的操作过程
  • 开启事务 (multi)
  • 命令入队(set …get)
  • 执行事务(exec)
  • 放弃事务(discard)

事务中所有的命令操作都是序列化、顺序执行

127.0.0.1:6379> multi  #开启事务
OK
127.0.0.1:6379(TX)> set key1 v1 #命令入队
QUEUED
127.0.0.1:6379(TX)> set key2 v2
QUEUED
127.0.0.1:6379(TX)> set key3 v3
QUEUED
127.0.0.1:6379(TX)> get key2
QUEUED
127.0.0.1:6379(TX)> set key4 v4
QUEUED
127.0.0.1:6379(TX)> exec #执行事务
1) OK
2) OK
3) OK
4) "v2"
5) OK
127.0.0.1:6379> exec
(error) ERR EXEC without MULTI #当前未开启事务

执行discard时,事务将会被阻断不被执行

127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379(TX)> set k 2 #命令入队
QUEUED
127.0.0.1:6379(TX)> set k1 3
QUEUED
127.0.0.1:6379(TX)> set k2 4
QUEUED
127.0.0.1:6379(TX)> DISCARD #放弃事务
OK
127.0.0.1:6379> get k2
(nil)
127.0.0.1:6379> exec #执行事务出错
(error) ERR EXEC without MULTI
127.0.0.1:6379> 

事务错误

编译时错误:代码语法错误,所有的命令都不会执行

127.0.0.1:6379> multi #开启事务
OK
127.0.0.1:6379(TX)> set k 1 #命令入队
QUEUED
127.0.0.1:6379(TX)> set k1 2
QUEUED
127.0.0.1:6379(TX)> error #执行一个错误的命令
(error) ERR unknown command `error`, with args beginning with: 
127.0.0.1:6379(TX)> set k3 4
QUEUED
127.0.0.1:6379(TX)> exec # 执行事务出现异常
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> 

运行时异常,代码逻辑错误,其他命令正常执行

所以不保证事务原子性操作

127.0.0.1:6379> multi#开启事务
OK
127.0.0.1:6379(TX)> set k1 v1 #命令入队
QUEUED
127.0.0.1:6379(TX)> set k2 v2 
QUEUED
127.0.0.1:6379(TX)> set k3 v3
QUEUED
127.0.0.1:6379(TX)> incr k1 #对字符串进行自增操作(该命令逻辑错误)
QUEUED
127.0.0.1:6379(TX)> get k2
QUEUED
127.0.0.1:6379(TX)> exec
1) OK
2) OK
3) OK
4) (error) ERR value is not an integer or out of range #命令报错
5) "v2"
#该结果说明 redis单条指令保证原子性操作,但是redis事务不能保证原子性
监控
悲观锁
  • 认为什么时候都会出错,无论做什么都会加锁
  • 共享资源的时候每次只能给一个线程使用,其他线程会被阻塞,用完后再把资源转让给其他线程
乐观锁
  • 认为什么时候都不会出问题,所以不会上锁,但是在更新数据的时候去判断一下,在此期间是否有人修改过这个数据
  • 一般多用于多读场景,写场景很少被使用
  • 获取versio
  • 更新的时候比较version

使用watch key监控指定数据,相当于乐观锁加锁。

基于单线程正常执行

127.0.0.1:6379> set money 100 #设置Money 100
OK
127.0.0.1:6379> set use 0 #设置use 0
OK
127.0.0.1:6379> watch money #监视money 上锁 
OK
127.0.0.1:6379> multi  #开启事务
OK 
127.0.0.1:6379(TX)> decrby money 30  
QUEUED
127.0.0.1:6379(TX)> incrby use 30
QUEUED
127.0.0.1:6379(TX)> exec #监视数据是否被修改
1) (integer) 70
2) (integer) 30
127.0.0.1:6379>

测试多线程修改值,使用watch可以当做redis的乐观锁操作

# 线程1
27.0.0.1:6379> set money 100
OK
127.0.0.1:6379> set use 0
OK
127.0.0.1:6379> watch money
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379(TX)> decrby money 50
QUEUED
127.0.0.1:6379(TX)> incrby use 50
QUEUED
#开启线程2
[root@gitShile bin]# redis-server kconfig/redis.conf 
[root@gitShile bin]# redis-cli -p 6379
127.0.0.1:6379> incrby money 500
(integer) 600
127.0.0.1:6379>
#继续操作线程1
127.0.0.1:6379(TX)> exec  #执行事务
(nil)
127.0.0.1:6379> get money
"600"
127.0.0.1:6379> get use
"0"

7、redis 持久化

RDB
1.什么是RDB?

在指定的时间间隔内,将内存的数据集快照(Snapshot)写入磁盘,它恢复时是将快照文件写入到内存中。

2.RBD怎样持久化?

rbd保存的文件以dump.rbd二进制的形式快照中进行配置的

redis会单独创建(folk)一个进程来实现持久化,将数据写入到一个临时文件中,待持久化结束后,再用这个临时文件替换上次持久化好的文件。

3.dump.rbd触发机制
  • save的规则满足时,触发rdb规则
  • 执行flushall命令时,触发rdb规则
  • 退出redis时,触发rdb规则
  • 备份中会自动产生dump.rdb文件
优点:
  • 对于大规模数据恢复时,RBD比AOF恢复的方式快
  • RDB可以最大化Redis性能,父进程做的就是fork子进程,然后继续接受客户端请求,让子进程负责持久化操作,父进程无需进行IO操作。
缺点:
  • fork进程的时候,会占用一定的内容空间

  • 需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了!

AOF
1.什么是AOF?

以日志的形式记录redis每一个写操作,将redis执行的过程记录下来(不追加读操作),只需追加不可改写文件

2.AOF怎样持久化?
redis启动之后会读取appendonly.aof文件来实现重新恢复数据,完成恢复数据的工作。默认不开启,需要将redis.conf中的appendonly no改为yes启动Redis。

appendfsync always:#每修改同步,每一次发生数据变更都会持久化到磁盘上,性能较差,但数据完整性较好。

appendfsync everysec: #每秒同步,每秒内记录操作,异步操作,如果一秒内宕机,有数据丢失。

appendfsync no:#不同步。
3.数据恢复

重启Redis时,如果dump.rdb与appendfsync.aof同时都存在时,Redis会自动读取appendfsync.aof文件,通过该文件中对数据库的日志操作,来实现数据的恢复。当然如果该文件被破坏,我们可以通过redis-check-aof工具来修复,如redis-check-aof --fix能修复破损的appendfsync.aof文件,当然如果dump.rdb文件有破损,我们也可以用redis-check-rdb工具来修复,如果appendfsync.aof文件破损了,是启动不客户端的,也就是无法完成数据的恢复。

优点:
  • 每一次修改都同步,文件的完整会更加好!
  • Redis可以在AOF文件变得过大时,会自动地在后台对AOF进行重写
  • 从不同步,效率最高的!
缺点:
  • 对于相同的数据集来说,AOF文件要比RDB文件大。
  • AOF的运行效率要比RBD慢

学习资源来自:https://www.bilibili.com/video/BV1S54y1R7SB?t=348&p=36

redis官网:redis中文官方网站

redis面试高频问题:redis面试题

狂神说redis:狂神说redis.

你可能感兴趣的:(redis)