setnx是原子操作吗_Redis基本指令,操作及工具类

redis,远程字典服务,强大的后端必备技能.

如何启动redis

 #redis ==>数据库,缓存,消息中间件#五种数据类型strings / hashs / lists / sets / sorted setsps -ef|grep redis #查看redis进程(在命令行下)#启动redis,首先要知道redis-server位置,还要知道redis.conf位置**使用 locate redis-server 和 locate redis.conf **#接着使用下面指令/usr/local/bin/redis-server /www/server/redis/redis.confnetstat -nplt #可以查看是否启动成功#连接edisredis-cli -p 6379 #(下面语句在redis下)set key xxxget keykeys * #所有keyshutdown --> exit #退出redis#测试redis-benchmarkredis-benchmark -h localhost -p 6379 -c 100 -n 100000#共16个数据库select *  #切换数据库dbsize #查看数据库大小flushdb #清空当前库flushall #清空所有数据库exists name #判断name是否存在move name 1 #移动name到数据库1del name #删除keyexpire name 10  #十秒后过期这时候使用ttl #name查看他的时间type name #查看name类型append name "hello" #在name后追加hellostrlen name #看name长度

Strings

 set views 0incr views #views加1decr views #views减1incrby views 10 #增长10decrby views 10 #减10
 getrange name 0 3 #截取字符串[0,3]getrange name 0 -1 #截取全部字符串
 #替换 name=abcdsetrange name 1 xx #从1位开始替换两位 变成 axxdsetex (set with expire)#设置过期时间setnx (set if not exist)#不存在再设置
 mset k1 v1 k2 v2 k3 v3 #批量设置msetnx k1 v1 k2 v2 #接上一条指令,会设置失败,因为已经存在,要么都成功,要么都失败
 set user:1 {name:zhangsan,age:12}mset user:1:name zhangsan user:2:age 2
 getset name xxx  # 先get再set,不存在会返回nil但是也会创建

List

所有list命令l开头

 lpush是将一个或多个值插入到头部 (leftpush)lpush list onelpush list twolpush list threelrange list 0 -1 #拿全部值lrange list 0 1 #拿到 three 和 two 栈,先进后出rpush #是将一个或多个值插入到尾部lpop #头部移除rpop #尾部移除lindex list 1 #通过下标获取值llen list #查看长度lrem list 1 one #移除指定的值 one一次lrem list 2 three #移除指定值three 两次######################################################
 trim #修剪ltrim  list 1 2 #从头部 1, 2 位置截取剩下2个(如 lpush list a b c d e,(e为头部)ltrim list 1 2后lrange list 0 -1 结果为 d c )rtrim#####################################################rpoolpush list newlist #移除list最后一个元素并添加到新列表lset list 1 item #在list指定下标赋值linsert list before "b" "z" #b 前面插入 zlinsert list after "b" "z" #b 后面插入 z

set

 set 无序的里面的值不允许重复sadd myset "hello"sadd myset "hello1"sadd myset "hello2"smembers myset #查看sismember myset hello #返回1  已存在 无法插入sismember myset hello4 #返回0 不存在,可以加入scard myset #获取myset元素个数srem myset hello #移除set中的元素helloset 抽取随机元素srandmember mysetspop 随机弹出元素smove myset myset2 "hello"##################################################sdiff set1 set2 #差集sinter set1 set2 #交集,共同好友sunion set1 set2 #并集

hash

 hash(哈希) Map集合hset myhash field1 ahget myhash field1 # 获取字段值hmset myhash field1 a field2 b #同时设置多个hashhgetall myhash #获取全部hashhexists myhash field1 #判断field1是否存在hsetnx myhash field1 hello #不存在才创建hincrby myhash field1 1 #给field+1

Zset 有序的set

 zadd myset 1 onezadd myset 2 twozadd myset 3 three可以排序,比如工资zadd salary 2500 xiaozadd salary 3000 zhangzadd salary 500 dazrevrange myset 0 -1 倒序zrangebyscore salary -inf +inf (负无穷到正无穷)zrevrangebyscore myset 10000 100(倒序)zcount myset 1 10 获取1到10间的成员数量

