Redis数据库的安装与基本应用
# 第一章:Redis 介绍
什么是 redis
Redis 是使用 c 语言开发的一个高性能键值数据库。Redis 可以通过一些键值类型来存储数据。
键值类型:String 字符类型 map 散列类型 list 列表类型 set 集合类型 sortedset 有序集合类型
redis 历史发展
2008 年,意大利的一家创业公司 Merzia 推出了一款基于 MySQL 的网站实时统计系统 LLOOGG,然而没过多久该公司的创始人
Salvatore Sanfilippo 便对 MySQL 的性能感到失望,于是他决定亲自为 LLOOGG 量身定做一个数据库,并于 2009 年开发完成,这个数据库就是 Redis。不过 SalvatoreSanfilippo 并不满足只将 Redis 用于 LLOOGG 这一款产品,而是希望更多的人使用它,于是在同一年 Salvatore Sanfilippo 将 Redis 开源发布,并开始和 Redis 的另一名主要的代码贡献者 PieterNoordhuis 一起继续着 Redis 的开发,直到今天。
优点
响应速度快,能有效提高系统的性能。
支持 6 种数据类型。
操作都是原子的。
还支持各种实现,过期特性等等
与本地缓存的优势:
读写速度:并发下本地缓存需要加锁,读写慢一点
redis 可以用分布式锁防止重复点击
本地缓存的数据结果少,redis 可以储存多种,还可以持久化
本地缓存容易导致线程安全问题。
与 ehcache 对比
Redis 是独立的,其他程序是可以拿到这个数据的,而 Ehcache 是和程序绑定的,其他独立程勋拿不到数据。
与 memcache 的对比
单一数据类型,不支持主从复制,不支持虚拟内存
memcache 数据不可恢复,一旦挂掉。
memcache 可以修改最大内存,使用 LRU 算法,而 Redis 目前底层使用了 VM,突破了物理内存的限制。
redis 的应用场景
缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)但要知道经常修改的数据表不适合使用 redis,因为双删策略执行的结果是把 redis 中保存的那条数据删除了,以后的查询就都会去查询数据库。所以 redis 使用的是读远远大于改的数据缓存。
分布式集群架构中的 session 分离。
聊天室的在线好友列表。
任务队列。(秒杀、抢购、12306 等等)
应用排行榜。
网站访问统计。
数据过期处理(可以精确到毫秒)
第二章:redis 安装
1:Window 安装
安装包地址:https://github.com/microsoftarchive/redis
(1)进入安装包地址,选择 releases
(2)在 releases 页面下载最新版
msi 是可执行文件,按安装步骤安装即可。zip 直接解压就可以了。
端口号可保持默认的 6379,并选择防火墙例外,从而保证外部可以正常访问 Redis 服务。
以服务方式启动
以非服务方式启动
进入 CMD,进入 redis 的目录,执行如下命令
redis-server redis.windows.conf
设置密码
在 redis 目录中找到 redis.windows-service.conf 和 redis.windows.conf 两个文件
都打开找到 requirepass,加一行:requirepass 123456,123456 是密码,保存重新运行 redis,访问 redis 就需要密码了。
CMD 并进入 redis 目录,执行如下命令,执行前请保证 redis 服务已启动
redis-cli -h localhost -p 6379 -a 123456
2:Linux 安装
1:下载
官网地址:http://redis.io/
下载地址:http://download.redis.io/releases/redis-3.0.0.tar.gz
2:安装
redis 的安装环境会安装到 linux 系统中。
第一步:安装 VMware,并且在 VMware 中安装 centos 系统(参考 linux 教程)。
第二步:将 redis 的压缩包,上传到 linux 系统
第三步:对 redis 的压缩包进行解压缩
tar -zxf redis-3.0.0.tar.gz
第四步:安装 c 语言环境(安装 centos 之后,自带 c 语言环境)
yum install gcc-c++
第五步:编译 redis 源码
cd redis-3.0.0
make
第六步:安装 redis
make isntall PREFIX=/usr/local/redis
第七步:查看是否安装成功
3:redis 启动
前端启动
前端启动的命令:
./redis-server
前端启动的关闭:
强制关闭:Ctrl+c
正常关闭:
./redis-cli shutdown
启动界面:
前端启动的问题:
一旦客户端关闭,则 redis 服务也停掉。
后端启动
第一步:需要将 redis 解压之后的源码包中的 redis.conf 文件拷贝到 bin 目录下
cp /root/redis-3.0.0/redis.conf ./
第二步:修改 redis.conf 文件,将 daemonize 改为 yes
先要使用 vim redis.conf
daemonize yes
第三步:使用命令后端启动 redis
./redis-server redis.conf
第四步:查看是否启动成功
ps -aux | grep redis
关闭后端启动的方式:
强制关闭:
kill -9 5071
正常关闭:
./redis-cli shutdown
在项目中,建议使用正常关闭。
因为 redis 作为缓存来使用的话,将数据存储到内存中,如果使用正常关闭,则会将内存数据持久化到本地之后,再关闭。
如果是强制关闭,则不会进行持久化操作,可能会造成部分数据的丢失。
第三章:Redis 客户端
3.1:Redis 自带的客户端
- 启动
启动客户端命令
./redis-cli -h 127.0.0.1 -p 6379
-h:指定访问的 redis 服务器的 ip 地址
-p:指定访问的 redis 服务器的 port 端口
还可以写成:
./redis-cli
使用默认配置:默认的 ip【127.0.0.1】,默认的 port【6379】
-
关闭
Ctrl + c 或则输入 Quit
3.2:图形界面客户端
安装文件位置:
安装之后,打开如下:
Redis.conf 中的数据库数量的设置:
选择数据库的方式:
使用 select 加上数据库的下标 就可以选择指定的数据库来使用,下标从 0 开始
select 15
OK
防火墙设置:
3.3:Jedis 客户端
Redis 不仅是使用命令来操作,现在基本上主流的语言都有客户端支持,比如 java、C、C#、C++、php、Node.js、Go 等。
在官方网站里列一些 Java 的客户端,有Jedis、Redisson、Jredis、JDBC-Redis、等其中官方推荐使用 Jedis 和 Redisson。在企业中用的最多的就是 Jedis,下面我们就重点学习下 Jedis。
Jedis 同样也是托管在 github 上,地址:https://github.com/xetorthio/jedis
1:添加Jar包
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>2.9.0</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
2:单实例连接 redis
@Test
public void jedisclient (){
// Jedis
Jedis jedis = new Jedis ( "192.168.242.137",6379);//通过redis赋值
jedis.set ("s2", "222");//通过redis取值
string result = jedis.get ( "s2");
system. out.println (result);
//关闭jedis
jedis.close ();
}
3:使用 jedis 连接池连接 redis 服务器
Jedis当然也支持连接池,连接池的好处我就不再缀述,我就说说怎么用:
首先将配置参数抽取出来写成redis.properties文件。例如:
#*****************jedis连接参数设置*********************
#redis服务器ip
redis.ip=xxx.xxx.xxx.xxx
#redis服务器端口号
redis.port=6379
#redis访问密码
redis.passWord=123456
#与服务器建立连接的超时时间
redis.timeout=3000
#************************jedis池参数设置*******************
#jedis的最大活跃连接数
jedis.pool.maxActive=100
#jedis最大空闲连接数
jedis.pool.maxIdle=50
#jedis池没有连接对象返回时,等待可用连接的最大时间,单位毫秒,默认值为-1,表示永不超时。
#如果超过等待时间,则直接抛出JedisConnectionException
jedis.pool.maxWait=1500
#从池中获取连接的时候,是否进行有效检查
jedis.pool.testOnBorrow=true
#归还连接的时候,是否进行有效检查
jedis.pool.testOnReturn=true
书写Redis连接池工具类RedisPoolUtil,网上有其他版本的方式,其实实现的本质都是一样的
import java.util.Properties;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
/**
* Redis连接池工具类
*/
public class RedisPoolUtil {
private static JedisPool jedisPool = null;
private static String redisConfigFile = "redis.properties";
//把redis连接对象放到本地线程中
private static ThreadLocal<Jedis> local=new ThreadLocal<Jedis>();
//不允许通过new创建该类的实例
private RedisPoolUtil() {
}
/**
* 初始化Redis连接池
*/
public static void initialPool() {
try {
Properties props = new Properties();
//加载连接池配置文件
props.load(RedisPoolUtil.class.getClassLoader().getResourceAsStream(redisConfigFile));
// 创建jedis池配置实例
JedisPoolConfig config = new JedisPoolConfig();
// 设置池配置项值
config.setMaxTotal(Integer.valueOf(props.getProperty("jedis.pool.maxActive")));
config.setMaxIdle(Integer.valueOf(props.getProperty("jedis.pool.maxIdle")));
config.setMaxWaitMillis(Long.valueOf(props.getProperty("jedis.pool.maxWait")));
config.setTestOnBorrow(Boolean.valueOf(props.getProperty("jedis.pool.testOnBorrow")));
config.setTestOnReturn(Boolean.valueOf(props.getProperty("jedis.pool.testOnReturn")));
// 根据配置实例化jedis池
jedisPool = new JedisPool(config, props.getProperty("redis.ip"),
Integer.valueOf(props.getProperty("redis.port")),
Integer.valueOf(props.getProperty("redis.timeout")),
props.getProperty("redis.passWord"));
System.out.println("线程池被成功初始化");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获得连接
* @return Jedis
*/
public static Jedis getConn() {
//Redis对象
Jedis jedis =local.get();
if(jedis==null){
if (jedisPool == null) {
initialPool();
}
jedis = jedisPool.getResource();
local.set(jedis);
}
return jedis;
}
//归还连接
public static void closeConn(){
//从本地线程中获取
Jedis jedis =local.get();
if(jedis!=null){
jedis.close();
}
local.set(null);
}
//关闭池
public static void closePool(){
if(jedisPool!=null){
jedisPool.close();
}
}
}
最后Test方法测试使用上述方法即可。
注意::::可能会连接超时失败,其实是防火墙的问题,到时候打开防火墙口,然后重启防火墙就OK了。
@Test
public void jedisPool() {
// JedisPool
JedisPool pool = new JedisPool ("192.168.242.137",6379);/通过连接池获取jedis对象
Jedis jedis = pool.getResource () ;
jedis.set ( "s4","444");
string result = jedis.get ("s3");
system.out.println (result);
//关闭jedis客户端
jedis.close ( );
//关闭连接池
pool.close () ;
}
Spring 整合 jedisPool(自学)
- 添加 spring 的 jar 包
- 配置 spring 配置文件 applicationContext.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:mvc="http://www.springframework.org/schema/mvc"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
<!-- 连接池配置 -->
<bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">
<!-- 最大连接数 -->
<property name="maxTotal" value="30" />
<!-- 最大空闲连接数 -->
<property name="maxIdle" value="10" />
<!-- 每次释放连接的最大数目 -->
<property name="numTestsPerEvictionRun" value="1024" />
<!-- 释放连接的扫描间隔(毫秒) -->
<property name="timeBetweenEvictionRunsMillis" value="30000" />
<!-- 连接最小空闲时间 -->
<property name="minEvictableIdleTimeMillis" value="1800000" />
<!-- 连接空闲多久后释放, 当空闲时间>该值 且 空闲连接>最大空闲连接数 时直接释放 -->
<property name="softMinEvictableIdleTimeMillis" value="10000" />
<!-- 获取连接时的最大等待毫秒数,小于零:阻塞不确定的时间,默认-1 -->
<property name="maxWaitMillis" value="1500" />
<!-- 在获取连接的时候检查有效性, 默认false -->
<property name="testOnBorrow" value="false" />
<!-- 在空闲时检查有效性, 默认false -->
<property name="testWhileIdle" value="true" />
<!-- 连接耗尽时是否阻塞, false报异常,ture阻塞直到超时, 默认true -->
<property name="blockWhenExhausted" value="false" />
</bean>
<!-- redis单机 通过连接池 -->
<bean id="jedisPool" class="redis.clients.jedis.JedisPool"
destroy-method="close">
<constructor-arg name="poolConfig" ref="jedisPoolConfig" />
<constructor-arg name="host" value="192.168.242.130" />
<constructor-arg name="port" value="6379" />
</bean>
</beans>
- 测试代码
@Test
public void testJedisPool() {
JedisPool pool = (JedisPool) applicationContext.getBean("jedisPool");
Jedis jedis = null;
try {
jedis = pool.getResource();
jedis.set("name", "lisi");
String name = jedis.get("name");
System.out.println(name);
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (jedis != null) {
// 关闭连接
jedis.close();
}
}
}