Redis基本操作

Redis

Redis入门

   Redis是一个开源(BSD许可),内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理。它支持字符串、哈希表、列表、集合、有序集合,位图,hyperloglogs等数据类型。内置复制、Lua脚本、LRU收回、事务以及不同级别磁盘持久化功能,同时通过Redis Sentinel提供高可用,通过Redis Cluster提供自动分区

Redis下载

下载地址:http://download.redis.io/releases/redis-3.2.8.tar.gz

Redis的安装

   这里在mac下模拟安装,如果需要在linux或者window下安装的话,请自行百度。这里以3.2.8为例

Redis的启动和关闭

启动:
   在命令行输入命令 redis-server,默认链接Redis(127.0.0.1:6379) 启动,如果出现蛋糕图案说明安装成功。

关闭:

  • 使用redis-cli shutdown命令关闭。
  • 使用进程ps -ef | grep redis , kill -9 pid,使用这种方式可能会导致数据丢失。

Redis键

常用命令:

  • key * :返回所有键
  • exists key : 判断某个key是否存在
  • expire key : 给指定的键设置过期时间
  • ttl key : 查看还有多少秒过期,-1表示永不过期,-2表示已过期
  • type key : 查看你的key是什么类型

Redis数据类型

  • 字符串
       string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象。
    string类型是Redis最基本的数据类型,一个键最大能存储512MB。可以在conf文件里设置maxmemory的内存大小,单位是字节。
127.0.0.1:6379> set key1 hello
OK
127.0.0.1:6379> get key1
"hello"
127.0.0.1:6379> 

如果key已经存在则覆盖已经存在的值。

  • Hash(哈希)

hset key filed value
hget key filed
hmset key filed value [filed value...]
hmget key filed [filed...]
hgetall key

127.0.0.1:6379> hmset user:1 usernmae zhangsan password 123456 age 18 address xian
OK
127.0.0.1:6379> hgetall user:1
1) "usernmae"
2) "zhangsan"
3) "password"
4) "123456"
5) "age"
6) "18"
7) "address"
8) "xian"
127.0.0.1:6379> 
127.0.0.1:6379> hmget user:1 age
1) "18"

  • List(列表)
    Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到 列表的头部(左边)或者尾部(右边)。
127.0.0.1:6379> lpush lisi xianren
(integer) 1
127.0.0.1:6379> lpush lisi 18
(integer) 2
127.0.0.1:6379> lpush lisi qinguo
(integer) 3
127.0.0.1:6379> lrange lisi 0 10
1) "qinguo"
2) "18"
3) "xianren"
127.0.0.1:6379> 
  • Set(集合)
    Redis的Set是string类型的无序集合。
127.0.0.1:6379> sadd redis hao haoyong henhaoyong
(integer) 3
127.0.0.1:6379> sadd redis shizhendehaoyong
(integer) 1
127.0.0.1:6379> smembers redis
1) "hao"
2) "haoyong"
3) "henhaoyong"
4) "shizhendehaoyong"
127.0.0.1:6379> 
  • zset有序集合
    Redis zset和set一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
127.0.0.1:6379> zadd wangwu 1 a
(integer) 1
127.0.0.1:6379> zadd wangwu 0 b
(integer) 1
127.0.0.1:6379> zadd wangwu 3 c
(integer) 1
127.0.0.1:6379> zadd wagnwu 2 d
(integer) 1
127.0.0.1:6379> zrangebyscore wangwu 0 5
1) "b"
2) "a"
3) "c"
127.0.0.1:6379> 