三种特殊数据类型

geospatial 地理位置

推算两地距离,附近人

 geoadd china:city 纬度 经度 城市geoadd china:city 116.397128 39.916527 beijinggeoadd china:city 121.48941 31.40527 shanghaigeoadd china:city 106.54041 29.40268 chongqinggeoadd china:city 106.54041 29.40268 chongqing#java可以批量导入地理数据geopos china:city beijing #查询地理位置两人之间的距离geodist  m:米km:千米mi:英里ft:英尺geodist china:city beijing chongqing km #km设置单位附近的人,先获得定位,通过半径查询.georadius georadius china:city 110 30 1000 km #查询经度110 纬度30范围1000km之内的城市georadius china:city 110 30 1000 km withdist#显示指定位置指定距离内城市与其距离georadius china:city 110 30 1000 km withcoord#显示位置的指定范围的城市的定位信息georadius china:city 110 30 1000 km withdist withcoord count 2 #筛选出两个指定的结果,包含距离和定位信息georadiusbymember china:city beijing 1500 km#找出指定元素范围内的元素名称geahash字符串属性,将二维经纬度转为一维的字符串geohash china:city beijing "wx4g0dtf9e0"  `底层是zset,所以可以通过zet进行操作,比如移除元素等` zrange china:city 0 -1 #查询所有元素 zrem china:city beijing #移除北京这个元素  

Hyperloglog:基数统计的算法

基数:不重复的元素

A{1,3,5,6,5}==>A{1,3,5,6}

简介

网站的UV(一个人访问多次算一个人)

优点:只需要12kb内存.2^64个元素,错误率低 0.81%,统计UV合适

 pfadd my a b c d e c d s c  v d a s a #添加元素pfcount my #统计不同元素数量 7pfadd me c d c s a x s c z #添加第二组pfmerge new my me #合并my和me成new.pfcount new #统计出new的基数数量pfadd x 逐个添加时,重复的会添加失败

Bitmaps

位存储

统计用户信息,活跃,不活跃,登录,未登录,打卡.只有两个状态就可以使用

 127.0.0.1:6379> setbit sign 0 1(integer) 0127.0.0.1:6379> setbit sign 1 0(integer) 0127.0.0.1:6379> setbit sign 2 1(integer) 0127.0.0.1:6379> setbit sign 3 1(integer) 0127.0.0.1:6379> setbit sign 4 1(integer) 0127.0.0.1:6379> setbit sign 5 0(integer) 0127.0.0.1:6379> setbit sign 6 1(integer) 0七天sign的设置情况查看某一天的bit值getbit sign 50#统计这周打卡记录bitcount sign

事务(伪事务)

redis单条命令保证原子性,

但是事务不保证原子性

redis 没有隔离级别的概念

开启事务

命令入列

执行事务(exec)

乐观锁

监视器watch

 127.0.0.1:6379> multi #开启事务OK127.0.0.1:6379> set k1 v1 #命令入队QUEUED127.0.0.1:6379> set k2 v2 #命令入队QUEUED127.0.0.1:6379> set k3 v3 #命令入队QUEUED127.0.0.1:6379> get k1 #命令入队QUEUED127.0.0.1:6379> exec #执行1) OK2) OK3) OK4) "v1"

放弃事务: discard

编译型异常,所有代码都不会执行

运行时异常,错误命令异常,其他命令正常执行

监控

悲观锁:

乐观锁:

redis监控测试

 127.0.0.1:6379> set money 100OK127.0.0.1:6379> set out 0OK127.0.0.1:6379> watch moneyOK127.0.0.1:6379> multiOK127.0.0.1:6379> decrby money 20QUEUED127.0.0.1:6379> incrby out 20QUEUED127.0.0.1:6379> exec1) (integer) 802) (integer) 20#使用watch可以当乐观锁操作,watch后如果冲突会执行失败失败后,再watch再开启事务再命令入列执行

