Redis

Redis

  • NoSql,非关系型数据库

数据库发展历程

单机数据库时代

  • 一个应用,一个数据库实例

缓存,水平切分时代

  • 增减读写数据库缓存
  • 单表数据量过大,采用表水平切分,把一张表分成几张表

读写分离时代

  • 有不同的数据库实例,分别负责读写
  • 当写数据库完成写数据时,读数据库要完成数据同步

分库分表时代(集群)

  • 如果一张表的数据量过大,把一张表的数据分开,用不同的数据库存储
  • 访问该表,可能会使用多个数据库,需要切换不同的数据源

非关系型数据库时代(NoSql时代)

  • 上面的都是基于关系型数据库实现的:Mysql,Oracle,DB2,sqlserver…
  • 如今迎来了非关系型数据库:Redis,Hbasc,MongoDB
  • 底层存储机制被改变,不在采用仅以表为存储机制的存储方式,而是采用聚合数据结构存储数据。
  • 不仅支持key-value结构,还支持hash,set,list等数据结构。
  • Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

Redis特点

  • Remote dictionary server,远程字典服务
  • 是C语言编写的,开源的,基于内存运行的并支持持久化的,高性能的NoSql数据库,是当前热门的NoSql数据库之一。
  • 支持备份

安装

Windows

  • **下载地址:**https://github.com/tporadowski/redis/releases

  • 打开一个 cmd 窗口 使用 cd 命令切换目录到 C:\redis 运行:

    redis-server.exe redis.windows.conf
    
  • 如果想方便的话,可以把 redis 的路径加到系统的环境变量里,这样就省得再输路径了,后面的那个 redis.windows.conf 可以省略,如果省略,会启用默认的.

  • 这时候另启一个 cmd 窗口,原来的不要关闭,不然就无法访问服务端了。

  • 切换到 redis 目录下运行:

    redis-cli.exe -h 127.0.0.1 -p 6379			//启动服务,指定IP和端口port
    
  • 设置键值对:

    set myKey abc
    
  • 取出键值对:

    get myKey
    

Linux

  • **下载地址:**http://redis.io/download,下载最新稳定版本。

  • # wget http://download.redis.io/releases/redis-6.0.8.tar.gz
    # tar xzf redis-6.0.8.tar.gz
    # cd redis-6.0.8	
    # make		//需要gcc编译器
    
  • 执行完 make 命令后,redis-6.0.8 的 src 目录下会出现编译后的 redis 服务程序 redis-server,还有用于测试的客户端程序 redis-cli:

make:

Linux 下 make 命令是系统管理员和程序员用的最频繁的命令之一。管理员用它通过命令行来编译和安装很多开源的工具,程序员用它来管理他们大型复杂的项目编译问题。

make 命令像命令行参数一样接收目标。这些目标通常存放在以 “Makefile” 来命名的特殊文件中,同时文件也包含与目标相对应的操作。

当 make 命令第一次执行时,它扫描 Makefile 找到目标以及其依赖。如果这些依赖自身也是目标,继续为这些依赖扫描 Makefile 建立其依赖关系,然后编译它们。一旦主依赖编译之后,然后就编译主目标(这是通过 make 命令传入的)。

现在,假设你对某个源文件进行了修改,你再次执行 make 命令,它将只编译与该源文件相关的目标文件,因此,编译完最终的可执行文件节省了大量的时间。

  • 下面启动 redis 服务:

    # cd src
    # ./redis-server
    
  • 注意这种方式启动 redis 使用的是默认配置。也可以通过启动参数告诉 redis 使用指定配置文件使用下面命令启动。

    # cd src
    # ./redis-server ../redis.conf
    
  • redis.conf 是一个默认的配置文件。我们可以根据需要使用自己的配置文件。

  • 启动 redis 服务进程后,就可以使用测试客户端程序 redis-cli 和 redis 服务交互了。 比如:

    # cd src
    # ./redis-cli
    redis> set foo bar
    OK
    redis> get foo
    "bar"
    