解析配置文件

  • daemonize no
    默认情况下 redis不是作为守护进程运行的,如果你想让它在后台运行,你就把它改成yes。当redis作为守护进程运行的时候,它会写一个 pid 到 /var/run/redis.pid 文件里面。
  • tcp-backlog 511
    在高并发的环境下,你需要把这个值调高以避免客户端连接缓慢的问题。
    Linux内核会一声不响的把这个值缩小成/proc/sys/net/core/somaxconn 对应的值,所以你要修改这两个值才能达到你的预期。
  • tcp-keepalive 300
  • loglevel notice
  • databases 默认值16,表示Redis默认的数据库实力数量,如果需要切换数据库,需要使用select number命令切换,flushall清空整个Redis服务器的数据,包括0-16的所有数据库实例,所以使用谨慎使用此命令。flushdb用于清空当前数据库中所有的key。
  • SNAPSHOTTING
    持久换
  • SECURITY
    默认redis是不需要密码输入的,如果我们需要设置密码登录,可以通过命令config set requirepass "111111" ,但是下次在使用命令的时候回提示你输入密码,但是redis是运行于linux之上的,Redis认为Linux是足够安全的,所以redis默认是不需要密码的。Redis支持密码,但不建议这么做。
  • LIMISTS限制
    • 1 maxClients
    • 2 maxmemory
    • 3 maxmemory-policy(缓存过期策略6种)
      • volatile-lru -> remove the key with an expire set using an LRU algorithm
      • allkeys-lru -> remove any key according to the LRU algorithm
      • volatile-random -> remove a random key with an expire set
      • allkeys-random -> remove a random key, any key
      • volatile-ttl -> remove the key with the nearest expire time (minor TTL)
      • noeviction -> don't expire at all, just return an error on write operations
    • 4 maxmemroy-samples
      设置样本数量,LRU算法和TTL算法都并非是精准的算法而是估算值,,所以你可以设置样本的大小,Redis默认会检查这么多个key并选择其中LRU的那个

查看数据库大小

使用info命令查看数据库使用情况

used_memory:数据占用了多少内存(字节
used_memory_human:数据占用了多少内存(带单位的,可读性好)
used_memory_rss:redis占用了多少内存
used_memory_peak:占用内存的峰值(字节)
used_memory_peak_human:占用内存的峰值(带单位的,可读性好)

127.0.0.1:6379> info
......
......
# Memory
used_memory:886548
used_memory_human:865.77K
used_memory_rss:2068480
used_memory_rss_human:1.97M
used_memory_peak:886548
used_memory_peak_human:865.77K
used_memory_peak_perc:100.12%
used_memory_overhead:884987
used_memory_startup:835253
used_memory_dataset:1561
used_memory_dataset_perc:3.04%
......
......

Redis的持久化

  • rdb
    实现机制:当redis需要做持久化时,redis会fork一个子进程;子进程将数据写到磁盘上一个临时RDB文件中;当子进程完成写临时文件后,将原来的RDB替换掉,这样的好处就是可以copy-on-write
  • aof
    filesnapshotting方法在redis异常死掉时,最近的数据会丢失,Append-only方法可以做到全部数据不丢失,但redis的性能就要差些。AOF就可以做到全程持久化,只需要在配置文件中开启(默认是no),appendonly yes开启AOF之后,redis每执行一个修改数据的命令,都会把它添加到aof文件中,当redis重启时,将会读取AOF文件进行“重放”以恢复到redis关闭前的最后时刻。

Redis的事务

   MULTI 命令用于开启一个事务,它总是返回 OK。 MULTI 执行之后, 客户端可以继续向服务器发送任意多条命令, 这些命令不会立即被执行, 而是被放到一个队列中, 当 EXEC命令被调用时, 所有队列中的命令才会被执行。
另一方面, 通过调用 DISCARD , 客户端可以清空事务队列, 并放弃执行事务
demo如下

127.0.0.1:6379> multi
OK
127.0.0.1:6379> incr foo
QUEUED
127.0.0.1:6379> incr bar
QUEUED
127.0.0.1:6379> exec
1) (integer) 1
2) (integer) 1
127.0.0.1:6379> 

发生回滚的的原因

  • 语法错误
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key value
QUEUED
127.0.0.1:6379> set key
(error) ERR wrong number of arguments for 'set' command
127.0.0.1:6379> errorcommand key
(error) ERR unknown command 'errorcommand'
127.0.0.1:6379> exec
(error) EXECABORT Transaction discarded because of previous errors.
127.0.0.1:6379> get key
(nil)
127.0.0.1:6379> 

   当遇到语法错误的时候,后面执行exec的命令时,系统会discarded事务。

  • 运行错误
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 1
QUEUED
127.0.0.1:6379> sadd key 2
QUEUED
127.0.0.1:6379> set key 3
QUEUED
127.0.0.1:6379> exec
1) OK
2) (error) WRONGTYPE Operation against a key holding the wrong kind of value
3) OK
127.0.0.1:6379> get key
"3"
127.0.0.1:6379> 
  • 为什么不支持事务
    以下是这种做法的优点:

    • Redis 命令只会因为错误的语法而失败(并且这些问题不能在入队时发现),或是命令用在了错误类型的键上面:这也就是说,从实用性的角度来说,失败的命令是由编程错误造成的,而这些错误应该在开发的过程中被发现,而不应该出现在生产环境中。
    • 因为不需要对回滚进行支持,所以 Redis 的内部可以保持简单且快速。
      Redis的事务没有关系数据库事务提供的回滚(rollback)功能 。为此开发者必须在事务执行出错后自己收拾剩下的摊子(将数据库复原回事务执行前的状态等)。
  • 放弃事务
    使用discard命令,放弃事务,事务队列被清空,并且客户端会从事务状态中退出

  • watch命令
    watch监控一个键的值是否被改过,在一个事务中,在没有执行exec命令之前,如果监控的值被改动了,则事务失败。如果事务成功,则取消对所有的键的监控。watch也可以监视多个值watch key1 key2 key3

