Redis入门
Redis介绍
一种全新的内存型数据库。
Redis是key-value型的NoSQL(Not only SQL)数据库(非关系型数据库);
Redis将数据存储在内存中,同时也能持久化到磁盘;
Redis常用于缓存,利用内存的高效提高程序的处理速度。
笔记:
内存RAM,关机重启后数据会丢失,redis支持将数据持久化到硬盘上;
系统和数据库服务直接可以增加redis服务器,系统直接从redis中获取数据,速度更快。
Redis特点
速度快;广泛的语言支持;持久化;多种数据结构;主从复制;分布式于高可用。
笔记:
开源,可以根据需求开发特定的redis工具
高可用:哨兵机制,防止一台redis服务器当机系统就无法使用。
Redis的安装与启动
1)Linux系统上安装Redis:
进入redis官网:https://redis.io/
因为redis是服务器端的NoSQL数据库,官方默认不会提供windows下的redis最新版本,只提供tar.gz格式tar.gz格式的redis最新版本的下载,所以redis的安装平台首选Linux系统。
点击Check the downloads page.
可以看到具体的安装过程
步骤:
进入linux系统,打开终端
cd /usr/local #进入local目录,一般习惯将程序安装在这个目录下
mkdir redis #创建一个名为redis的文件夹,用于安装 redis
cd redis #进入redis目录
yum install gcc #底层依赖gcc才能使用make命令进行编译,需先安装gcc编译包
wget http://download.redis.io/releases/redis-6.0.8.tar.gz #下载最新redis安装包
tar xzf redis-6.0.8.tar.gz #解压安装包
cd redis-6.0.8/ #进入解压后的目录,里面存放的是redis源代码等,其中redis.conf是redis的核心配置文件
make #编译源代码
cd src #进入源代码目录,其中redis-server是redis的启动命令,redis-cli是redis的连接客户端
cd .. #返回上一级目录
./src/redis-server redis.conf #启动redis
使用make编译时报错:
经查资料了解到,centos7安装redis6.x版本要正常编译,需要升级gcc的版本
gcc -v #查看gcc版本
centos7默认gcc版本为4.8.5
redis6.x版本需要的gcc版本为5.3及以上
//升级gcc到9以上
yum -y install centos-release-scl
yum -y install devtoolset-9-gcc devtoolset-9-gcc-c++ devtoolset-9-binutils
//临时将此时的gcc版本改为9(scl命令启用只是临时的,推出xshell或者重启就会恢复到原来的gcc版本)。
scl enable devtoolset-9 bash
//或永久改变
echo "source /opt/rh/devtoolset-9/enable" >>/etc/profile
这时再查询gcc版本,变为了9.x版本
重新使用make编译,往下进行流程
看到下图文字表示编译成功:
redis启动成功界面:
2)windows系统上安装Redis:
微软对redis重构,提供了能够在windows上运行的redis。
github地址:https://github.com/MicrosoftArchive/redis
不过版本很久没有更新了,截止目前,最后一次更新的才3.2.100版本
点击relese page
下载.zip版本,版本有些老,作为学习可以用,生产环境服务器上不可以
解压安装包
redis-server.exe是启动程序
redis-windows.conf是redis核心配置文件
cmd进入终端
进入redis目录,启动redis,下图是启动成功界面。
reids的常用基本配置
Redis通用命令
笔记:
例1:守护进程方式启动redis,即后台运行
解决终端重启或关闭后redis进程关闭的问题。
启动linux终端,进入redis目录:
cd redis-6.0.8/
打开并编辑redis配置文件:
vim redis.conf
定位到文件的146行,将daemonize的参数由no改为yes,表示允许后台启动(按i进入编辑模式,修改后:wq保存并退出)
关闭redis服务:
使用kill命令(不推荐,后续会学习使用redis-cli关闭命令)。
kill -9 进程号
例2:使用redis-cli客户端
进入redis目录:
cd redis-6.0.8/
启动redis-cli,进入redis客户端,可以输入redis命令并执行:
./src/redis-cli
检查redis服务是否正常启动:
ping
ping 看是否能提供服务 ping 显示pong正常
退出cli:
exit
使用cli关闭redis服务:
./src/redis-cli shutdown
实际项目一般不会用默认端口6379,防止黑客或第三方攻击。通过修改redis.conf文件来修改默认端口:
定位到配置文件92行,修改port后的端口号
修改日志文件名字(保存在redis目录下):
定位到171行,logfile ,默认为空字符串
重新启动redis可以看到变化:
后台启动,端口号为6380
这时,再连接cli客户端,提示6379连接被拒绝,因为我们把端口改为了6380,需要连接6380端口。
在cli中操作redis数据库:
select 数据库名字 #切换数据库
redis中数据库的名字就是一个一个的数字 默认16个 序号0~15,超过会提示越界
修改cong配置文件来修改数据库总数:
定位到186行。
但这样只要加上端口号就可以通过redis-cli访问数据很危险,需要设置密码:
定位到conf配置文件507行。
把 requirepass 那一行注释打开,修改密码
这样就必须提供密码才能访问redis数据了。
cli连接身份验证:
auth 密码
指定数据文件的保存路径修改,很重要,但很少修改,默认是当前文件夹:
定位到conf配置文件第263行
redis目录中的另一个重要文件:
dump.rdb 文件,用来保存的全量数据(包含任何操作),防止redis突然当机造成数据丢失。
Redis数据类型
1)String-字符串类型
结构:
命令:
单个kv不要太大,否则会影响存取数据的速度、效率;
value是数字时,底层也是以字符串类型存储的。
2)Hash键值类型
结构:
用于存储结构化数据。
命令:
3)List列表类型
结构:
List列表就是一系列字符串的“数组”,按插入顺序排列;
List列表最大长度为2的32次方-1,可以包含40亿个元素。
命令:
lrange 获取list中数据,后面两个参数是开始范围 start end,取全部值参数为 0 -1
4)Set集合类型
结构:
Set集合是字符串的无序集合,集合成员是唯一的。
命令:
sadd 集合名字 字符串(数组) #创建一个集合,插入成员
smembers 集合名字 #查看某集合所有成员
插入成员时,返回1表示插入成功,返回0表示失败
集合求交集:
sinter 集合1 集合2
集合求并集:
sunion 集合1 集合2
集合求差集(1有,2没有的):
sdiff 集合1 集合2
5)Zset集合类型
结构:
Zset集合是字符串的有序集合,集合成员是唯一的。在Set集合基础上加了一个分数参数,使集合有序。
默认按照分数升序排列。
命令:
zadd 集合名字 分数 字符串 #创建一个集合,插入成员
zrange 集合名字 start end #用于输出指定范围的元素,0 -1 表示全部元素
Redis的Java客户端——Jedis
redis官网为每种语言都提供了对应的客户端,Jedis是Java语言开发的Redis客户端工具包;
Jedis只是对Redis命令的封装,掌握Redis命令便可以轻松上手。
1)Jedis使用演示
一般redis服务器仅做redis服务使用,我们的java程序要用另外一台服务器。
多个服务器之间进行来回通讯,redis的配置要进行一些更改。
1⃣️默认情况下只允许在本机访问redis,要想远程访问需要修改两个参数:
定位到conf文件88行,protected-mode 保护模式,yes表示只允许指定的地址才能访问redis服务,
开发需要,要先设置为no,允许其他主机也能访问redis。
定位到69行,bind 默认 127.0.0.1 后面的地址表示能访问redis的主体ip
修改为 bind 0.0.0.0 所有主机可访问,实际项目不能这样,不安全,要设置成具体服务器地址
2⃣️设置防火墙对6379端口放行
正常第一次放行是不会有红色warning的,这里是因为之前已经放行了,所以才warning提示。
3⃣️查看redis服务器IP地址,联机时需要用到
ifconfig
4⃣️下载安装jedis
进入redis官网,点击Clients
点击java
里面有许多开源的redis java客户端,点击图标,进入github官网
里面有安装的方式,下面使用maven方式下载
目前最新版本为3.3.0版本
2.9.0版本最稳定,暂用这一版本。
5⃣️jedis使用入门
启动idea➡️create new project➡️maven➡️next
在pom文件中加入redis依赖
测试代码:
1 public class JedisTestor { 2 public static void main(String[] args) { 3 Jedis jedis = new Jedis("192.168.132.144" , 6379);//服务器地址,端口号 4 try { 5 jedis.auth("12345");//验证密码 6 jedis.select(2);///切换到数据库2 7 System.out.println("Redis连接成功"); 8 //字符串 9 jedis.set("sn" , "7781-9938"); 10 String sn = jedis.get("sn"); 11 System.out.println(sn); 12 jedis.mset(new String[]{"title" , "婴幼儿奶粉" , "num" , "20"}); 13 List<String> goods = jedis.mget(new String[]{"sn" , "title" , "num"}); 14 System.out.println(goods); 15 Long num = jedis.incr("num"); 16 System.out.println(num); 17 //Hash 18 jedis.hset("student:3312" , "name" , "张晓明"); 19 String name = jedis.hget("student:3312" , "name"); 20 System.out.println(name); 21 Map<String,String> studentMap = new HashMap(); 22 studentMap.put("name", "李兰"); 23 studentMap.put("age", "18"); 24 studentMap.put("id", "3313"); 25 jedis.hmset("student:3313", studentMap); 26 Map<String,String> smap = jedis.hgetAll("student:3313"); 27 System.out.println(smap); 28 //List 29 jedis.del("letter"); 30 jedis.rpush("letter" , new String[]{"d" , "e" , "f"}); 31 jedis.lpush("letter" , new String[]{"c" , "b" , "a"}); 32 List<String> letter = jedis.lrange("letter" , 0 , -1); 33 jedis.lpop("letter"); 34 jedis.rpop("letter"); 35 letter = jedis.lrange("letter", 0, -1); 36 System.out.println(letter); 37 }catch(Exception e){ 38 e.printStackTrace(); 39 }finally { 40 jedis.close();//关闭jedis连接 41 } 42 43 } 44 }
注意:redis中1个汉子3个字节,一个字符串返回的长度也是按字节来算的
2)利用Jedis缓存数据
用redis做缓存,需具备的特性:数据不能太大,且更新频率比较低的数据
将java对象存入redis(转换为json存,用时在将json转换回来,需要用到fastjson)
测试代码:
1 public class CacheSample { 2 public CacheSample(){ 3 Jedis jedis = new Jedis("192.168.132.144");//如果是默认端口号6379,可以不写第二个参数 4 try { 5 List<Goods> goodsList = new ArrayList<Goods>(); 6 goodsList.add(new Goods(8818, "红富士苹果", "", 3.5f)); 7 goodsList.add(new Goods(8819, "进口脐橙", "", 5f)); 8 goodsList.add(new Goods(8820, "进口香蕉", "", 25f)); 9 jedis.auth("12345"); 10 jedis.select(3); 11 for (Goods goods : goodsList) { 12 String json = JSON.toJSONString(goods); 13 System.out.println(json); 14 String key = "goods:" + goods.getGoodsId(); 15 jedis.set(key , json); 16 } 17 } catch (Exception e) { 18 e.printStackTrace(); 19 }finally { 20 jedis.close(); 21 } 22 } 23 24 public static void main(String[] args) { 25 new CacheSample(); 26 System.out.printf("请输入要查询的商品编号:"); 27 String goodsId = new Scanner(System.in).next(); 28 Jedis jedis = new Jedis("192.168.132.144"); 29 try{ 30 jedis.auth("12345"); 31 jedis.select(3); 32 String key = "goods:" + goodsId; 33 if(jedis.exists(key)){ 34 String json = jedis.get(key); 35 System.out.println(json); 36 Goods g = JSON.parseObject(json, Goods.class);//将json转换为Goods类对象 37 System.out.println(g.getGoodsName()); 38 System.out.println(g.getPrice()); 39 }else{ 40 System.out.println("您输入的商品编号不存在,请重新输入!"); 41 } 42 }catch(Exception e){ 43 e.printStackTrace(); 44 }finally { 45 jedis.close(); 46 } 47 } 48 }
java对象
1 public class Goods { 2 private Integer goodsId; 3 private String goodsName; 4 private String description; 5 private Float price; 6 7 public Goods(){ 8 9 } 10 11 public Goods(Integer goodsId, String goodsName, String description, Float price) { 12 this.goodsId = goodsId; 13 this.goodsName = goodsName; 14 this.description = description; 15 this.price = price; 16 } 17 18 public Integer getGoodsId() { 19 return goodsId; 20 } 21 22 public void setGoodsId(Integer goodsId) { 23 this.goodsId = goodsId; 24 } 25 26 public String getGoodsName() { 27 return goodsName; 28 } 29 30 public void setGoodsName(String goodsName) { 31 this.goodsName = goodsName; 32 } 33 34 public String getDescription() { 35 return description; 36 } 37 38 public void setDescription(String description) { 39 this.description = description; 40 } 41 42 public Float getPrice() { 43 return price; 44 } 45 46 public void setPrice(Float price) { 47 this.price = price; 48 } 49 }
报错:
connection refused
原因:
1.服务器地址错了
2.物理网络没有调通