Redis 从精通到陌生

1.1redis 是什么

Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。

1.2NoSQL介绍

NoSQL,泛指非关系型的数据库,随着物联网web2.0网站的兴起,传统的关系数据库在应付web2.0网站,特别是超大规模和高并发的SNS类型的web2.0网站已经力不从心,暴露出很多难以克服的问题,而非关系型的数据库则由其本身的特点得到了非常迅速的发展。NoSQL数据库的产生就是为了解决大规模数据集合多重种类带来的挑战,尤其是大数据应用难题

1.2.1 NoSQL数据库的四大分类

键值(key-value)存储数据库
这一数据库主要会使用到一个哈希表,这个表中有一个特定的键和一个指针指向特定的数据,Key/Value模型对于IT系统来说的优势在于简单,容易部署,但是对部分键进行查询或者跟新时,效率就会低下,例如:Tokyo,Redis,Oracle BDB。

列存储数据库
这部分数据库用来应对分布式存储的海量数据,键依然存在,但是他们的特点是指向多个列。这些列是由家族来安排的。如HBase,Riak。

文档型数据库
“文档”是文档数据库中的主要概念。此类数据库可存放并获取文档,其格式可以是XML、JSON、BSON等,这些文档具备可述性(self-describing),呈现分层的树状结构(hierarchical tree data structure),可以包含映射表、集合和纯量值。数据库中的文档彼此相似,但不必完全相同。文档数据库所存放的文档,就相当于键值数据库所存放的“值”。文档数据库可视为其值可查的键值数据库。如CouchDB,MongoDb

图形数据库
图数据库源起欧拉和图理论,也可称为面向/基于图的数据库,对应的英文是Graph Database。图数据库的基本含义是以“图”这种数据结构存储和查询数据,而不是存储图片的数据库。它的数据模型主要是以节点和关系(边)来体现,也可处理键值对。它的优点是快速解决复杂的关系问题。如Neo4j

总结:NoSQL数据库在以下几张情况比较适用:
1.数据模型比较简单,需要灵活性
2.需要灵活性更强的IT系统;
3.对数据库性能要求较高;
4.不需要高度的数据一致性;
5.对于规给定key,比较容易映射复杂值的环境

Redis 与其他key-value缓存产品有以下三个特点:
1.支持数据的持久化,可以将内存中的数据保存在磁盘中,重启的时候可以再次加载进行使用。

2.不仅仅支持简单的key-value类型的数据,同时提供list,set,zset,hash等数据结构再次加载使用。

3.Redis支持数据的备份,集群等高可用功能。

1.3特点

1.性能极高-因为是由 C语言,数据放在内存中使用快
2.丰富的数据类型-支持String,List,Hash,Set及Ordered Set数据类型操作
3.原子性-所有操作都是原子性的
4.丰富的特性

Redis是一个简单的,高效的,分布式的,基于内存的缓存工具。
架设好服务器后,通过网络连接,提供Key-Value式缓存服务。
简单,是Redis突出的特色。
简单可以保证核心功能的稳定和优异。

Redis总结

redis单个key存入512M大小
redis 支持多种类型的数据结构
redis是单线程 原子性
redis可以持久化,因为使用了RDB和AOF机制
redis支持集群 而且redis默认支持16个库(0-15)
redis还可以做消息队列比如聊天室

2.Redis 安装

2.1.window

window安装

2.2.linux

因为Redis 是C语言编写的所以需要安装gcc(GCC编译器是Linux下最常用的编译器)

2.2.1.安装gcc

首先确保root登录,然后Linux需要联外网

yum -y install gcc automake autoconf libbtool make

注意:运行yum时出现/var/run/yum.pid已被锁定,pid为XXX的另一个程序正在运行问题解决

rm-f/var/run/yum.pid

2.2.2.安装Redis

1.wget http://download.redis.io/releases/redis-4.0.1.tar.gz
2.tar zxvf redis-4.0.1.tar.gz (解压)
3.cd redis-4.0.1
4.(编译) make 或make  MALLOC=libc
5.make PREFIX=/usr/local/redis install
(安装编译后的文件) 安装到指目录: 
注意:PREFIX必须大写、同时会自动为我们创建redis目录,并将结果安装此目录

安装不成功请看这里

3启动Redis

3.1启动Redis服务

进入对应的安装目录 /user/local/redis
执行命名: ./bin/redis-server

3.2启动Redsi客户端命令

