7、redis缓存

什么是redis?
Redis是用C语言开发的一个开源的高性能键值对(key-value)数据库。它通过提供多种键值数据类型来适应不同场景下的存储需求,目前为止Redis支持的键值数据类型如
下:
字符串类型
散列类型
列表类型
集合类型
有序集合类型。

redis的应用场景
缓存(数据查询、短连接、新闻内容、商品内容等等)。(最多使用)
分布式集群架构中的session分离。
聊天室的在线好友列表。
任务队列。(秒杀、抢购、12306等等)
应用排行榜。
网站访问统计。
数据过期处理(可以精确到毫秒)


redis是对内存进行操作。

单机版redis有16个数据库,默认使用0号库,库与库之间相互独立,允许出现重复变量名

集群环境只有0号库

------切记------

---我们在开发时使用的是单机版redis,在程序运行时,一定要记得打开装有redis服务的虚拟机,把单
---机版 redis-server打开,进入/usr/local/redis/bin
[root@taotao-redis bin]# ./redis-server redis.conf 
---关闭 redis 服务
[root@taotao-redis bin]# ./redis-cli -p 6379 shutdown

当我们使用Junit测试 jedis 的时候,若出现 Class not found...... 不要慌张,这个问题首先看
自己redis服务打开没,在不停的重启taotao-rest这个mavean工程。

一、redis安装

需要安装gcc:yum install gcc-c++

1、下载redis的源码包。
2、把源码包上传到linux服务器
3、解压源码包
tar -zxvf redis-3.0.0.tar.gz
4、Make
5、Make install
[root@bogon redis-3.0.0]# make install PREFIX=/usr/local/redis

启动单机版redis

1、前端启动模式
/usr/local/redis/bin/redis-server
默认是前端启动模式,端口是6379
2、后端启动
1)从redis的源码目录中复制redis.conf到redis的安装目录。
2)修改配置文件

修改配置文件.png

3)[root@bogon bin]# ./redis-server redis.conf

Redis常用命令
---定义/获取变量
127.0.0.1:6379> set a 10
OK
127.0.0.1:6379> get a
"10"
---设置/查看变量有效时间 永久变量返回-2,失效变量返回-1,暂时有效返回一个整数
127.0.0.1:6379> EXPIRE a 100
(integer) 1
127.0.0.1:6379> ttl a
(integer) 94
127.0.0.1:6379> ttl a
(integer) -2
常用数据类型
String
Hash
List
Set
SortedSet
hash结构的常见操作指令
---学习前先明确一下概念,这里我们把Redis的key称作key(键),把数据结构hash中的key称为field(域)。

**hdel key field[field...]**
  删除hash表中的一个或多个指定域,若key或field不存在则会忽略;例:hdel hk k1 k2。

**hexists key field**
  判断hash表中指定域是否存在,返回1,若key或field不存在则返回0;例:hexists hk k1。

**hget key field**
  获取hash表中指定域的值,key或域不存在时返回nil;例:hget hk k1。

**hgetall key**
  获取hash表中所有域的值;例:hgetall hk,返回结果如:
  1) k1
  2) v1
  3) k2
  4) v2
  5) k3
  6) v3
1和2、3和4、5和6各为一组,代表hash表的field和value。

**hincrby key field increment**
  为hash表中的指定域增加指定的整数值(负数亦可),若域不存在则默认初始化值为0后再进行操纵,若域存在但值不为数值但非64位有符号数时返回错误;例:hincrby hk k1 15。

**hincrbyfloat key field increment**
  和hincrby相似,不同的是hincrbyfloat操作的是浮点数;例:hincrbyfloat hk k1 1.3。

**hkeys key**
  返回hash表中的所有域,若key不存在返回空;例:hkeys hk。

**hvals key**
  返回hash表中的所有val,若key不存在返回空;例:hvals hk。

**hlen key**
  返回hash表中所有域的数量,若key不存在返回0;例:hlen hk。

**hset key field value**
  将field-value设置到hash表中,若key不存在会新建hash表再赋值,若field已存在则会覆盖现有值;例:hset hk k v。

**hsetnx key field value**
  和hset类似,但是hsetnx要求field不存在才能进行此操作,否则会返回0;例:hset hk k v。

**hmget key field[field...]**
  返回hash表中多个指定域的值,若key不存在返回空,若field不存在返回nil;例:hmget hk k1 k2 k3。

**hmset key field1 value1[field value...]**
  将一个或多个field-value设置到hash表中;例:hmset hk k4 v4 k5 v5 k6 v6。

**hscan key cursor[match pattern][count count]**
  采用游标的方式对当前的hash进行迭代(具体描述请参考[scan](http://www.cnblogs.com/krockey/p/6019556.html)),例:hscan hk 0。

二、redis集群构架

1、环境

需要使用官方提供的ruby脚本 需要 ruby 环境
yum install ruby
yum install rubygems

需要使用集群管理工具来管理包 redis-trib.rb

开启单机版redis
方式一:进入redis目录下的bin目录,找到redis-server,开启

[root@taotao-redis bin]# ./redis-server

方式二:后台模式开启,需要修改bin目录下的redis-conf,


redis-conf.png
[root@taotao-redis bin]# ./redis-server redis.conf
2、集群搭建

第一步:创建6个redis实例,端口号7001~7006

第二步:修改redis的配置文件
1、修改端口号
2、打开cluster-enable前面的注释

第三步:把集群的ruby脚本复制到redis-cluster目录下

第四步:启动6个redis实例
自制shell命令开启redis


启动redis.png
[root@taotao-redis redis-cluster]# chmod +x startall.sh
[root@taotao-redis redis-cluster]# ./startall.sh 
[root@taotao-redis redis-cluster]# ps aux | grep redis

第五步:创建集群

./redis-trib.rb create --replicas 1 192.168.76.133:7001 192.168.76.133:7002 192.168.76.133:7003 192.168.76.133:7004 192.168.76.133:7005  192.168.76.133:7006
3、测试集群
[root@taotao-redis redis-cluster]# redis01/redis-cli -h 192.168.76.133 -p 7002 -c
192.168.76.133:7002> set a 100
-> Redirected to slot [15495] located at 192.168.76.133:7003
OK
192.168.76.133:7003> get a 
"100"
192.168.76.133:7003> ping
PONG
4、关闭redis

1)进入redis关闭

[root@taotao-redis redis]# bin/redis-cli
127.0.0.1:6379> shutdown
not connected> quit

2)根据端口号关闭