Jedis

Java操作redis的中间件

新建java springboot项目,导入jedis,fastjson

 @Test    void test() {        Jedis jedis = new Jedis("127.0.0.1", 6379);        jedis.set("name", "fuckyou");        System.out.println("清空数据: "+jedis . flushDB());        System.out.println("判断某个键是否存在: " + jedis.exists("username"));        System.out.println("新增< 'username', ' user'>的键值对: " + jedis.set("username", "ku"));        System.out.println("新增的键值对: " + jedis.set("password", "pas"));                                        System. out. print("系统中所有的键如下: ");        Set<String> keys = jedis. keys( "*");        System. out . println(keys);        System . out . println( "删除键password: "+jedis . del(  "password"));        System. out . println( "判断键password是否存在: "+jedis. exists(  "password"));        System . out . println( "查看键username所存储的值的类型: "+jedis. type(  "username"));        System. out . println( "随机返回key空间的一个: "+jedis . randomKey());        System . out . println("重命名 "+jedis . rename( "username", "name" ));        System . out. println( "取出改后的name: "+jedis. get("name"));        System. out. println("按索引查询: "+jedis. select(  0));        System. out . println( "删除当前选择数据库中的所有key: "+jedis . flushDB());        System. out . println("返回当前数据库中key的数目: "+jedis. dbSize());        System. out . println("删除所有数据库中的所有key: "+jedis.flushAll());}

事务:

     @Test    void test() {        Jedis jedis = new Jedis("127.0.0.1", 6379);        Transaction multi = jedis.multi();        JSONObject object = new JSONObject();        object.put("k1", "v1");        object.put("k2", "v2");        String toJSONString = object.toJSONString();        try {            multi.set("user1", toJSONString);            multi.exec();//执行事务        } catch (Exception e) {            multi.discard();//放弃事务            e.printStackTrace();        }finally {            System.out.println(jedis.get("user1"));            jedis.close();//最后关闭连接        }}

springboot操作

pom.xml引入包 spring-boot-starter-data-redis

新建项目界面nosql中的第一个redis

jedis已经不使用了,直连不安全,BIO模式

用的lettuce,采用netty,多线程中进行共享,减少线程数据.NIO模式

即可知道redis相关配置

 @Configuration(proxyBeanMethods = false)@ConditionalOnClass(RedisOperations.class)@EnableConfigurationProperties(RedisProperties.class)@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })public class RedisAutoConfiguration {    @Bean    @ConditionalOnMissingBean(name = "redisTemplate")    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory)            throws UnknownHostException {        RedisTemplate<Object, Object> template = new RedisTemplate<>();        template.setConnectionFactory(redisConnectionFactory);        return template;}    @Bean    @ConditionalOnMissingBean    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory)            throws UnknownHostException {        StringRedisTemplate template = new StringRedisTemplate();        template.setConnectionFactory(redisConnectionFactory);        return template;}}
 #spring.redis.host=127.0.0.1#spring.redis.port=6379#spring.redis.lettuce.pool.max-active=8#等等..默认lettuce.基本不需要自己配置
 @SpringBootTestclass DemoApplicationTests {  @Autowired  private RedisTemplate redisTemplate;    @Test  void contextLoads() {  }    @Test  void Test() {    redisTemplate.opsForValue().set("k1", "v1");    redisTemplate.opsForList().leftPush("k2", "v2");    List k2 = redisTemplate.opsForList().range("k2", 0, -1);    System.out.println(k2);    redisTemplate.opsForSet();    redisTemplate.opsForHash();    redisTemplate.opsForZSet();    redisTemplate.opsForGeo();    redisTemplate.opsForHyperLogLog();      }  }
 //关键代码: @Autowiredprivate RedisTemplate redisTemplate;//接着使用即可redisTemplate.opsForValue().set("k1", "v1");//操作stringredisTemplate.opsForList().leftPush("k2", "v2");//操作listList k2 = redisTemplate.opsForList().range("k2", 0, -1);System.out.println(k2);redisTemplate.opsForSet();//操作setredisTemplate.opsForHash();//操作hashredisTemplate.opsForZSet();//操作zsetredisTemplate.opsForGeo();//操作georedisTemplate.opsForHyperLogLog();//操作基数