redis-cli -h ip地址 -p 端口 (ip默认本机 端口默认6379 默认可不填)
突出客户端命令: Ctrl1+c

3.3检测服务端是否启动

redis-cli
127.0.0.1:6379> ping
PONG

4.Linux配置Redis

Redis的配置文件位于Redis安装目录下,文件名为redis.conf(windows下为redis.windows.conf)

4.1配置Redis

Linux环境下
Redis端口号或默认启动配置。但一般我们都会通过手动配置完成回到根目录找到解压文件中的redis.conf

theblind@LAPTOP-2OT43UL7:~$ cd redis-4.0.1
theblind@LAPTOP-2OT43UL7:~/redis-4.0.1$  cp  redis.conf /usr/local/redis
cp: cannot create regular file '/usr/local/redis/redis.conf': Permission denied(要先进入root)
theblind@LAPTOP-2OT43UL7:~/redis-4.0.1$  sudo -s(进入root)
[sudo] password for theblind:
root@LAPTOP-2OT43UL7:~/redis-4.0.1#  cp redis.conf /usr/local/redis
root@LAPTOP-2OT43UL7:~/redis-4.0.1# cd /usr/local/redis
root@LAPTOP-2OT43UL7:/usr/local/redis# ll
total 60
drwxr-xr-x 1 root root  4096 Jun 10 11:08 ./
drwxr-xr-x 1 root root  4096 Jun  8 11:29 ../
drwxr-xr-x 1 root root  4096 Jun  8 11:29 bin/
-rw-r--r-- 1 root root   157 Jun  8 13:30 dump.rdb
-rw-r--r-- 1 root root 57764 Jun 10 11:08 redis.conf
root@LAPTOP-2OT43UL7:/usr/local/redis#

使用less -mn redis.conf可以查看文件内容 按空格翻页 输入/可以查找如/port Ctrl+z 出去
使用vim redis.conf 文本编译器打开 可以对其进行修改

保存命令
按ESC键 跳到命令模式,然后:
:w 保存文件但不退出vi
:w file 将修改另外保存到file中,不退出vi
:w! 强制保存,不推出vi
:wq 保存文件并退出vi
:wq! 强制保存文件,并退出vi
q: 不保存文件,退出vi
:q! 不保存文件,强制退出vi
:e! 放弃所有修改,从上次保存文件开始再编辑

Windows环境下
在这里插入图片描述

redis.conf 配置文件详解
redis.conf 配置项说明如下:

  1. Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程
    daemonize no

  2. 当Redis以守护进程方式运行时,Redis默认会把pid写入/var/run/redis.pid文件,可以通过pidfile指定
    pidfile /var/run/redis.pid

  3. 指定Redis监听端口,默认端口为6379,为什么选用6379作为默认端口,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字
    port 6379

  4. 绑定的主机地址
    bind 127.0.0.1
    5.当 客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能
    timeout 300

  5. 指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose
    loglevel verbose

  6. 日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给/dev/null
    logfile stdout

  7. 设置数据库的数量,默认数据库为0,可以使用SELECT 命令在连接上指定数据库id
    databases 16

  8. 指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合
    save
    Redis默认配置文件中提供了三个条件:
    save 900 1
    save 300 10
    save 60 10000
    分别表示900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改。

  9. 指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大
    rdbcompression yes

  10. 指定本地数据库文件名,默认值为dump.rdb
    dbfilename dump.rdb

  11. 指定本地数据库存放目录
    dir ./

  12. 设置当本机为slave服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步
    slaveof

  13. 当master服务设置了密码保护时,slave服务连接master的密码
    masterauth

  14. 设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH 命令提供密码,默认关闭
    requirepass foobared

  15. 设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回max number of clients reached错误信息
    maxclients 128

  16. 指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理 后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区
    maxmemory

  17. 指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no
    appendonly no

  18. 指定更新日志文件名,默认为appendonly.aof
    appendfilename appendonly.aof

  19. 指定更新日志条件,共有3个可选值:
    no:表示等操作系统进行数据缓存同步到磁盘(快)
    always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全)
    everysec:表示每秒同步一次(折中,默认值)
    appendfsync everysec

  20. 指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中(在后面的文章我会仔细分析Redis的VM机制)
    vm-enabled no

  21. 虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享
    vm-swap-file /tmp/redis.swap

  22. 将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0
    vm-max-memory 0

  23. Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值
    vm-page-size 32

  24. 设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。
    vm-pages 134217728

  25. 设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4
    vm-max-threads 4

  26. 设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启
    glueoutputbuf yes

  27. 指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法
    hash-max-zipmap-entries 64
    hash-max-zipmap-value 512

  28. 指定是否激活重置哈希,默认为开启(后面在介绍Redis的哈希算法时具体介绍)
    activerehashing yes

  29. 指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件
    include /path/to/local.conf

  30. Redis中的内存维护策略

