markdown Redis的
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了markdown Redis的相关的知识,希望对你有一定的参考价值。
# REDIS
* REmote DIctionary Server
1. key/value _store_
2. Built-in support for data structures like hashes
3. Performs well as a _cache store_ and a full-fledged NoSQL data store
## Installing Redis
* `brew install redis` on OSX
* To have launchd start redis now and restart at login: `brew services start redis`
* If you don't want/need a background service: `redis-server /usr/local/etc/redis.conf` (use!)
* Use in a rails app: `gem install redis`
---
## How does caching work?
* Disk access is expensive!
* Disk access also negatively impacts performance!
* To counter this, implement a caching layer between your application and database server
* Initially, a caching layer **doesn't contain any data at first**!
* When it receives the request for the data, it calls the database and stores the result
in memory
* Later requests won't need to access the database because the data is already stored in
the cache!
---
## Model Caching using Redis
* Create a simple app using scaffold `Snippet content:text`
* In this example, redis will be used to load snippets from Rails rather than using a SQL db.
* For loading a page that contains many records, it may take a very long time to load, Redis can
be used to load the records **drastically faster**
* Once the app is created and migrations are ran, install the following gems:
* `gem 'rack-mini-profiler'`: displays loading time in upper left corner of browser
* `gem 'faker'`: used to fill in dummy data to create records faster
```ruby
#example of using faker in seed.db
100000.times do
Snippet.create(content: Faker::Lorem.paragraph)
end
```
* `bundle install`
* `bundle exec rake db:seed`
* Change root to `snippets#index`
* Run `rails s`
* Notice the loading time of rack-mini-profiler!
---
## Using Redis as a cache store
* Open terminal, in one window run `redis-server`
* Make an alias in your bash_profile: **`redis-server /usr/local/etc/redis.conf`**
* Add the following gems to `Gemfile`:
* `gem 'redis'`
* `gem 'redis-rails'`
* `bundle install`
* In `config/development.rb`, you can instruct Rails to use redis as a cache store: (or even `production.rb`)
```ruby
module nameOfApp
class Application < Rails::Application
config.cache_store = :redis_store, 'redis://localhost:6379/0/cache', {expires_in: 90.minutes}
# redis has 16 databases to choose from (0-15), represents the 0 before cache
# cache represents the namespace
# you can configure host, port and other db:
# Redis.new(:host => '10.0.1.1', :port => 6380, :db => 15)
# Alternatively:
config.cache_store = :redis_store, {
host: 'localhost',
port: 6379,
db: 0,
namespace: 'cache'
}
end
end
```
* Restart your app any time you makes changes to these files!
---
### Application Modifications
* Configuring and setting up redis is now complete!
* Instead of loading records from the SQL database, head in to a controller that loads records:
```ruby
#include the controller helper folder, code will be ran inside there
# example SnippetsController.rb
def index
@data = fetch_snippets
end
#helpers/snippets_helper.rb
module SnippetsHelper
def fetch_snippets
snippets = $redis.get("snippets")
if snippets.nil?
#IMPORTANT:
# the first time around snippets will be nil, redis hasn't put anything in yet
snippets = Snippet.all.to_json
#Now redis is inserting the array of snippets in a hash with key "snippets"
# from the database access, so that next time it can just bypass the db and use its store
$redis.set("snippets", snippets)
#Expire the cache every 5 hours
$redis.expire("snippets", 5.hour.to_i)
end
JSON.load snippets
end
end
#Update the views
<% @data.each do |snippet| %>
<%= snippet["content"] %>
<% end %>
```
* **_Why convert the data received from the db?_** The fastest way to write objects to redis.
* Alternative is to iterate over all the objects and then save them as a hash = SLOW
* Fastest way is to save them as a JSON encoded string, to decode use `JSON.load`
* This alters the returned data so we will need to change the views to access attributes
as a hash (as above)
* Restart server and refresh page to notice the change in loading time!
* If you make a change to a model, redis will wait the amount specified to expire befor
getting fresh data. You can create a `after_save` validation on the model being cached:
```ruby
#example of categories being cached
class Category
after_save: :clear_cache
def clear_cache
$redis.del "categories"
end
end
```
* Now, when a model is updated (and saved to the db) Rails is instructed to clear the cache,
ensuring that the cache is always upto date.
---
## Redis Rails
* in gemfile: `gem 'redis-rails'`
```ruby
# setting a key/value pair
redis.set("key", "value")
# retrieving a value
redis.get("key")
#=> "value"
# in your rails app, view template
<% cache 'word-of-the-hour', :expires_in => Time.now.beginning_of_hour + 1.hour do %>
<%= %w(ruby rails javascript web developer).sample %>
<% end %>
# Every hour, redis will empty the cache and set a new value for the key
```
## Redis (Overview)
* Install Redis [link](http://redis.io)
* After installation run `redis server`
* In a new tab, run `redis-cli`
* You can see the redis url: `127.0.0.1:6379`, default port is 6379
* Simple commands:
```ruby
# set key value
set name parm
# get value from key
get name
# => parm
```
---
## Redis Basics
### Datatypes
* key/value pair
* string
* list (list of ORDERED strings)
* hashes
* set (list of UNORDERED and UNIQUE strings)
### Redis Persistence Options
* Data is saved in memory for fast access!
* Two options:
* **AOF** (Append-only File): logs every operation in the system file. If the log gets too
large, Redis will be able to shrink it down to only the latest version of the file.
* **RDB** (Redis Database File): creates a snapshot, creating copies of moments in time.
(Default)
* Configuring which option to use:
* `cd` in to the directory where you downloaded redis
* Open `redis.config`, find section for `Snapshotting`, read the info on how to configure
the snapshot after x sec with atleast x amount of changes
* Find section for `appendonly` and change `no` to `yes`
* Save & close, copy the path to the file
* Restart the server and this time append the path to it:
`redis-server /usr/local/etc/redis.conf`
### Replication
* Copy and rename the above file as `redis2.conf`
* change the port number to `3780`
* find `slaveof` and replace with: `slaveof 127.0.0.1 6379`, _slave of `redis.config`_
* Open a new tab and start another server with the `redis2.conf` file
* Should notice `master-slave relation has started`
### Security
* Open both `.conf` files
* find `requirepass enterpass`, replace `enterpass` with a password, make sure slave is updated
with the same password in the location of `masterauth`
* restart both servers for each to take effect!
* In order to use the cli, enter the following: `redis-cli -a password`, entering the password
that was set in the `.conf` file.
### Datasets using Keys
```ruby
set address 435
incr address #increment by 1
# => 436
incrby address 100 #increment by x
#decrement
decr address
decrby address
# For multiple words for a value, USE DOUBLE QUOTES!!
set country "North America"
#getset is used to get a key and then set it, returns original key
getset firstName "Parm"
#set multiple values:
mset street blah city blah2 state blah3 zip "blah4"
#retrieve those values:
mget street city state zip
#check if something exists:
exists street
# returns 1 for yes it exists, 0 else
#delete a key
del street
#expire a key in x sec
exp city 5
#set and expires
set zip "989-899989" ex 9
```
### Hash
```ruby
#creating a hash:
hmset nameofhash key1 value1 key2 value2 ...
#retrieve the hash:
hgetall nameofhash
#retrieve a certain value in the hash:
hget nameofhash key1
#retrieve multiple values
hmget nameofhash key1 key2
#exist?
hexist nameofhash key1
#set another key
hmset nameofhash keyx valuex
#increment
hincrby nameofhash key numtoincrementby
```
### Lists
```ruby
#creates a new list (right push appends to bottom of list)
rpush nameoflist value1 value2 value3 ...
#list the list
lrange nameoflist startindex stopindex
#startindex is usually 0!
# -1 all
# -2 all except the last one
# -3 all except the last 2
#append to the BEGINNING of a list (left push)
lpush nameoflist valuex
#remove (left pop)
lpop nameoflist
#right pop (removes at the end of the list)
rpop nameoflist
#trimming a list
ltrim nameoflist starti stopi
#ex ltrim grocery 0 2
# lrange 0 -1 to see the new list
```
### Sets
```ruby
#creating a set
sadd nameofset value1 value2 value3 value4
#retrieve set
smembers name
#add more values
sadd valuex valauey
#is there?
sismember nameofset value
#returns 0 no, 1 yes
#creating a subset
sadd nameofset:value value_1 value_2 value_3 ...
#retrieve subset
smembers nameofset:value
#creating a new value that has the same sublist as another value
sunionstore nameofset:newvalue nameofset:existingvalue
#remove the last value from the subset
spop nameofset:value
#count of how many values
scard nameofset
```
### Sorted Sets
```ruby
#creating a sorted set, helps if keys are integers
zadd nameofset key1 value1 key2 value2 key3 value3 ...
#listing the set
zrange nameofset starti endi
# 0 start, -1 end
# return just the values, to return with key AND values:
zrange nameofset 0 -1 withscores #again 0 is starti and -1 is endi
#reverse the set
zrevrange nameofset starti endi withscores
#get upto a certain range of key
zrangebyscore nameofset -inf integer withscores
#inf = information that will be obtained until the integer value
#retrieve the position of a value
zrank nameofset value
#returns the index or ranking
# IF THEY KEYS ARE NOT INTEGERS, REDIS WOULD SORT THE KEYS ALPHABETICALLY
```
---
### Security with Redis
* open the `config` file and search for security, `requirepass password` is the main way to secure
redis
* Next, ensure that redis port and address is firewalled from unrestriced access!
* Binding redis to a single interface is the standard config and best practice
* Search for `bind` and notice that redis is binded to `127.0.0.1` = 1 interface, which means
we can only access the redis server through that address!
* It is advised to stray away from adding more than one interface to a single redis server!
以上是关于markdown Redis的的主要内容,如果未能解决你的问题,请参考以下文章