删除数据需要另外获取连接

     RedisConnection connection = redisTemplate.getConnectionFactory().getConnection();    connection.flushAll();//删除所有数据    connection.flushDb();//删除数据
 如果不进行对象序列号,会报错,需要自己执行序列号操作   ` class User`@Component//方便直接调用@Data@AllArgsConstructor@NoArgsConstructorpublic class User {  private String name;  private Integer age;  }` Test `          @Test  void Test() throws JsonProcessingException {    User user = new User("哈哈", 10);    String s = new ObjectMapper().writeValueAsString(user);//不序列号不行,所有可以在pojo里面对象直接序列号    redisTemplate.opsForValue().set("user", s);      Object user1 = redisTemplate.opsForValue().get("user");    System.out.println(user1);    }  

因此,直接创建对象的时候序列号,就不会报错

 @Component//方便直接调用@Data@AllArgsConstructor@NoArgsConstructorpublic class User implements Serializable {private String name;private Integer age;}
 @Testvoid Test() throws JsonProcessingException {User user = new User("哈哈", 10);//    String s = new ObjectMapper().writeValueAsString(user);//不序列号不行,所有可以在pojo里面对象直接序列号redisTemplate.opsForValue().set("user", user);Object user1 = redisTemplate.opsForValue().get("user");System.out.println(user1);}

自己的redisTemplate配置

 @Configurationpublic class RedisConfig {    @Bean  @SuppressWarnings("all")  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {    RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();    template.setConnectionFactory(factory);    Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);    ObjectMapper om = new ObjectMapper();    om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);    om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);    jackson2JsonRedisSerializer.setObjectMapper(om);    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();    // key采用String的序列化方式    template.setKeySerializer(stringRedisSerializer);    // hash的key也采用String的序列化方式    template.setHashKeySerializer(stringRedisSerializer);    // value序列化方式采用jackson    template.setValueSerializer(jackson2JsonRedisSerializer);    // hash的value序列化方式采用jackson    template.setHashValueSerializer(jackson2JsonRedisSerializer);    template.afterPropertiesSet();    return template;  }}