redis作为优秀的中间缓存件,时常会存储大量的数据,即使采取了集群部署来动态扩容,也应该即使的整理内存,维持系统性能。

在redis中有两种解决方案,
一是为数据设置超时时间,

二是采用LRU算法动态将不用的数据删除。内存管理的一种页面置换算法,对于在内存中但又不用的数据块(内存块)叫做LRU,操作系统会根据哪些数据属于LRU而将其移出内存而腾出空间来加载另外的数据。

1.volatile-lru:设定超时时间的数据中,删除最不常使用的数据.

2.allkeys-lru:查询所有的key中最近最不常使用的数据进行删除,这是应用最广泛的策略.

3.volatile-random:在已经设定了超时的数据中随机删除.

4.allkeys-random:查询所有的key,之后随机删除.

5.volatile-ttl:查询全部设定超时时间的数据,之后排序,将马上将要过期的数据进行删除操作.

6.noeviction:如果设置为该属性,则不会进行删除操作,如果内存溢出则报错返回.
volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键
allkeys-lfu:从所有键中驱逐使用频率最少的键
https://www.jianshu.com/p/c8aeb3eee6bc

自定义配置Redis

1.进入对应的暗转目录 /usr/local/redsi
修改 redis。conf 配置文件 vim redis.conf(进入命令模式 修改属性)
2.Redis配置中必须修改的:
daemonize no 修改为 daemonize yes
bind 127.0.0.1 注释掉
requirepass 设置密码

Redis采用的是单进程多线程的模式。
当redis.conf中选项daemonize设置称yes时,代表开启进程守护模式。该模式下,redis会在后台运行,并将进程pid号写入至redis.conf选项中,此时redis将一直运行,除非手动kill该进程。
当daemonize选项设置成no时,当前界面将进入redis的命令行界面,exit强制退出或者关闭连接工具都会导致redis进程退出

5.Redis启动

5.1服务端启动

root@LAPTOP-2OT43UL7:/usr/local/redis# ./bin/redis-server ./redis.conf
75:C 10 Jun 14:51:56.694 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
75:C 10 Jun 14:51:56.695 # Redis version=4.0.1, bits=64, commit=00000000, modified=0, pid=75, just started
75:C 10 Jun 14:51:56.696 # Configuration loaded

5.2客户端启动

本地客户端启动

root@LAPTOP-2OT43UL7:/usr/local/redis# ./bin/redis-cli -a 123456
127.0.0.1:6379>

远程服务上执行

redis-cli -h host -p port -a password
redis-cli –h IP地址 –p 端口 –a 密码

使用ps命令查看进程的状态,并不动态连续

ps -ef | grep -i redis 

Redis关闭

第一种关闭方式:(断电,非正常关闭。容易丢失数据)
查询 PID ps -ef | grep -i redis

kill -9 pid

第二种关闭方式:(正常关闭,数据保存)

./bin/redis-cli shutdown 

127.0.0.1:6379> shutdown
not connected>

6.Redis命令描述

6.1.什么是Redis命令描述

Redis命令描述用于redis服务上执行操作。

Redis支持五种数据类型:string(字符串),hash(哈希),list,set,以及zset(sorted set)等

6.2.Redis键 key

Redis 键命令用于管理redis的键

DEL key
该命令用于在 key存在时删除该key。

127.0.0.1:6379> set ss "s"
OK
127.0.0.1:6379> del ss
(integer) 1

DUMP key
返回被序列化的值。

127.0.0.1:6379> set ss "s"
OK
127.0.0.1:6379> dump ss
"\x00\x01s\b\x00\xd3J\xda\x13\xcb^\xb0\xaf"

EXISTS key
检查指定的key是否存在。

127.0.0.1:6379> set ss "s"
OK
127.0.0.1:6379> exists ss
(integer) 1(存在)
127.0.0.1:6379> exists s
(integer) 0(不存在)

EXPIRE key
为指定key设置过期时间(单位秒)。