gcc编译错误?
  • 安装好的虚拟机(用磁盘iso文件),其中自带的gcc版本是4.8.5的,版本太低。安装后redis后,执行make命令,会导致编译错误,原因是gcc版本太低导致的。

  • 升级gcc版本:

    • [root@localhost redis-6.0.1]# gcc -v                             # 查看gcc版本
      [root@localhost redis-6.0.1]# yum -y install centos-release-scl  # 升级到9.1版本
      [root@localhost redis-6.0.1]# yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
      [root@localhost redis-6.0.1]# scl enable devtoolset-9 bash
      以上为临时启用,如果要长期使用gcc 9.1的话:
      [root@localhost redis-6.0.1]# echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
      
  • 再次重新编译即可。

  • 或者在安装redis之前再安装一边gcc,也不会出现这个问题。

设置全局启动
#cd redis-6.0.8
#make install	//复制命令到usr/local/bin
//启动命令:
redis-server 
  • 将redis命令,放到bin目录下,以便可以在任何一个目录下启动redis服务。
  • 命令被放到了:/usr/local/bin 目录中,其中的命令已经被设置到了环境变量中。

redis基本操作

启动-停止

  • 启动:# redis-server [&]
  • 停止:kill -9 pid 或者 redis-cli shutdown,通过客户端向服务器发送一个命令,shutdown命令。

按照配置文件启动服务

  • redis提供了服务的配置文件,启动的时候指定配置文件,就可以按照配置文件的设置启动服务

  • [root@bogon /]# redis-server redis-conf &		//& 表示后台启动,一般使用,不会占用整个终端
    

客户端连接服务

  • 先启动服务 [root@bogon /]# redis-server &
  • 执行命令连接客户端[root@bogon /]# redis-cli ,默认连接本机(127.0.0.1)6379端口的redis服务。
指定连接IP和端口
  • [root@bogon /]# redis-cli -h Ip -p port,指定连接的服务器的IP和端口。

退出客户端

  • 127.0.0.1:6379> exit

基本知识

1)测试redis服务的性能

# redis-benchmark

2)查看redis服务是否正常运行

  • 127.0.0.1:6379> ping
  • 测试正常返回PONG

3)查看redis服务器统计信息

  • 127.0.0.1:6379> info [指定段名称]
  • 查看[指定段]全部信息

4)redis数据库实例

  • 类似mysql的一个个database,redis也有自己的数据库实例。
  • 但是redis的数据库实例,只能通过redis服务创建和维护,开发人员不能修改和自行创建数据库实例。
  • 默认情况下,redis服务启动的时候,会创建16个数据库实例,并且给这些数据库进行编号,从0开始。可以通过配置文件(redis-conf)指定redis服务启动的时候创建多少个数据库实例。
  • 开发使用数据库实例的时候,通过编号进行使用。
  • redis的数据库实例,不用维护表结构,本身的内存占用十分少,大约几十kb,所以及时使用不完数据库实例,也不会造成多大的空间浪费。
如何切换数据库实例?
  • redis服务启动默认使用0号数据库实例

  • 切换数据库实例:

  • 127.0.0.1:6379> select index //idnex是数据量实例编号,从0开始
    //切换后 select 1
    

127.0.0.1:6379[1]>



### 5)数据库基本操作