redisUtil 工具类

  import org.springframework.beans.factory.annotation.Autowired;import org.springframework.data.redis.core.RedisTemplate;import org.springframework.stereotype.Component;import org.springframework.util.CollectionUtils; import java.util.List;import java.util.Map;import java.util.Set;import java.util.concurrent.TimeUnit; /** * Redis工具类 * * @author zhangzhixiang * @date 2019年06月19日 */@Componentpublic final class RedisUtil {     @Autowired    private RedisTemplate<String, Object> redisTemplate;     // =============================common============================    /**     * 指定缓存失效时间     *     * @param key  键     * @param time 时间(秒)     * @return     */    public boolean expire(String key, long time) {        try {            if (time > 0) {                redisTemplate.expire(key, time, TimeUnit.SECONDS);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 根据key 获取过期时间     *     * @param key 键 不能为null     * @return 时间(秒) 返回0代表为永久有效     */    public long getExpire(String key) {        return redisTemplate.getExpire(key, TimeUnit.SECONDS);    }     /**     * 判断key是否存在     *     * @param key 键     * @return true 存在 false不存在     */    public boolean hasKey(String key) {        try {            return redisTemplate.hasKey(key);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 删除缓存     *     * @param key 可以传一个值 或多个     */    @SuppressWarnings("unchecked")    public void del(String... key) {        if (key != null && key.length > 0) {            if (key.length == 1) {                redisTemplate.delete(key[0]);            } else {                redisTemplate.delete(CollectionUtils.arrayToList(key));            }        }    }    // ============================String=============================     /**     * 普通缓存获取     *     * @param key 键     * @return 值     */    public Object get(String key) {        return key == null ? null : redisTemplate.opsForValue().get(key);    }     /**     * 普通缓存放入     *     * @param key   键     * @param value 值     * @return true成功 false失败     */    public boolean set(String key, Object value) {        try {            redisTemplate.opsForValue().set(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 普通缓存放入并设置时间     *     * @param key   键     * @param value 值     * @param time  时间(秒) time要大于0 如果time小于等于0 将设置无限期     * @return true成功 false 失败     */    public boolean set(String key, Object value, long time) {        try {            if (time > 0) {                redisTemplate.opsForValue().set(key, value, time, TimeUnit.SECONDS);            } else {                set(key, value);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 递增     *     * @param key   键     * @param delta 要增加几(大于0)     * @return     */    public long incr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("递增因子必须大于0");        }        return redisTemplate.opsForValue().increment(key, delta);    }     /**     * 递减     *     * @param key   键     * @param delta 要减少几(小于0)     * @return     */    public long decr(String key, long delta) {        if (delta < 0) {            throw new RuntimeException("递减因子必须大于0");        }        return redisTemplate.opsForValue().increment(key, -delta);    }    // ================================Map=================================     /**     * HashGet     *     * @param key  键 不能为null     * @param item 项 不能为null     * @return 值     */    public Object hget(String key, String item) {        return redisTemplate.opsForHash().get(key, item);    }     /**     * 获取hashKey对应的所有键值     *     * @param key 键     * @return 对应的多个键值     */    public Map<Object, Object> hmget(String key) {        return redisTemplate.opsForHash().entries(key);    }     /**     * HashSet     *     * @param key 键     * @param map 对应多个键值     * @return true 成功 false 失败     */    public boolean hmset(String key, Map<String, Object> map) {        try {            redisTemplate.opsForHash().putAll(key, map);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * HashSet 并设置时间     *     * @param key  键     * @param map  对应多个键值     * @param time 时间(秒)     * @return true成功 false失败     */    public boolean hmset(String key, Map<String, Object> map, long time) {        try {            redisTemplate.opsForHash().putAll(key, map);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 向一张hash表中放入数据,如果不存在将创建     *     * @param key   键     * @param item  项     * @param value 值     * @return true 成功 false失败     */    public boolean hset(String key, String item, Object value) {        try {            redisTemplate.opsForHash().put(key, item, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 向一张hash表中放入数据,如果不存在将创建     *     * @param key   键     * @param item  项     * @param value 值     * @param time  时间(秒) 注意:如果已存在的hash表有时间,这里将会替换原有的时间     * @return true 成功 false失败     */    public boolean hset(String key, String item, Object value, long time) {        try {            redisTemplate.opsForHash().put(key, item, value);            if (time > 0) {                expire(key, time);            }            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 删除hash表中的值     *     * @param key  键 不能为null     * @param item 项 可以使多个 不能为null     */    public void hdel(String key, Object... item) {        redisTemplate.opsForHash().delete(key, item);    }     /**     * 判断hash表中是否有该项的值     *     * @param key  键 不能为null     * @param item 项 不能为null     * @return true 存在 false不存在     */    public boolean hHasKey(String key, String item) {        return redisTemplate.opsForHash().hasKey(key, item);    }     /**     * hash递增 如果不存在,就会创建一个 并把新增后的值返回     *     * @param key  键     * @param item 项     * @param by   要增加几(大于0)     * @return     */    public double hincr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, by);    }     /**     * hash递减     *     * @param key  键     * @param item 项     * @param by   要减少记(小于0)     * @return     */    public double hdecr(String key, String item, double by) {        return redisTemplate.opsForHash().increment(key, item, -by);    }    // ============================set=============================     /**     * 根据key获取Set中的所有值     *     * @param key 键     * @return     */    public Set<Object> sGet(String key) {        try {            return redisTemplate.opsForSet().members(key);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }     /**     * 根据value从一个set中查询,是否存在     *     * @param key   键     * @param value 值     * @return true 存在 false不存在     */    public boolean sHasKey(String key, Object value) {        try {            return redisTemplate.opsForSet().isMember(key, value);        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 将数据放入set缓存     *     * @param key    键     * @param values 值 可以是多个     * @return 成功个数     */    public long sSet(String key, Object... values) {        try {            return redisTemplate.opsForSet().add(key, values);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }     /**     * 将set数据放入缓存     *     * @param key    键     * @param time   时间(秒)     * @param values 值 可以是多个     * @return 成功个数     */    public long sSetAndTime(String key, long time, Object... values) {        try {            Long count = redisTemplate.opsForSet().add(key, values);            if (time > 0)                expire(key, time);            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }     /**     * 获取set缓存的长度     *     * @param key 键     * @return     */    public long sGetSetSize(String key) {        try {            return redisTemplate.opsForSet().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }     /**     * 移除值为value的     *     * @param key    键     * @param values 值 可以是多个     * @return 移除的个数     */    public long setRemove(String key, Object... values) {        try {            Long count = redisTemplate.opsForSet().remove(key, values);            return count;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }    // ===============================list=================================     /**     * 获取list缓存的内容     *     * @param key   键     * @param start 开始     * @param end   结束 0 到 -1代表所有值     * @return     */    public List<Object> lGet(String key, long start, long end) {        try {            return redisTemplate.opsForList().range(key, start, end);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }     /**     * 获取list缓存的长度     *     * @param key 键     * @return     */    public long lGetListSize(String key) {        try {            return redisTemplate.opsForList().size(key);        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }     /**     * 通过索引 获取list中的值     *     * @param key   键     * @param index 索引 index>=0时, 0 表头,1 第二个元素,依次类推;index<0时,-1,表尾,-2倒数第二个元素,依次类推     * @return     */    public Object lGetIndex(String key, long index) {        try {            return redisTemplate.opsForList().index(key, index);        } catch (Exception e) {            e.printStackTrace();            return null;        }    }     /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @return     */    public boolean lSet(String key, Object value) {        try {            redisTemplate.opsForList().rightPush(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @param time  时间(秒)     * @return     */    public boolean lSet(String key, Object value, long time) {        try {            redisTemplate.opsForList().rightPush(key, value);            if (time > 0)                expire(key, time);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @return     */    public boolean lSet(String key, List<Object> value) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 将list放入缓存     *     * @param key   键     * @param value 值     * @param time  时间(秒)     * @return     */    public boolean lSet(String key, List<Object> value, long time) {        try {            redisTemplate.opsForList().rightPushAll(key, value);            if (time > 0)                expire(key, time);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 根据索引修改list中的某条数据     *     * @param key   键     * @param index 索引     * @param value 值     * @return     */    public boolean lUpdateIndex(String key, long index, Object value) {        try {            redisTemplate.opsForList().set(key, index, value);            return true;        } catch (Exception e) {            e.printStackTrace();            return false;        }    }     /**     * 移除N个值为value     *     * @param key   键     * @param count 移除多少个     * @param value 值     * @return 移除的个数     */    public long lRemove(String key, long count, Object value) {        try {            Long remove = redisTemplate.opsForList().remove(key, count, value);            return remove;        } catch (Exception e) {            e.printStackTrace();            return 0;        }    }}

测试

 @SpringBootTestclass DemoApplicationTests {    @Autowired  private RedisUtil redisUtil;    @Test  void contextLoads() {  }    @Test  void Test() throws JsonProcessingException {    User user = new User("哈哈", 10);    redisUtil.set("user1", user);    Object user1 = redisUtil.get("user1");    System.out.println(user1);    }  }

redis.conf

 locate redis.confcd ..到目录vim redis.conf
网络
 bind 127.0.0.1protected-mode yesport 6379daemonize yes #守护进程方式运行,如果是no需改为yesloglevel notice #日志logfile "/www/server/redis/redis.log"databases 16 #默认16个数据库always-show-logo yes #显示logo#   save ""  持久化规则save 900 1 #900内,有一个key进行修改,进行持久化save 300 10 #300秒内,10个key进行修改就持久化save 60 10000 #60秒内10000次修改则持久化stop-writes-on-bgsave-error yes #持久化错误后默认继续工作rdbcompression yes #是否压缩rdbchecksum yes #保存rdb时候进行校验dbfilename dump.rdbdir /www/server/redis/ #rdb保存文件目录################ REPLICATION ####################主从复制########## SECURITY #############可以设置密码config get requirepass 获取密码>requirepass 123456 #如果在### SECURITY #####加上这句,就会设置密码或者直接命令设置:config set requirepass "123456"这样下次需要先`auth 123456` 才可以继续操作############## CLIENTS ################## maxclients 10000  #最大客户数# maxmemory-policy noeviction #内存策略
 ################ APPEND ONLY MODE #############AOF配置appendonly no #默认不开启,默认rdb持久化,大部分时间够用了appendfilename "appendonly.aof" #持久化文件名字save 保存配置文件设置

Redis持久化

RDB==> dump.rdb

locate dump.rdb 定位dump.rdb

执行flushall,退出redis都会产生rdb文件

如果需要恢复rdb,则定位dir,后续待补充

 127.0.0.1:6379> config get dir1) "dir"2) "/www/server/redis"