PEXPIRE key
为指定key设置过期时间(单位毫秒)。

127.0.0.1:6379> expire ss 60
(integer) 1

TTL key
以秒为单位,返回指定的key的剩余生存时间。(-1表示永久 -2 表示失效)

127.0.0.1:6379> ttl ss
(integer) 57

PTTL key
以毫秒为单位,返回指定的key的剩余生存时间。

127.0.0.1:6379> pttl ss
(integer) 26904

PERSIST key
移除指定key的过期时间,key将持久保存。

127.0.0.1:6379> expire ss 60
(integer) 1
127.0.0.1:6379> persist ss
(integer) 1
127.0.0.1:6379> ttl ss
(integer) -1

KEYS pattern
根据pattern查找指定的key。
通配符 :
* 代表所有
* ? 表示代表一个字符

127.0.0.1:6379> keys *
1) "ss"
127.0.0.1:6379> set a:1 "ss"
OK
127.0.0.1:6379> keys a:?
1) "a:1"
127.0.0.1:6379> keys *
1) "a:1"
2) "ss"

RANDOMKEY
从当前数据库随机返回一个key

127.0.0.1:6379> RANDOM KEY(错误写法)
(error) ERR unknown command 'RANDOM'
127.0.0.1:6379> randomkey
"a:1"

RENAME key newkey
修改Key的名称

127.0.0.1:6379> rename a:1 a:2
OK
127.0.0.1:6379> keys *
1) "ss"
2) "a:2"

TYPE key
返回指定key值的类型

127.0.0.1:6379> type ss
string

MOVE key db Redis是有多个数据库的
将指定key从当前数据库移动到指定db中

127.0.0.1:6379> move ss 1
(integer) 1
127.0.0.1:6379> keys *
1) "a:2"
127.0.0.1:6379> select 1(选择当前的数据库)
OK
127.0.0.1:6379[1]> keys *
1) "ss"

DEL key
该命令用于在 key存在时删除该key。

6.3.应用场景

EXPIRE key seconds
1.限时的优惠活动信息
2.网站数据缓存(对于一些需要定时更新的数据,例如:积分排行榜)
3.手机验证码
4.限制网站访客访问频率(1分钟访问10次)

6.4.Keyd 命名规范

redis 单个key存入 512m大小

1.key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且后降低查找的效率;
2.key也不要太短,太短的话,key的可读性会降低
3.在一个项目中,key最好使用统一的命名规范,例如user:123:user;

为什么命名要这样 user:123:user?
假如有一个Users表 它有以下信息
id ,name,age

命名
user:1:name xx (1代表id)
user:2:name xxx
为什么不用下划线 user_1_name xx
因为有可能列名就叫u_id,u_name什么的,怕你搞混。

7.Redis 数据类型

7.1 String

7.1.1 简介

string 是redis最基本的类型,一个key对应一个value。
string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象。
string类型是Redis最基本的数据类型,一个键最大能存储512MB。
二进制安全是指,在传输数据时,保证二进制数据的信息安全,也就是不被篡改,破译等,如果被攻击,能够及时检测出来
二进制安全特点:
1.编码,解码发生在客户端完成,执行效率高
2.不需要频繁的编解码,不会出现乱码

7.1.2 String命令

赋值语法
SET key value(注意KEY是区分大小写的)
SET 命令用于设置给定key的值。如果key已经存储值,SET就覆写酒值,而且是无视旧值。
SETNX key value
只有key不存在的时设置的值。如果存在就不起作用

127.0.0.1:6379> setnx a "a"
(integer) 1
127.0.0.1:6379> setnx a  "aa"
(integer) 0

MSET key value(mony(多个) set)
同时设置一个或多个 key-value

127.0.0.1:6379> mset s "ss" ss "aa"  sss  "sss"
OK
127.0.0.1:6379> keys *
1) "ss"
2) "s"
3) "sss"

取值语法
GET key_name
GET命令用来获取指定key的值。如果key不存在,返回nil。
如果key存储的值不是字符串类,返回一个错误。
GETRANGE key start end (get range(范围))
作用就是截取字符串,start 开始下标, end 结束下标 ,下标从0开始

127.0.0.1:6379> set range "javapp"
OK
127.0.0.1:6379> getrange range 0 3
"java"

GETBIT key offset
对key所存储的字符串值,获取指定偏移量上的位

MGET key【key2】
获取一个或者多个给定key的value