- ```js
127.0.0.1:6379> dbsize	//查看数据库实例key的个数
127.0.0.1:6379> keys *	//查看当前数据库实例的所有key
127.0.0.1:6379> flushdb	//清空当前数据库实例的所有key
127.0.0.1:6379> flushall 	//清空所有数据库的key

6)查看数据库配置信息

  • 127.0.0.1:6379> config get * 	//查看所有配置信息
    127.0.0.1:6379> config get 配置名称	//查看指定配置信息
    

5种数据结构

  • string ,list(有序),set(无序),hash,zset(排序)
  • string是最基本的数据结构,它能存储任何数据类型的数据。包括二进制数据,序列化后的数据,json话的对象甚至是一张图片(最大512M)。
  • list是简单的字符串列表,按照列表插入顺序排序。底层是一个链表结构(C语言实现)。
  • set无序,不重复
  • hash,是一个string类型的key和value映射表,特别适合存储实体类对象。
  • zset,也是string类型的元素的集合,不重复。zset的每一个元素都会关联一个分数,redis默认按照分数升序排序集合种元素。

如何存储?


1)关于key的操作命令

keys pattern

  • pattern是通配符
    • ’ * ',匹配0个或多个字符
    • ’ ? ',匹配一个字符
    • ’ [ ] ',匹配中括号中的一个字符
  • 查看数据库实例中的指定的key们。

exist key [key…]

  • 判断key在数据库中是否存在。存在返回1,否则返回0。
  • 判断多个key的时候,返回存在的key的数量

move key index

  • 移动key到index库中

ttl

  • 查看指定key的剩余生存时间
  • time to life ,生存时间
  • 返回值:
    • 如果key不存在,返回-2
    • 如果没有设置key的生存时间,返回-1,表示永远不会过期。

expire key xxxxx[s]

  • 时间单位是秒,s
  • 给指定key设置最大生存时间 。
  • 设置成功返回 1

type key

  • 查看指定key的数据类型。

rename key newkey

  • 重命名指定key

del key [key…]

  • 删除指定的key,返回成功删除的key的个数

2)操作数据结构


Sting

String

set key value

  • 设置key,值是value
  • 如果key已经存在,那么会产生覆盖

setnx key value

  • 不重复key设置,如果存在相同的key,则放弃该次操作
  • 重复了,返回 0

mset k1 v1 k2 v2 [key value…]

  • 批量设置键值对,key和value之间用空格间隔

msetnx k1 v1 k2 v2 [key value…]

  • 批量设置,如果有一个重复的key,就放弃整个操作

get key

  • 获取key

mget k1 k2 k3 [key…]

  • 批量获取key的值,没有返回(nil)

append key value

  • 追加value到key中的值上
  • 返回追加后的value长度
  • 如果key不存在,则创建一个新的key,值为value

strlen key

  • 获取指定key的字符串长度

incr key

  • 对数值型的字符串,执行+1操作
  • 返回+1后的数值大小
  • 如果key不存在,则创建一个值为0的key,然后加1,返回1。
  • 如果可以不是数值类型的,那么报错:ERR value is not an integer or out of range

decr key

  • -1,返回-1后的数值大小

incrby/decrby key offset

  • offset,设置的偏移量,对数值型的key进行+/- offset的操作

getrange key startIndex endIndex

  • [startIndex,endIndex],闭区间截取
  • 截取key对应的字符串从startIndex到endIndex结束的子字符串。下标从0开始
  • 返回截取后的子字符串
  • 注意:下标可以是负数,负下标表示从右往左开始,从-1开始,依次减小。-5 -4 -3 -2 -1[0 1 2 3 4]
  • 例如:name:zhangsan ,getrange name 0 4 == getrange 0 -4

setrange key startIndex value

  • 覆盖key从 strartInde 开始 的内容。包括startIndex
  • 返回覆盖后的字符串长度。

setex key seconds value

  • 设置字符串的同时,设置其最大生存时间

List

List

  • 一个key,对应多个value
  • 每个元素都有下标,下标从0开始,下标也可以用负数表示,-1表示最后一个元素,往前负数越小。

lpsuh key value [ value …]

  • 放入list集合多个value值,底层采用双链表实现。插入顺序采用头插法
  • 每次插入值都是从表头插入

lrange key startIndex endIndex

  • 获取集合[ startIndex,endIndex ]的数值
  • 下标从0开始,支持负下标。-1表示最后一个数。

rpush key elemet element…

  • 每次都从尾部插入数值,尾插。

lpop/rpop key

  • 从左/右删除一个元素,返回删除元素的值。

lindex key index

  • 获取指定key对应集合的index下标处的元素
  • 支持负下标,没有的返回(nil)

llen key

  • 获取指定key对应集合的长度

lrem key count value

  • 当count>0时,从左侧删除集合count个value,否则从右侧删除count个value。
  • 当count==0时,从集合删除所有值为value的元素。

ltrim key strartIndex endIndex

  • 截取[ strartIndex,endIndex ]的元素,组成新的列表,并重新赋值给key。
  • 相当于删除[ strartIndex,endIndex ]外的元素

lset key index value

  • 将指定key对应的集合的index下标处的数值设置为value

linsert key before/after pivot value

  • 将value插入在指定集合的pivot元素之前/后。
  • pivot时第一个遇到的指定数值处,进行插入操作。
Set

Set

  • 单key,多value,无序,不可重复

sadd key value [ value ]

  • 放入指定key对应的集合value,批量插入
  • 返回成功插入的元素个数,重复的值不会被插入

smembers key

  • 获取指定集合中的全部元素,元素顺序无序

sismember key member

  • 判断集合中member元素是否存在,存在返回 1 ,不存在返回 0

scard key

  • 获取集合的长度

srem key member [ member …]

  • 删除集合一个或多个值为member的元素

srandmember key [ count ]

  • 随机从集合中获取count个元素
  • count<0 ,获取的元素可以重复,count>0,获取的元素不重复

smove source dest member

  • 将source集合的member元素移动到dest集合中

sdiff key1 key2 [key…]

  • 获取第一个key1集合中独有的元素,其他集合都没用的元素

sinter key1 key2 [key…]

  • 获取所有集合的交集

sunion key1 key2 [ key…]

  • 获取所有集合的并集
Hash

Hash

  • 单key-{ field-value,field-value,…}

h[m]set key field1 value1 field2 value2 [ field value…]

  • 放入hash集合,多个field-value键值对。

hget key field

  • 获取集合的指定field域的数值。

hmget key field1 field2 [feiled…]

  • 批量获取filed的值

hgetall key

  • 获取集合所有的field-value对

hlen key

  • 获取集合的键值对个数

hdel key field field [ filed…]

  • 删除集合中一个或多个filed

hexists key field

  • 判断集合中是否存在field

hkeys/kvals key

  • 获取集合中所有的key/value值

hincrby[ float ] key field int[ float ]

  • 将集合中field的值进行加int/float运算,可以整数/浮点数加

hsetnx key field value

  • 保护性加入集合中一个field-value
  • 如果已经存在,则放弃本次操作,不会产生覆盖。
zset

Zset

  • 单key,有序,不可重复,每一个元素都有一个score分数
  • 分数可以重复,redis默认按照score升序排序。

zadd key score1 value1 score2 value2 [ score value…]

  • 添加一个或多个分数为score值为value的元素加入集合

zrange key startIndex endIndex [ withscores ]

  • 查看集合[ startIndex,endIndex ] 的元素。0 -1 查看全部
  • 带上withscores,显示分数

z[rev]rangebyscore key min max [ withscore ]

  • 根据分数在[min ,max]范围的元素。withscores决定是否显示在结果集中分数。

zcount key min max

  • 获取集合分数在[ min,max ]的元素个数

zrem key member1 member2 [ member…]

  • 删除集合中一个或多个元素

zcard key

  • 获取集合的元素个数

zrank key member

  • 获取集合member元素的排名,从0开始,分数从小到大

zrevrank key member

  • 分数从大到小,获取集合member元素的排名

zscore key member

  • 获取集合member元素的分数

配置文件redis-conf

  • 配置一些redis服务端运行时的一些参数
  • 如果不使用配置文件,那么redis会按照默认的参数运行
  • 如果使用配置文件,在启动redis服务时必须指定所使用的配置文件

1)关于网络配置

port
  • redis所在端口号,默认是6379
bind
  • 配置客户端连接redis服务时,所能使用的ip地址,默认可以使用redis服务所在主机上任何一个IP都可以;一般情况下,都会配置一个ip,而且通常是一个真实ip

  • 如果配置了port和bind,服务端连接服务器的时候,必须指定ip和port。因为redis-cli 默认使用6379端口号连接。

  • redis-cli -h ip -p port //指定ip和端口号连接服务器
    
  • 同理使用,redis-cli关闭服务器也需要指定IP和port。

tcp-keepalive
  • 设置服务器的保活时间
  • 设置服务器每隔多少秒向客户端发送ACK请求,测试客户端是否挂掉。对于无响应的客户端,则会关闭其连接。
  • 如果设置为0,则不会进行保活检测。

2)常规配置

loglevel
  • 设置日志级别,开发阶段可以使用debug,生产阶段通常设置notice/warning。默认时notice。
  • log4j定义了8个级别的log(除去OFF和ALL,可以说分为6个级别),优先级从高到低依次为:OFF、FATAL、ERROR、WARN、INFO、DEBUG、TRACE、 ALL。

ALL 最低等级的,用于打开所有日志记录。

TRACE designates finer-grained informational events than the DEBUG.Since:1.2.12,很低的日志级别,一般不会使用。

DEBUG 指出细粒度信息事件对调试应用程序是非常有帮助的,主要用于开发过程中打印一些运行信息。

INFO 消息在粗粒度级别上突出强调应用程序的运行过程。打印一些你感兴趣的或者重要的信息,这个可以用于生产环境中输出程序运行的一些重要信息,但是不能滥用,避免打印过多的日志。

WARN 表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。

ERROR 指出虽然发生错误事件,但仍然不影响系统的继续运行。打印错误和异常信息,如果不想输出太多的日志,可以使用这个级别。

FATAL 指出每个严重的错误事件将会导致应用程序的退出。这个级别比较高了。重大错误,这种级别你可以直接停止程序了。

OFF 最高等级的,用于关闭所有日志记录。

  • 如果将log level设置在某一个级别上,那么比此级别优先级高的log都能打印出来。例如,如果设置优先级为WARN,那么OFF、FATAL、ERROR、WARN 4个级别的log能正常输出,而INFO、DEBUG、TRACE、 ALL级别的log则会被忽略。Log4j建议只使用四个级别,优先级从高到低分别是ERROR、WARN、INFO、DEBUG。

  • 从我们实验的结果可以看出,log4j默认的优先级为ERROR或者WARN(实际上是ERROR)。

logfile
  • 设置日志文件
databases
  • 设置redis的数据库个数。默认时16个。

3)安全配置

  • redis,默认客户端登录时不需要密码的,只要指定IP和port就行了
requirepass
  • 默认不设置密码
  • 设置登录redis服务器的密码,设置后客户端登录需要指定密码(-a指定)
protected-mode
  • 安全模式,默认时yes
  • yes/no,当为yes的时候,开启权限和密码等安全验证。

Redis持久化

  • redis提供了持久化策略,在适当的实际采用适当的手段把内存中的数据持久化到磁盘中,每次redis服务启动的时候,都会再次从磁盘中记载这些数据。

RDB策略

  • 在指定的时间间隔内,redis服务执行指定次数的写操作后,会自动触发一次持久化操作。

  • RDB策略时redis的默认策略,redis服务开启的时候,这种持久化策略就默认开启了。

  • 默认策略是:

    • save

    • save 900 1		//15分钟,执行1此写操作
      save 300 10		//5分钟,10次
      save 60 10000	//1分钟,1万次写操作
      
dbfilename
  • 数据持久化到磁盘后,保存数据的文件名称。
  • 默认是dump.rdb,也可以自己配置。
dir
  • 持久化后保存数据的文件所在的目录。

  • 默认是./ 就是redis启动的目录。

  • 修改文件名称,save,dir都是在redis.conf配置文件中配置的。

AOF策略

  • 采用操作日志来记录每一次的写操作,每次启动redis服务的时候,都会重新执行一边操作日志中的指令。
  • 效率很低,redis默认不开启。
appendonly
  • 配置AOF是否开启。yes/no
appendfilename
  • AOF策略的操作日志文件名称。

  • # At the date of writing these commands are: set setnx setex append
    appendonly no
    # The name of the append only file (default: "appendonly.aof")
    appendfilename "appendonly.aof"
    

事务

  • 把一组数据库操作放在一起执行,保证操作的原子性,要么同时成功,要么同时失败。

redis事务

  • 允许把一组数据库操作(redis命令)放在一起执行,把命令进行序列化,然后一起执行吧,保证部分原子性。
  • 他不能完全保证原子化操作,只能保证部分原子性。
1)multi:
  • 用来标记一个事务的开始。
  • 单独执行这个命令表示开启事务。
  • 之后执行的命令都会加入命令队列,等待exec,然后统一执行。
2)exec:
  • 用来事务队列中所有的命令

部分原子性

  • 1)如果一组命令中,在压入命令队列的过程中,发生了致命错误,那么整个队列的命令都不会执行。比如,在压入队列过程中,发现了命令语法错误,就会导致整个队列命令的不执行。
  • 2)如何命令在压入过程中正常,而在执行过程中发送错误。那么只会影响发送错误的命令,而不会影响其他的命令。
  • 3)编译过程错误具有原子性,而运行过程错误不具有原子性。
3)discard :
  • 放弃队列中的命令。弹出队列中的命令,不再执行。

  • 清除所有已经压入队列的命令,并且结束整个事务。

  • multi
    set k1 v1
    set k2 v2
    discard 	//放弃前面的命令,并结束事务。
    
4)防止并发修改 watch
  • mysql中:乐观锁

    • 对重要的表中的记录都加上一个“锁”字段,用来防止并发修改同一条记录。

    • id balance version(锁字段)
      
      //修改余额的操作
      update table set balacne=balance-countMoney,version=vsersoin+1
      where version=先前查出的version
      
    • 如果version和先去取出的不一样,那么此次操作将不会执行。每次执行成功都会修改veriosn。

    • 只有version和修改前取出的version一致的时候才会执行修改操作。保证一次只有一个用户修改一个记录。

  • redis中:watch key命令

    • 监控某一个键,在事务的执行时,如果这个键发生了变化,则本次事务的放弃执行,所有命令都不会执行。

    • 监控的键可能会被其他客户端在本客户端压入事务命令队列的时候,修改了这个键,那么本客户端的事务将会被放弃执行。

    • //客户端1
      >set balance 100
      >set balance 200
      >set version 1
      >watch version		//开启监控
      >multi			//开启事务
      	decrby balcane 80
      	incr version
      >exec
      
      //客户端2
      >incr verison    //另一个客户端修改了监控的键version
      
      //结果:在客户端1中
      >exec
      (nil)
      
    • 就类似乐观锁,在开启监控的时候取出这个键version,在exec的时候,检查当前的version和之前的是否相同,如果不同,则放弃当前事务。

5)unwatch
  • 放弃监控所有的键
  • unwatch //放弃所有监控的键
笔记
  • redis的命令是具有隔离性的,每个客户端之间互不影响,每个客户端执行命令的时候,不会被其他客户端发来的命令打断。
  • 除非在使用watch监控的时候,其他客户端修改监控的键,会导致监控该键的客户端事务的放弃。

消息的订阅和发布

  • 客户端之间的通信
  • redis客户端订阅频道,发布者往频道上发布消息。这样所有订阅该频道的客户端都会收到消息

subscribe

  • subscribe ch1 ch2 …

  • 订阅一个或多个频道。

  • psubscribe:支持频道使用通配符

publish

  • publish ch message
  • 向指定频道发生message消息。

更好的消息订阅和通信:activeMQ2,Rabbit

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值