[root@taotao-redis redis]# bin/redis-cli -p 7001 shutdown

自制shell关闭redis

关闭redis.png

[root@taotao-redis redis-cluster]# ps aux | grep redis
[root@taotao-redis redis-cluster]# chmod +x shutdown.sh
[root@taotao-redis redis-cluster]# ./shutdown.sh
[root@taotao-redis redis-cluster]# ps aux | grep redis
5、Jedis客户端测试

(1)单机版

public class JedisTest {

    @Test
    public void testJedisSingle() {
        //创建一个jedis的对象。
        Jedis jedis = new Jedis("192.168.25.153", 6379);
        //调用jedis对象的方法,方法名称和redis的命令一致。
        jedis.set("key1", "jedis test");
        String string = jedis.get("key1");
        System.out.println(string);
        //关闭jedis。
        jedis.close();
    }
    
    /**
     * 使用连接池
     */
    @Test
    public void testJedisPool() {
        //创建jedis连接池
        JedisPool pool = new JedisPool("192.168.25.153", 6379);
        //从连接池中获得Jedis对象
        Jedis jedis = pool.getResource();
        String string = jedis.get("key1");
        System.out.println(string);
        //关闭jedis对象
        jedis.close();
        pool.close();
    }
}

(2)集群版:不需要开启连接池,JedisCluster自带连接池

@Test
    public void testJedisCluster() {
        HashSet<HostAndPort> nodes = new HashSet<>();
        nodes.add(new HostAndPort("192.168.25.153", 7001));
        nodes.add(new HostAndPort("192.168.25.153", 7002));
        nodes.add(new HostAndPort("192.168.25.153", 7003));
        nodes.add(new HostAndPort("192.168.25.153", 7004));
        nodes.add(new HostAndPort("192.168.25.153", 7005));
        nodes.add(new HostAndPort("192.168.25.153", 7006));
        
        JedisCluster cluster = new JedisCluster(nodes);
        
        cluster.set("key1", "1000");
        String string = cluster.get("key1");
        System.out.println(string);
        
        cluster.close();
    }

redis安装好后需要开启端口号本机才能访问使用

不管是使用单机版还是集群版,都需要开启端口号(集群的话就全部开启)

---redis 需要开启端口号才能使用
[root@taotao-redis ~]# cd /sbin
[root@taotao-redis sbin]# sudo iptables -I INPUT -p tcp --dport 6379 -j ACCEPT
[root@taotao-redis sbin]# sudo service iptables save
[root@taotao-redis sbin]# sudo service iptables restart

三、业务逻辑添加缓存

业务逻辑图.png

需要在taotao-rest(服务层添加缓存)

1、Jedis整合Spring

1.1 单机版整合
<!-- jedis客户端单机版 -->
    <bean id="redisClient" class="redis.clients.jedis.JedisPool">
        <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
        <constructor-arg name="port" value="6379"></constructor-arg>
        <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
    </bean>
/**
     * Spring单机版测试
     */
    @Test
    public void testSpringJedisSingle() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
        JedisPool pool = (JedisPool) applicationContext.getBean("redisClient");
        Jedis jedis = pool.getResource();
        String string = jedis.get("key1");
        System.out.println(string);
        jedis.close();
        pool.close();
    }
1.2 集群版整合
<bean id="redisClient" class="redis.clients.jedis.JedisCluster">
        <constructor-arg name="nodes">
            <set>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7001"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7002"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7003"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7004"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7005"></constructor-arg>
                </bean>
                <bean class="redis.clients.jedis.HostAndPort">
                    <constructor-arg name="host" value="192.168.25.153"></constructor-arg>
                    <constructor-arg name="port" value="7006"></constructor-arg>
                </bean>
            </set>
        </constructor-arg>
        <constructor-arg name="poolConfig" ref="jedisPoolConfig"></constructor-arg>
    </bean>
/**
     * Spring集群版测试
     */
    @Test
    public void testSpringJedisCluster() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring/applicationContext-*.xml");
        JedisCluster cluster = (JedisCluster) applicationContext.getBean("redisClient");
        String string = cluster.get("keyCluster");
        System.out.println(string);
        cluster.close();
    }

2、把缓存添加到业务逻辑

注意:添加的缓存不能影响业务逻辑。

3、缓存同步

当后台管理系统修改内容之后,需要通知redis把修改内容对应的分类id的key删除。


添加缓存后的构架.png
3.1 解决方案

在taotao-rest工程中发布一个服务。当后台管理系统修改内容后,调用此服务,同步缓存。

3.2 同步缓存服务的调用

需要在后台管理系统中添加一个服务调用的逻辑。当修改内容信息后,需要调用此服务同步缓存。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容