127.0.0.1:6379> mget ss s ss
1) "aa"
2) "ss"
3) "aa"

GETSET key value
先获取key的value然后在设置新的value

127.0.0.1:6379> set a "aa"
OK
127.0.0.1:6379> getset a "haha"
"aa"
127.0.0.1:6379> get a
"haha"

STRLEN key(string lenght 字符串长度)
返回key所储存的字符串值的长度

127.0.0.1:6379> strlen a
(integer) 4

删除语法:
DEL key
删除指定的key,返回值为数字类型

127.0.0.1:6379> strlen a
(integer) 4

自增/自减:
INCR key
将key中存储的数字加1并返回,如果key不存在,那么key的值会被初始化为0,然后在执行incr操作

127.0.0.1:6379> incr id
(integer) 1
127.0.0.1:6379> get id
"1"
127.0.0.1:6379> incr id
(integer) 2

自增:INCRBY key 增量值
incrby将key中存储的数字加上指定的增量值并返回

127.0.0.1:6379> incrby id 66
(integer) 68

自减:DECR key 或者 DECRBY key 减值
与上面相似
字符串拼接:APPEND key value
将value添加到指定key的末尾,如果不存在,为其赋值
返回字符串长度

127.0.0.1:6379> setnx sss "ss"
(integer) 1
127.0.0.1:6379> append sss "66"
(integer) 4
127.0.0.1:6379> get sss
"ss66"

好奇的宝宝应该都试过写入中文,当你get时候就出现类似于\xe6\x88\x91\xe5\x8f\xe5\xa5\xbd\xe5\xb8\x85
解决办法

127.0.0.1:6379> append what "我好帅"(明明我好帅,可是别人却get不到)
(integer) 11
127.0.0.1:6379> get what
"\xe6\x88\x91\xe5\x8f\xe5\xa5\xbd\xe5\xb8\x85"

7.1.3.应用场景:

1.String 通常用于保存单个字符串或JSON字符串数据
2.因String是二进制安全的,所有你完全可以吧一个图片的内容作为字符串来存储
3.计数器(常规key-value 缓存应用。常规计数:微博数,粉丝数)
incr等指令本身就具有原子操作的特性,所以完全可以利用redis的incr,incrby,decr,decrby等来实现原子计数,可以解决高并发的安全问题

7.2.哈希(Hash)

7.2.1.简介

Redis hash是一个string类型的field和value的映射表。hash特别适合用于存储对象。Redis中每个hash可以存储2的32次方-1键值对(40多亿)
可以看成具有key和value的MAP容器,该类型非常适合于存储值对象的信息。

7.2.2.Hash命令

赋值语法:
HSET key field value
为指定的key,设置field和value

127.0.0.1:6379> hset user:1 id 1
1

HMSET key field value 【field1 value1】
同时将多个field-value设置到哈希表key中

127.0.0.1:6379> hset user:1 name  "ww"  age  11

取值语法:
HGET key field
获取存储在HASH中的值,根据field得到value
HMGET key field[field1]
获取key所有给定字段的值
HGETALL key
返回hash表中所有的字段和值

HKEYS key
获取所有哈希表的字段
HLEN key
获取哈希表中字段数量

删除语法
HDEL key field1[dield2]
删除一个或者多个哈希表字段

其它语法:
HSETNX key field value(setnx)
只有在字段field不存在时,设置哈希表字段的值
HINCRBY key field increment(incrby)
为哈希表key中的指定字段的整数值加上增量increment。
HINCRBYFLOAT key field increment
为哈希表key中的指定字段的浮点数值加上增量increment。

HEXISTS key field(exists)
查看哈希表key中指定的字段是否存在

7.3.Java连接Redis

在官方网站列一些Java客户端访问,有:Jedis/Redisson/Jredis/JDBC-Redis等,其中官方推荐使用Jedis和Redisson。我们常用Jedis
开始之前要把redis 服务开启,在项目中导入Jedis的jar包

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

7.3.1.开启端口防火墙

关于防火墙这块有大佬吗?我是ubantu系统,ubuntu默认是没有防火墙的,但是我显示有 ,可是不能操作

root@LAPTOP-2OT43UL7:~# sudo whereis iptables
iptables: /sbin/iptables /usr/share/iptables /usr/share/man/man8/iptables.8.gz

7.3.2.Java操作Redis设置密码

如何查看ip
ifconfig(windows中是ipconfig)