Redis 分区

   分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。
分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。

  • Redis集群
       
    Redis集群是自动分片和高可用的首选方案
  • Twemproxy
    Twemproxy是Twitter维护的(缓存)代理系统,代理Memcached的ASCII协议和Redis协议。该代理实现了一致性hash算法。

Redis的订阅发布

Redis的复制

Redis的Java客户端Jedis

Spring Boot整合Redis

yml配置文件

spring:
  redis:
    database: 0
    host: 127.0.0.1
    port: 6379
    password:
    pool:
      max-active: 8 # 连接池最大连接数(使用负值表示没有限制)
      max-wait: -1  # 连接池最大阻塞等待时间(使用负值表示没有限制
      max-idle: 8   # 连接池中的最大空闲连接
      min-idle: 0   # 连接池中的最小空闲连接
    timeout: 0      # 链接超时时间

ServiceImpl.java如下

package com.yao.service;

import com.yao.domain.City;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

/**
 * Created by yaochenglong on 17/11/20.
 * CityServiceImpl demo
 */
@Service
public class CityServiceImpl implements CityService {

    private static Logger logger = Logger.getLogger(CityServiceImpl.class);

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public City findCityById(String id) {
        String key ="city"+id;

        ValueOperations<String,City> operations = redisTemplate.opsForValue();
        Boolean hasKey = redisTemplate.hasKey(key);
        if(hasKey){
            City city = operations.get(key);
            logger.info("CityServiceImpl.findCityById() : 从缓存中获取了城市>>"+city.getCityName());
            return city;
        }

        //模拟从数据库中获取数据
        City city = new City();
        city.setId("123");
        city.setCityName("西安");
        city.setDescription("爱我大西安");
        operations.set(key,city);
        System.out.println("ityServiceImpl.findCityById() : 从数据库中获取了城市");
        return city;
    }

    @Override
    public Long updateCity(City city) {

        //Long ret = cityDao.updateCity(city);
          Long ret = 1l;

        // 缓存存在,删除缓存

        String key = "city_" + city.getId();

        boolean hasKey = redisTemplate.hasKey(key);

        if (hasKey) {

            redisTemplate.delete(key);


            logger.info("CityServiceImpl.updateCity() : 从缓存中删除城市 >> " + city.toString());

        }


        return ret;

    }
}

Controller 如下

package com.yao.controller;

import com.yao.domain.City;
import com.yao.service.CityService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by yaochenglong on 17/11/20.
 */
@RestController
public class CityController {
    @Autowired
    private CityService cityService;

    @GetMapping("/city/get/{id}")
    public String getCity(@PathVariable("id") String id){
        City city = cityService.findCityById(id);
        return city.getCityName();
    }
}

连续访问请求两次,结果如下:

2017-11-20 22:19:59.985  INFO 1179 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-11-20 22:19:59.985  INFO 1179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2017-11-20 22:19:59.995  INFO 1179 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 10 ms
ityServiceImpl.findCityById() : 从数据库中获取了城市
2017-11-20 22:20:01.704  INFO 1179 --- [nio-8080-exec-3] com.yao.service.CityServiceImpl          : CityServiceImpl.findCityById() : 从缓存中获取了城市>>西安

   我们可以看到第一次从数据库中获取数据,第二次访问则从缓存中获取数据。

高可用性

  • Redis哨兵

  • 自动分区

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

推荐阅读更多精彩内容