本文共 12250 字,大约阅读时间需要 40 分钟。
1.安装
下载安装包
课前资料提供的安装包,或者: 建议上传到我们的home下:/usr/local/leyou解压
tar -xvf redis-4.0.9.tar.gz
mv redis-4.0.9 redis cd redis make && make install
2.配置
修改安装目录下的redis.conf文件
vim redis.conf
修改以下配置:
#bind 127.0.0.1 # 将这行代码注释,监听所有的ip地址,外网可以访问protected-mode no # 把yes改成no,允许外网访问daemonize yes # 把no改成yes,后台运行
3.启动或停止
redis提供了服务端命令和客户端命令:
4.设置开机启动
vim /etc/init.d/redis
输入下面内容:
#!/bin/sh# chkconfig: 2345 90 10# description: Redis is a persistent key-value databasePATH=/usr/local/bin:/sbin:/usr/bin:/binREDISPORT=6379EXEC=/usr/local/bin/redis-serverREDIS_CLI=/usr/local/bin/redis-cliPIDFILE=/var/run/redis.pidCONF="/usr/local/leyou/redis/redis.conf"case "$1" in start) if [ -f $PIDFILE ] then echo "$PIDFILE exists, process is already running or crashed" else echo "Starting Redis server..." $EXEC $CONF fi if [ "$?"="0" ] then echo "Redis is running..." fi ;; stop) if [ ! -f $PIDFILE ] then echo "$PIDFILE does not exist, process is not running" else PID=$(cat $PIDFILE) echo "Stopping ..." $REDIS_CLI -p $REDISPORT SHUTDOWN while [ -x ${PIDFILE} ] do echo "Waiting for Redis to shutdown ..." sleep 1 done echo "Redis stopped" fi ;; restart|force-reload) ${0} stop ${0} start ;; *) echo "Usage: /etc/init.d/redis {start|stop|restart|force-reload}" >&2 exit 1 esac
然后保存退出
注意:以下信息需要根据安装目录进行调整:
EXEC=/usr/local/bin/redis-server # 执行脚本的地址
REDIS_CLI=/usr/local/bin/redis-cli # 客户端执行脚本的地址
PIDFILE=/var/run/redis.pid # 进程id文件地址
CONF="/usr/local/src/redis-3.0.2/redis.conf" #配置文件地址
2)设置权限
chmod 755 /etc/init.d/redis
3)启动测试
/etc/init.d/redis start
启动成功会提示如下信息:
Starting Redis server...Redis is running...
4)设置开机自启动
chkconfig --add /etc/init.d/redischkconfig redis on
redis-server /opt/myredis/redis.confredis-cli
都只能是字符串
keys * 查看当前库的所有键
exists < key> 判断某个键是否存在 type < key> 查看键的类型 del < key> 删除某个键 expire < key> < seconds> 为键值设置过期时间,单位秒 ttl < key> 查看还有多久过期,-1表示永不过期,-2表示已过期 dbsize 查看当前数据库中key的数量 flushdb 清空当前库 Flushall 通杀全部库String类型是二进制安全的。意味着Redis的string可以包含任何数据。比如jpg图片或者序列化的对象 。
String类型是Redis最基本的数据类型,一个Redis中字符串value最多可以是512M
get 查询对应键值
set 添加键值对 append 将给定的追加到原值的末尾 strlen 获取值的长度 senx 只有在key 不存在时设置key的值 incr 将key中存储的数字值增1 只能对数字值操作,如果为空,新增值为1 decr 将key中存储的数字值减1 只能对数字之操作,如果为空,新增值为-1 incrby /decrby 步长 将key中存储的数字值增减,自定义步长 所谓原子操作是指不会被线程调度机制打断的操作;这种操作一旦开始,就一直运行到结束,中间不会有任何 context switch (切换到另一个线程)。
在单线程中, 能够在单条指令中完成的操作都可以认为是" 原子操作",因为中断只能发生于指令之间。 在多线程中,不能被其它进程(线程)打断的操作就叫原子操作。 Redis单命令的原子性主要得益于Redis的单线程 思考:java中i++是否是原子操作它的底层实际是个双向链表,对两端的操作性能很高,通过索引下标的操作中间的节点性能会较差
lpush/rpush < key> < value1> < value2> 从左边/右边插入一个或多个值。
lpop/rpop < key> 从左边/右边吐出一个值。 值在键在,值光键亡。 rpoplpush < key1> < key2> 从< key1>列表右边吐出一个值,插到< key2>列表左边 lrange < key> < start> < stop> 按照索引下标获得元素(从左到右) lindex < key> < index> 按照索引下标获得元素(从左到右) llen < key> 获得列表长度 linsert < key> before < value> < newvalue> 在< value>的后面插入< newvalue> 插入值 lrem < key> < value> 从左边删除n个value(从左到右)sadd … 将一个或多个 member 元素加入到集合 key 当中,已经存在于集合的 member 元素将被忽略。
smembers 取出该集合的所有值。 sismember 判断集合是否为含有该值,有返回1,没有返回0 scard 返回该集合的元素个数。 srem … 删除集合中的某个元素。 spop 随机从该集合中吐出一个值。 srandmember 随机从该集合中取出n个值。 不会从集合中删除 sinter 返回两个集合的交集元素。 sunion 返回两个集合的并集元素。 sdiff 返回两个集合的差集元素。以元素为键(key),以分数为值
如何利用zset实现一个文章访问量的排行榜
docker run -p 6379:6379 -v /zzyyuse/myredis/data:/data -v /zzyyuse/myredis/conf/redis.conf:/usr/local/etc/redis/redis.conf -d redis:3.2 redis-server /usr/local/etc/redis/redis.conf --appendonly yes启动:docker run -p 6379:6379 -d redis:3.2 redis-server docker exec -it CONTAINER_ID redis-cli
public static void main(String[] args) { //连接本地的 Redis 服务 Jedis jedis = new Jedis("127.0.0.1",6379); //查看服务是否运行,打出pong表示OK System.out.println("connection is OK=======>:"+jedis.ping()); }}
不同于关系型数据库
Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断 Redis事务的主要作用就是串联多个命令防止别的命令插队秒杀案例
关系型数据库都是悲观锁:加锁,一次事务结束开锁,下一个事务开始加锁
nosql都是乐观锁:比较版本悲观锁(Pessimistic Lock), 顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以**每次在拿数据的时候都会上锁,这样别人想拿这个数据就会block直到它拿到锁。**传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁
乐观锁(Optimistic Lock), 顾名思义,就是很乐观,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号等机制。乐观锁适用于多读的应用类型,这样可以提高吞吐量。Redis就是利用这种check-and-set机制实现事务的。
秒杀并发模拟 ab工具
3) 遗留问题超卖问题
持久化:把数据存到磁盘上
Redis是把数据存在内存中 Redis提供了2个不同形式的持久化方式 RDB 和 AOF快照:恢复数据
RDB:Redis 关系数据库存储的是数据 主要是更改配置1)触发机制
手动触发(一般不用)触发持久化:1.满足保存策略2.正常shutdown
一定要压缩文件太大AOF:(append only file)存储的是指令
以日志的形式来记录每个写操作 优点:
备份机制更稳健,丢失数据概率更低。 可读的日志文本,通过操作AOF稳健,可以处理误操作。 缺点: 比起RDB占用更多的磁盘空间 恢复备份速度要慢 每次读写都同步的话,有一定的性能压力。 官方推荐两个都启用。
如果对数据不敏感,可以选单独用RDB 不建议单独用 AOF,因为可能会出现Bug。 如果只是做纯内存缓存,可以都不用 … … AOF和RDB同时开启,redis听AOF主从复制,就是主机数据更新后根据配置和策略,自动同步到备机的master/slaver机制,Master以写为主,Slave以读为主。
vim 替换:%s/6379/6380
能 切入点问题?slave1、slave2是从头开始复制还是从切入点开始复制?比如从k4进来,那之前的123是否也可以复制只读 从机是否可以写?set可否?原地待命 都down 主机shutdown后情况如何?从机是上位还是原地待命能 主机又回来了后,主机新增记录,从机还能否顺利复制能 其中一台从机down后情况如何?依照原有它能跟上大部队吗?
上面的只是在命令行操作不是永久的,需要在配置文件:slaveof 配置
从二: slaveof ip port从一
sentinel 哨兵 宿管大妈监视出入人员
阻塞 i/o | 非阻塞 |
---|---|
给女神发信息后等女神下楼 | 一直给女神发信息并等下楼 |
问题
* Redis 是一个开源(BSD许可)的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息中间件。 * 1、安装redis:使用docker; docker run -d -p 6379:6379 --name myredis redis * 2、引入redis的starter * 3、配置redis spring.redis.host=192.168.100.246 * 4、测试缓存 * 原理:CacheManager===Cache 缓存组件来实际给缓存中存取数据 * 1)、引入redis的starter,容器中保存的是 RedisCacheManager; * 2)、RedisCacheManager 帮我们创建 RedisCache 来作为缓存组件;RedisCache通过操作redis缓存数据的 * 3)、默认保存数据 k-v 都是Object;利用序列化保存;如何保存为json * 1、引入了redis的starter,cacheManager变为 RedisCacheManager; * 2、默认创建的 RedisCacheManager 操作redis的时候使用的是 RedisTemplate
@EnableCaching // 开启缓存
引入redis的starter,配置redisspring.redis.host=192.168.100.246
org.springframework.boot spring-boot-starter-redis
创建RedisConfig的配置类
// 1.项目启动时此方法先被注册成bean被spring管理,如果没有这个bean,则redis可视化工具中的中文内容(key或者value)都会以二进制存储,不易检查。 @Bean public RedisTemplateempRedisTemplate( RedisConnectionFactory redisConnectionFactory) throws UnknownHostException { RedisTemplate template = new RedisTemplate (); template.setConnectionFactory(redisConnectionFactory); Jackson2JsonRedisSerializer ser = new Jackson2JsonRedisSerializer (Department.class); template.setDefaultSerializer(ser); return template; } //CacheManagerCustomizers可以来定制缓存的一些规则 @Primary //将某个缓存管理器作为默认的 @Bean public RedisCacheManager employeeCacheManager(RedisTemplate empRedisTemplate){ RedisCacheManager cacheManager = new RedisCacheManager(empRedisTemplate); //key多了一个前缀 //使用前缀,默认会将CacheName作为key的前缀 cacheManager.setUsePrefix(true); return cacheManager; }
Service中操作缓存
@Qualifier("employeeCacheManager") @Autowired RedisCacheManager employeeCacheManager; //注解方式 @Cacheable(cacheNames = "dept",cacheManager = "employeeCacheManager") public Department getDeptById(Integer id){ System.out.println("查询部门"+id); return departmentMapper.getDeptById(id); } ------------------------------------------- // 使用缓存管理器得到缓存,进行api调用 public Department getDeptById(Integer id){ System.out.println("查询部门"+id); Department department = departmentMapper.getDeptById(id); //获取某个缓存 Cache dept = employeeCacheManager.getCache("dept"); dept.put("dept:1",department); return department; }
转载地址:http://yvxab.baihongyu.com/