root@LAPTOP-2OT43UL7:/usr/local/redis# ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.1.10  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 240e:361:4a4:8800:d887:6792:af77:b8f4  prefixlen 64  scopeid 0x0<global>
        inet6 240e:361:4a4:8800:29a3:6d61:e30d:fb25  prefixlen 128  scopeid 0x0<global>
        inet6 fe80::d887:6792:af77:b8f4  prefixlen 64  scopeid 0x0<global>
        ether 00:e0:4c:6b:bb:6e  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
	public static void main(String[] args) {
		// TODO Auto-generated method stub
 String host="192.168.1.10";
		 int port=6379;
		Jedis jedis=new Jedis(host,port);
		jedis.auth("123456");
		System.out.println(jedis.ping());
		
	}

7.3.2.Java Jedis连接池优化

我都可以用Jedis直接连了,还用什么连接池,这不麻烦吗?
数据库连接是非常宝贵的系统资源,要经过很多步骤才可以连上,用完关,过一会用的时候又要创,这样效率就很低了。
连接池的基本原理是,先初始化一定的数据库连接对象,并且把这些连接保存在连接池中。当程序需要访问数据库的时候,从连接池中取出一个连接,数据库操作结束后,再把这个用完的连接重新放回连接池。

public static void main(String[] args) {
		// TODO Auto-generated method stub
		JedisPoolConfig poolConfig=new JedisPoolConfig();//连接池配置信息
		poolConfig.setMaxTotal(5);//最大连接数
		poolConfig.setMaxIdle(1);//最大空闲数
        String host="192.168.1.10";
		int port=6379;
		JedisPool pool=new JedisPool(poolConfig,host,port);//连接池
	
		Jedis jedis=pool.getResource();//从池子中获取Jedis
		jedis.auth("123456");
		System.out.println(jedis.ping());
		
	}

在实际项目中JedisPoolConfig和JedisPool 只需要创建一个次所有我们一般创建一个工具类

public class RedisPoolUtils {
	
	private static JedisPool pool;
	static
	{
		JedisPoolConfig PoolConfig=new JedisPoolConfig();
		PoolConfig.setMaxTotal(5);
		PoolConfig.setMaxIdle(1);
		String host="192.168.1.10";
		int port=6379;
	    pool=new JedisPool(PoolConfig,host,port);
	}
	
	
	public static Jedis getJedis()
	{
		Jedis jedis=pool.getResource();
		jedis.auth("123456");
		return jedis;
	}
	
	public static void close(Jedis jedis)
	{
		jedis.close();
		
	}
	
	
	

}

操作一下

@Test
	public void t3()
	{
		Jedis jedis=RedisPoolUtils.getJedis();
		int id=1;//假如前端传来一个id让你查user信息
		String key=User.getKeyName()+""+id;
		if(jedis.exists(key))
		{
			Map<String,String> hash=jedis.hgetAll(key);
		User u=new User();
		u.setId(Integer.parseInt(hash.get("id")));
		u.setName(hash.get("name"));
		u.setAge(Integer.parseInt(hash.get("age")));
			System.out.println("从Redis数据库中查询"+u.getName());
			
		}else
		{
			//从mysql数据库中查并赋值到redis中
			User u=new User();
			u.setId(id);
			u.setName("xx");
			u.setAge(11);
			Map<String,String> hash=new HashMap();
			hash.put("id", u.getId()+"");
			hash.put("name", u.getName());
			hash.put("age", u.getAge()+"");
			jedis.hmset(key, hash);
			
			System.out.println("从mysql数据库中查查询"+u);
		}
		
		
		
	RedisPoolUtils.close(jedis);
		




		
		
		
		
	}

有同学肯定会说了:我去这么繁琐的吗?
来人把这个同学拖下去
很全的RedisPoolUtil
事实上现在一般都用框架开发不要自己写
在这里插入图片描述

7.4.RedisTemplate(redis模板)

7.4.1.简介

Spring data提供了RedisTemplate模板,它辅助了redis连接池管理的逻辑,
业务代码无须,关系获取,释放连接逻辑。
spring redis同时支持Jedis,Jredis,rjc客户端操作。

7.4.2.Spring data 使用RedisTemplate模板

1.Redis和Spring整合
先导jar包,放到你的pom.xml中

