什么是Redis
c语言开发的非关系型键值存储数据库
为什么要使用Redis
- redis是
单线程
,并发量高时incr和decr不会出现重复数字 - 能通过缓存
减轻数据库压力
若页面内容是查询数据库获得,为了防止多人多次刷新访问页面给数据库造成压力,可采用Redis缓存保存数据
Redis持久化
- 什么叫持久化:即将数据写入磁盘中(写入数据库)
- 为什么要持久化:为了使Redis在重启后仍能保证数据不丢失(redis数据库可以内存存储,也可以持久化,但内存存储时重启或宕机会丢失数据)
- redis持久化的方式:也可以两种方式混合使用
持久化方式 RDB方式(默认方式) AOF方式 实现方法 定时将内存 数据
进行快照
并存储到磁盘,重启后将快照读取到内存进行操作记录发送到Redis服务端的每一条 命令
并保存储到磁盘实现原理 1. fork函数复制一份当前进程的副本 2. 当前进程接收并处理客户端发来的命令,副本则将内存中的数据写入到硬盘中的临时文件(RDB文件存到硬盘是默认要进行压缩) 3. 副本写完所有数据后用临时文件替换旧的RDB文件 重启或宕机后执行aof文件中的命令进行数据恢复 配置方法 在redis.conf文件中配置快照启动间隔时间, 未到设定时间不会启动快照
在redis.conf文件中配置 改进方法 通过SAVE(当前进程快照,会阻塞其他请求)和BGSAVE(fork副本快照)来 手动快照
通过BGREWRITEAOF 手动重写AOF文件
注意事项 由于需要在内存中进行数据备份,所以要保证 内存充足
手动重写可以取出数据中间执行过程,保留最终数据命令,但容易丢失数据(除非每次都同步)
单机版Redis搭建
一、准备工作
- 准备依赖环境:yum install gcc-c++
- 准备相关安装包:tar -zxvf redis-3.0.0.tar.gz
二 、安装
在解压目录中依次执行编译和安装命令
- make
- make install PREFIX=/usr/local/redis
三 、启动Redis数据库服务
- 前端启动:./redis-server
- 后端启动:
- cp redis.conf /usr/local/redis
- 修改配置文件redis.conf:修改daemonize为yes
- ./redis-server redis.conf
四 、Redis数据库的使用
- Redis自带客户端使用:
- 连接redis服务:./redis-cli -p 端口 -h ip (如果连接的是集群需要加-c)
- 进行crud操作
- RedisDesktopManager:图形化管理工具(不支持集群,只能在单机版环境使用)
Redis集群搭建
一、搭建集群
集群中应该至少有三个节点,每个节点有一个备份节点
- 新建一个文件夹存放集群:mkdir redis-cluster
- 准备多个集群节点:cp redis redis-cluster/ -r
- 删除每个redis目录下的dump.rdb文件:rm dump.rdb
- 设置允许集群:修改redis.conf 打开Cluster-enable yes前面的注释
- 为节点设置不同端口:修改port(如果ip不同则不需要这步)
- 启动所有redis实例
- 创建集群:
- 将redis文件夹下的redis-trib.rb文件复制到redis-cluster目录下:cp redis-trib.rb /usr/local/redis-cluster/
- 安装ruby环境:yum install ruby、yum install rubygems、gem install redis-3.0.0.gem
- 创建集群:./redis-trib.rb create --replicas 每个节点的备份数 IP1 IP2 IP3 IP4 IP5 IP6
二、连接集群
- Redis自带客户端使用:
- 连接redis服务:/redis01/redis-cli -p 端口 -h ip -c
- 进行crud操作
使用Jedis连接Redis
一、准备工作:在项目中添加redis依赖的jar包
二、直接使用Jedis
- 单机版Redis使用
public void singleRedisTest() { //创建一个连接池对象 JedisPool jedisPool = new JedisPool("192.168.134.130",6379); //从连接池中获得一个连接 Jedis jedis = jedisPool.getResource(); //数据操作 jedis.set("test", "hello"); String s = jedis.get("test"); System.out.println(s); //释放连接 jedis.close(); //关闭连接池 jedisPool.close(); }
- Redis集群使用
public void clusterRedisTest() { //设置集群中的节点ip HashSet<HostAndPort> nodes = new HashSet<HostAndPort>(); nodes.add(new HostAndPort("192.168.134.130",7001)); nodes.add(new HostAndPort("192.168.134.130",7002)); nodes.add(new HostAndPort("192.168.134.130",7003)); nodes.add(new HostAndPort("192.168.134.130",7004)); nodes.add(new HostAndPort("192.168.134.130",7005)); nodes.add(new HostAndPort("192.168.134.130",7006)); //创建Jediscluster对象并添加集群节点 JedisCluster cluster = new JedisCluster(nodes); //操作数据 cluster.set("name", "youjie"); String s = cluster.get("name"); System.out.println(s); //关闭Jediscluster cluster.close(); }
三、spring配置使用Jedis
-
创建redis功能接口,接口中声明redis的各种crud操作方法
public interface JedisClient { public String set(String key, String value); public String get(String key); public Long hset(String key,String item, String value); public String hget(String key, String item); public Long incr(String key); public Long decr(String key); public Long expire(String key, int second); public Long ttl(String key); }
-
分别创建单机版和集群版两个实现类
//单机版 public class SingleJedisClientImpl implements JedisClient { @Autowired private JedisPool jedisPool; @Override public String set(String key, String value) { Jedis jedis = jedisPool.getResource(); String result = jedis.set(key, value); jedis.close(); return result; } ... }
//集群版 public class ClusterJedisClientImpl implements JedisClient { @Autowired private JedisCluster jedisCluster; @Override public String set(String key, String value) { return jedisCluster.set(key, value); } ... }
-
在applicationContext-service.xml中进行配置,两者配置其一即可
<!-- 配置redis单机版的jedisPool--> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="6379"></constructor-arg> </bean> <!-- 配置单机版实现类 --> <bean id="SingleJedisClientImpl" class="com.taotao.redis.utils.impl.SingleJedisClientImpl"/> <!-- 配置redis集群版的jedisCluster --> <bean id="jedisCluster" class="redis.clients.jedis.JedisCluster"> <constructor-arg> <set> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7001"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7002"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7003"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7004"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7005"></constructor-arg> </bean> <bean class="redis.clients.jedis.HostAndPort"> <constructor-arg name="host" value="192.168.134.130"></constructor-arg> <constructor-arg name="port" value="7006"></constructor-arg> </bean> </set> </constructor-arg> </bean> <!-- 配置集群版实现类 --> <bean id="ClusterJedisClientImpl" class="com.taotao.redis.utils.impl.ClusterJedisClientImpl"/>
-
连接redis进行操作
public void testJedisClientSpring() throws Exception { //创建一个spring容器 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml"); //从容器中获得JedisClient对象 JedisClient jedisClient = applicationContext.getBean(JedisClient.class); //操作数据 jedisClient.set("cliet1", "1000"); String string = jedisClient.get("cliet1"); System.out.println(string); }
项目中使用Redis
- 添加与读取缓存
访问页面时先从缓存数据库中读取数据,若无数据,则查询数据库并将其添加到缓存中 - 缓存同步
当后台操作系统对数据库中的数据进行了增删改时,在完成修改后删除缓存数据库中的数据
为了防止出错,在设计到多个项目时,最好只指定一个项目来写操作缓存数据库 - 缓存定时清除:过期时间设置
jedisClient.expire(key, seconds);