AOF如果有错位,redis无法启动,需要修复这个文件

redis-check-aof --fix appendonly.aof

Redis发布订阅

 subscribe channel #订阅频道publish channel "hello" #发送消息到频道

*Redis主从复制

主从复制,读写分离,主写从读

一主二从,集群至少需要三台服务器

默认都是主,变成从需要配置

info replication 查看信息

如何设置为从机

slaveof 127.0.0.1 6379

slaveof ip port认主机为老大

masterauth password验证主机密码

slave no one自己当主机,手动的

如何解决主从设置失败

 redis问题解决:Error condition on socket for SYNC: No route to host第一种方案:1.telnet ip port 是否通2.使用netstat -tnlp 查询IP地址是否为0.0.0.0(127.0.0.1代表只能本机使用)3.修改master中redis.conf中bind绑定0.0.0.02.重启master服务如果第一种方案行不通,那就使用第二种方案;第二种方案:1.关闭防火墙:service iptables stop2.如果出现以下异常Redirecting to /bin/systemctl stop iptables.serviceFailed to stop iptables.service: Unit iptables.service not loaded.(其他异常也可以试下)3.进入/etc/sysconfig/目录下查询有没有iptables文件4.如果没有,使用systemctl stop firewalld 关闭防火墙5.使用yum install iptables-services 安装或者更新服务6.service iptables stop尝试下关闭服务器7.关闭成功无异常,重启maste和slave,进入redis-cli 输入info就能看到maste和slave信息了

出现了哨兵模式.就自动了

哨兵模式 sentinel

(自动选举主机)

7298026c06cba40d51e88493d734659d.png

真正实施需要六个进程:三个哨兵互相监督.

133fb6a190b0b595457014592015bd66.png

 # 禁止保护模式protected-mode no# 配置监听的主服务器,这里sentinel monitor代表监控,mymaster代表服务器的名称,可以自定义,192.168.11.128代表监控的主服务器,6379代表端口,1代表只有两个或两个以上的哨兵认为主服务器不可用的时候,才会进行failover操作。sentinel monitor mymaster 192.168.81.83 6379 1# sentinel author-pass定义服务的密码,mymaster是服务名称,123456是Redis服务器密码# sentinel auth-pass sentinel auth-pass mymaster 123456

启动哨兵模式:与启动redis类似

/www/server/redis/src/redis-sentinel /www/server/redis/sentinel.conf

Redis 缓存穿透和雪崩

缓存穿透(查不到):使用布隆过滤器
缓存击穿(量太大)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值