<!--springdata整合redis-->
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-redis</artifactId>
      <version>1.8.6.RELEASE</version>
    </dependency>
    <!--jedis客户端需要依赖jar Redis-->
    <dependency>
      <groupId>redis.clients</groupId>
      <artifactId>jedis</artifactId>
      <version>2.4.2</version>
    </dependency>

2.对应实体Bean进行序列化操作
为什么要序列化

public class User implements Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

3.编写相应配置文件
新建一个Spring-Redis.xml和redisconf.properties
redisconf.properties放一下一些信息

redis.host=127.0.0.1
redis.port=6379

redis.pwd=123456

redis.database=0
redis.timeout=1000
redis.userPool=true
redis.pool.maxIdle=100#最大空闲数
redis.pool.minIdle=10#最小空闲数
redis.pool.maxTotal=200#连接池的最大连接数。0表示无限制,也就是pool里面放多少个jedis
redis.pool.maxWaitMillis=10000#建立连接等待的最大时间,如果超过此时间将报异常,-1表示无限制
redis.pool.minEvictableIdleTimeMillis=300000#连接的最小空闲时间默认1800000毫秒
redis.pool.numTestsPerEvictionRun=10#每次释放连接的最大数目,默认3
redis.pool.timeBetweenEvictionRunsMillis=30000#逐出扫描的时间间隔(毫秒),如果为负数,则不运行逐出线程,默认为-1
redis.pool.testOnBorrow=true#从池中取出连接前进行检验,如果检验失败,则从取另一个
redis.pool.testOnReturn=true#在return给pool时,是否提前进行检验;

redis.pool.testWhileIdle=true#在空闲时检查有效性,默认false

Spring-Redis.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
   
       ">

	<context:property-placeholder location="classpath:redis.properties"/>

<!--1配置连接池信息-->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <!--最大连接数-->
	<property name="maxTotal" value="${redis.pool.maxTotal}" />
	 <!--MaxIdle-->
<property name="maxIdle" value="${redis.pool.maxIdle}"/>

</bean>
<!--Spring 整合Jedis(Redis)-->
<bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">
<property name="hostName" value="${redis.host}"/>
<property name="port" value="${redis.port}"/>
	<property name="password" value="${redis.pwd}"/>
	<property name="poolConfig" ref="jedisPoolConfig"/>
</bean>

	<bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">
	<property name="connectionFactory" ref="jedisConnectionFactory"/>
	</bean>


</beans>   

接下来用单元测试看一下
如何创建单元测试



@Resource
    RedisTemplate<String,String> redisTemplate;


    public String getString(String key)
    {
   ValueOperations<String,String> string= redisTemplate.opsForValue();
 if(redisTemplate.hasKey(key))
 {
     System.out.println("在redis中取出并返回");
return string.get(key);
 }else
     {
         String result="巴拉巴拉";
         string.set(key,result);
         System.out.println("在MYSQL数据库中取出并返回");
         return result;
     }

    }





-----------------------------------------------------------------------------------------------------------------------------------



 @Test
    public void t1()
    {
        ClassPathXmlApplicationContext apc=new ClassPathXmlApplicationContext("applicationContext.xml","spring-redis.xml");
       userHtSer us= apc.getBean(userHtSer.class);
       String key="xx";
        System.out.println(us.getString(key));

    }

7.5.list(列表)

7.5.1.简介

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

7.5.2.命令

赋值语法
LPUSH key value1【value2】
将一个或者多个值插入到列表头(左侧)
RPUSH key value1【value2】
将一个或者多个值插入到列表尾(右侧)
LPUSHX key value (回想一下string类型中SETNX 与它相反)
将一个值插入到已存在的列表头,如果列表不存在,操作无效
RPUSHX key value
将一个值插入到已存在的列表尾,如果列表不存在,操作无效

取值语法:
LIEN key
获取列表的长度

LINDEX key index
通过索引获取列表元素

LRANGE key start stop
获取指定范围内的元素
其中 0表示列表第一个元素,1是第二个…,-1表示最后一个元素,-2是倒数第二个

删除语法:
LPOP key(pop有弹出的意思)
移出并获取列表的第一个元素(从表头开始)

RPOP key
移出并获取列表的最后一个元素(从表尾开始)

BLPOP key1[key2] timeout(单位秒哦 Block阻塞的意思)
移出并获取列表的第一个元素(从表头开始),如果列表没有元素就会阻塞列表(没错就像卡了一样。。)直到等待超时或发现可弹出元素为止

BRPOP key1[key2] timeout(单位秒哦)
移出并获取列表的最后一个元素(从表尾开始),如果列表没有元素就会阻塞列表直到等待超时或发现可弹出元素为止,时间到后返回nil

LTRIM key start stop(trim 修剪)
对一个列表进行修剪,只保留区间内的。

修改语法:
LSET key index value
通过索引设置列表元素的值
LINSERT key BEFORE|AFTER pivot value
在列表pivot元素前(before)或者后面(after
)插入元素 如果这个元素不存在,则无效
高级语法
RPOPLPUSH source destination
移除列表的最后一个元素,并将该元素添加到另一个列表并返回

BRPOPLPUSH source destination timeout
移除列表的最后一个元素,并将该元素添加到另一个列表并返回,如果列表没有元素会阻塞列表直到等待超时或者发现可弹出元素为止。

7.5.3.应用场景

项目常应用于:1.对数据量大的集合数据删减2.任务队列

1.对于数据量大的集合数据删减
列表数据显示,关注列表,粉丝列表,留言评价等。。分页,热点新闻(Top5)等
2.任务队列
list通常来实现一个消息队列,可以确保先后顺序,不必像MySql那样需要通过ORDER BY 来进行排序

任务队列介绍(生产者和消费者模式)
在处理Web客户端发送的命令请求时,某些操作的执行时间可能别我们预期的更长一些,通过将待执行任务的相关信息放入队列中,并在之后对队列进行处理,用户可以推迟执行那些需要一段时间才能完成的操作,这种将工作交给任务处理器执行的做法称为任务队列

常用案例:订单系统的下单流程,用户系统登录注册短信等

7.6.Set

7.6.1.简介

Redis 的Set是String 类型的无序集合。 集合成员是唯一的,这就意味着集合中不能出现重复的数据

7.6.2.命令

赋值语法:
SADD key member1【member】
向集合中添加一个或多个成员

取值语法:
SCARD key
获取集合的成员数
SMEMBERS key
返回集合中所有的成员
SISMEMBER key member
判断member元素是否是集合key的成员
SRANDMEMBER key【count】
返回集合中一个或者多个随机数

删除语法:
SREM key member1【member2】
移除集合中一个或多个成员
SPOP key【count】
移除并返回集合中的一个随机元素
SMOVE source destination member
将member从source集合移动到destination集合

差集语法:
SDIFF key1 【key2】(以左侧为主进行判断)
返回给定所有集合的差集
SDIFFSTORE destination key1【key2】
返回给定所有集合的差集并存储(store)destination(目的地)中
交集语法:
SINTER key1 [key2]
返回给定所有集合的交集(共享数据)
SINTERSTORE destination key1 [key2]
返回给定所有集合的交集并存储(store)destination(目的地)中

并集语法:
SUNION key1 [key2]
返回所有给定集合的并集
SUNIONSTORE destination key1 【key2】
返回所有给定集合的并集并储存到destination集合中

7.7.ZSET(有序集合)

7.7.1.简介

1.Redis zset与set一样都是string类型元素的集合,且不允许重复的成员。
2.不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
3.有序集合的成员是唯一的,但分数却可以重复。
4.集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1);
== Redis 的ZSet是有序,且不重复的==

7.7.2.命令

赋值语法:
ZADD key score1 member1 【score 2 member2 】

向有序集合添加一个或者多个成员,或者跟新已存在的分数

127.0.0.1:6379> zadd zsetjh  10 java 20 html

取值语法:
ZCARD key
获取有序集合的成员数
ZCOUNT key min max
计算在有序集合中指定区间分数的成员数
ZRANK key member
返回指定成员的索引
ZRANGE key start stop 【WITHSCORES】
通过索引区间返回有序集合指定区间内的成员(低到高)
加上WITHSCORES 则 member score都返回

ZRERANGE key start stop 【】(reverse反转)
通过索引区间返回有序集合指定区间内的成员(高到低)

删除语法:
DEL key
移除集合

ZREM key member1【member2】
移除有序集合中一个或者多个成员
ZREMARANGEBYRANK
移除有序集合中给定的排名区间的所有成员(第一名是0)
ZREMRANGEBYSCORE
移除有序集合中给定的分数区间的所有成员
长期更新,老实有点激动,我的博客有人看了QAQ,如果我有地方理解错误请指出,谢谢!

发布了57 篇原创文章 · 获赞 52 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_40495860/article/details/91049807